diff --git a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs index ab40092b3f..7a05a3da5c 100644 --- a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs +++ b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Beatmaps private TestBeatmapDifficultyCache difficultyCache; - private IBindable starDifficultyBindable; + private IBindable starDifficultyBindable; [BackgroundDependencyLoader] private void load(OsuGameBase osu) @@ -52,7 +52,7 @@ namespace osu.Game.Tests.Beatmaps starDifficultyBindable = difficultyCache.GetBindableDifficulty(importedSet.Beatmaps.First()); }); - AddUntilStep($"star difficulty -> {BASE_STARS}", () => starDifficultyBindable.Value?.Stars == BASE_STARS); + AddUntilStep($"star difficulty -> {BASE_STARS}", () => starDifficultyBindable.Value.Stars == BASE_STARS); } [Test] @@ -67,13 +67,13 @@ namespace osu.Game.Tests.Beatmaps }); AddStep("change selected mod to DT", () => SelectedMods.Value = new[] { dt = new OsuModDoubleTime { SpeedChange = { Value = 1.5 } } }); - AddUntilStep($"star difficulty -> {BASE_STARS + 1.5}", () => starDifficultyBindable.Value?.Stars == BASE_STARS + 1.5); + AddUntilStep($"star difficulty -> {BASE_STARS + 1.5}", () => starDifficultyBindable.Value.Stars == BASE_STARS + 1.5); AddStep("change DT speed to 1.25", () => dt.SpeedChange.Value = 1.25); - AddUntilStep($"star difficulty -> {BASE_STARS + 1.25}", () => starDifficultyBindable.Value?.Stars == BASE_STARS + 1.25); + AddUntilStep($"star difficulty -> {BASE_STARS + 1.25}", () => starDifficultyBindable.Value.Stars == BASE_STARS + 1.25); AddStep("change selected mod to NC", () => SelectedMods.Value = new[] { new OsuModNightcore { SpeedChange = { Value = 1.75 } } }); - AddUntilStep($"star difficulty -> {BASE_STARS + 1.75}", () => starDifficultyBindable.Value?.Stars == BASE_STARS + 1.75); + AddUntilStep($"star difficulty -> {BASE_STARS + 1.75}", () => starDifficultyBindable.Value.Stars == BASE_STARS + 1.75); } [Test] @@ -88,15 +88,15 @@ namespace osu.Game.Tests.Beatmaps }); AddStep("change selected mod to DA", () => SelectedMods.Value = new[] { difficultyAdjust = new OsuModDifficultyAdjust() }); - AddUntilStep($"star difficulty -> {BASE_STARS}", () => starDifficultyBindable.Value?.Stars == BASE_STARS); + AddUntilStep($"star difficulty -> {BASE_STARS}", () => starDifficultyBindable.Value.Stars == BASE_STARS); AddStep("change DA difficulty to 0.5", () => difficultyAdjust.OverallDifficulty.Value = 0.5f); - AddUntilStep($"star difficulty -> {BASE_STARS * 0.5f}", () => starDifficultyBindable.Value?.Stars == BASE_STARS / 2); + AddUntilStep($"star difficulty -> {BASE_STARS * 0.5f}", () => starDifficultyBindable.Value.Stars == BASE_STARS / 2); // hash code of 0 (the value) conflicts with the hash code of null (the initial/default value). // it's important that the mod reference and its underlying bindable references stay the same to demonstrate this failure. AddStep("change DA difficulty to 0", () => difficultyAdjust.OverallDifficulty.Value = 0); - AddUntilStep("star difficulty -> 0", () => starDifficultyBindable.Value?.Stars == 0); + AddUntilStep("star difficulty -> 0", () => starDifficultyBindable.Value.Stars == 0); } [Test] diff --git a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs index ef7b3bf8cc..4ef484cb67 100644 --- a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs +++ b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs @@ -99,8 +99,8 @@ namespace osu.Game.Beatmaps /// The to get the difficulty of. /// An optional which stops updating the star difficulty for the given . /// A delay in milliseconds before performing the - /// A bindable that is updated to contain the star difficulty when it becomes available. Will be null while in an initial calculating state (but not during updates to ruleset and mods if a stale value is already propagated). - public IBindable GetBindableDifficulty(IBeatmapInfo beatmapInfo, CancellationToken cancellationToken = default, int computationDelay = 0) + /// A bindable that is updated to contain the star difficulty when it becomes available. May be an approximation while in an initial calculating state. + public IBindable GetBindableDifficulty(IBeatmapInfo beatmapInfo, CancellationToken cancellationToken = default, int computationDelay = 0) { var bindable = new BindableStarDifficulty(beatmapInfo, cancellationToken) { @@ -346,7 +346,7 @@ namespace osu.Game.Beatmaps } } - private class BindableStarDifficulty : Bindable + private class BindableStarDifficulty : Bindable { public readonly IBeatmapInfo BeatmapInfo; public readonly CancellationToken CancellationToken; diff --git a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs index 3cefa07cfa..1799a35e6d 100644 --- a/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs +++ b/osu.Game/Overlays/Mods/BeatmapAttributesDisplay.cs @@ -54,7 +54,7 @@ namespace osu.Game.Overlays.Mods protected IBindable GameRuleset = null!; private CancellationTokenSource? cancellationSource; - private IBindable starDifficulty = null!; + private IBindable starDifficulty = null!; public ITooltip GetCustomTooltip() => new AdjustedAttributesTooltip(); @@ -134,7 +134,7 @@ namespace osu.Game.Overlays.Mods starDifficulty = difficultyCache.GetBindableDifficulty(BeatmapInfo.Value, (cancellationSource = new CancellationTokenSource()).Token); starDifficulty.BindValueChanged(s => { - starRatingDisplay.Current.Value = s.NewValue ?? default; + starRatingDisplay.Current.Value = s.NewValue; if (!starRatingDisplay.IsPresent) starRatingDisplay.FinishTransforms(true); diff --git a/osu.Game/Screens/OnlinePlay/DailyChallenge/DailyChallengeIntro.cs b/osu.Game/Screens/OnlinePlay/DailyChallenge/DailyChallengeIntro.cs index 3ec9217aa4..075d2af0aa 100644 --- a/osu.Game/Screens/OnlinePlay/DailyChallenge/DailyChallengeIntro.cs +++ b/osu.Game/Screens/OnlinePlay/DailyChallenge/DailyChallengeIntro.cs @@ -51,7 +51,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge private bool animationBegan; - private IBindable starDifficulty = null!; + private IBindable starDifficulty = null!; [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Plum); @@ -316,11 +316,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge }; starDifficulty = difficultyCache.GetBindableDifficulty(beatmap); - starDifficulty.BindValueChanged(star => - { - if (star.NewValue != null) - starRatingDisplay.Current.Value = star.NewValue.Value; - }, true); + starDifficulty.BindValueChanged(star => starRatingDisplay.Current.Value = star.NewValue, true); LoadComponentAsync(new OnlineBeatmapSetCover(beatmap.BeatmapSet as IBeatmapSetOnlineInfo) { diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 66aa3d9cc0..08ea0d0a90 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -4,7 +4,6 @@ #nullable disable using System.Collections.Generic; -using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -55,7 +54,7 @@ namespace osu.Game.Screens.Play this.mods.BindTo(mods); } - private IBindable starDifficulty; + private IBindable starDifficulty; private FillFlowContainer versionFlow; private StarRatingDisplay starRatingDisplay; @@ -191,25 +190,15 @@ namespace osu.Game.Screens.Play { base.LoadComplete(); - if (starDifficulty.Value != null) + starDifficulty.BindValueChanged(d => { - starRatingDisplay.Current.Value = starDifficulty.Value.Value; - starRatingDisplay.Show(); - } - else - starRatingDisplay.Hide(); - - starDifficulty.ValueChanged += d => - { - Debug.Assert(d.NewValue != null); - - starRatingDisplay.Current.Value = d.NewValue.Value; + starRatingDisplay.Current.Value = d.NewValue; versionFlow.AutoSizeDuration = 300; versionFlow.AutoSizeEasing = Easing.OutQuint; starRatingDisplay.FadeIn(300, Easing.InQuint); - }; + }, true); } private partial class MetadataLineLabel : OsuSpriteText diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 5a09780943..79564167f4 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -185,7 +185,7 @@ namespace osu.Game.Screens.Select } private CancellationTokenSource cancellationSource; - private IBindable starDifficulty; + private IBindable starDifficulty; [BackgroundDependencyLoader] private void load(LocalisationManager localisation) @@ -329,7 +329,7 @@ namespace osu.Game.Screens.Select starDifficulty = difficultyCache.GetBindableDifficulty(working.BeatmapInfo, (cancellationSource = new CancellationTokenSource()).Token); starDifficulty.BindValueChanged(s => { - starRatingDisplay.Current.Value = s.NewValue ?? default; + starRatingDisplay.Current.Value = s.NewValue; // Don't roll the counter on initial display (but still allow it to roll on applying mods etc.) if (!starRatingDisplay.IsPresent) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index b4eac5cdac..74f0c714a3 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -91,7 +91,7 @@ namespace osu.Game.Screens.Select.Carousel [Resolved] private BeatmapManager? manager { get; set; } - private IBindable starDifficultyBindable = null!; + private IBindable starDifficultyBindable = null!; private CancellationTokenSource? starDifficultyCancellationSource; public DrawableCarouselBeatmap(CarouselBeatmap panel) @@ -249,9 +249,8 @@ namespace osu.Game.Screens.Select.Carousel starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmapInfo, (starDifficultyCancellationSource = new CancellationTokenSource()).Token, 200); starDifficultyBindable.BindValueChanged(d => { - starCounter.Current = (float)(d.NewValue?.Stars ?? 0); - if (d.NewValue != null) - difficultyIcon.Current.Value = d.NewValue.Value; + starCounter.Current = (float)(d.NewValue.Stars); + difficultyIcon.Current.Value = d.NewValue; }, true); updateKeyCount(); diff --git a/osu.Game/Screens/SelectV2/BeatmapTitleWedge_DifficultyDisplay.cs b/osu.Game/Screens/SelectV2/BeatmapTitleWedge_DifficultyDisplay.cs index 9aaf317cb0..f9b3124a0e 100644 --- a/osu.Game/Screens/SelectV2/BeatmapTitleWedge_DifficultyDisplay.cs +++ b/osu.Game/Screens/SelectV2/BeatmapTitleWedge_DifficultyDisplay.cs @@ -8,13 +8,11 @@ using System.Threading; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; -using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Configuration; @@ -64,9 +62,6 @@ namespace osu.Game.Screens.SelectV2 private OsuHoverContainer mapperLink = null!; private OsuSpriteText mapperText = null!; - internal LocalisableString DisplayedVersion => difficultyText.Text; - internal LocalisableString DisplayedAuthor => mapperText.Text; - private GridContainer ratingAndNameContainer = null!; private DifficultyStatisticsDisplay countStatisticsDisplay = null!; private AdjustableDifficultyStatisticsDisplay difficultyStatisticsDisplay = null!; @@ -227,9 +222,12 @@ namespace osu.Game.Screens.SelectV2 updateDifficultyStatistics(); - settingChangeTracker = new ModSettingChangeTracker(m.NewValue); - settingChangeTracker.SettingChanged += _ => updateDifficultyStatistics(); - }); + if (m.NewValue.Any()) + { + settingChangeTracker = new ModSettingChangeTracker(m.NewValue); + settingChangeTracker.SettingChanged += _ => updateDifficultyStatistics(); + } + }, true); updateDisplay(); } @@ -255,26 +253,12 @@ namespace osu.Game.Screens.SelectV2 mapperText.Text = beatmap.Value.Metadata.Author.Username; } - updateStarDifficulty(cancellationSource.Token); + starRatingDisplay.Current = (Bindable)difficultyCache.GetBindableDifficulty(beatmap.Value.BeatmapInfo, cancellationSource.Token, 200); + updateCountStatistics(cancellationSource.Token); updateDifficultyStatistics(); } - private void updateStarDifficulty(CancellationToken cancellationToken) - { - difficultyCache.GetDifficultyAsync(beatmap.Value.BeatmapInfo, ruleset.Value, mods.Value, cancellationToken) - .ContinueWith(task => - { - Schedule(() => - { - if (cancellationToken.IsCancellationRequested) - return; - - starRatingDisplay.Current.Value = task.GetResultSafely() ?? default; - }); - }, cancellationToken); - } - private void updateCountStatistics(CancellationToken cancellationToken) { if (beatmap.IsDefault) @@ -304,7 +288,7 @@ namespace osu.Game.Screens.SelectV2 private void updateDifficultyStatistics() => Scheduler.AddOnce(() => { - if (beatmap.IsDefault) + if (beatmap.IsDefault || ruleset.Value == null) { difficultyStatisticsDisplay.TooltipContent = null; difficultyStatisticsDisplay.Statistics = Array.Empty(); @@ -317,28 +301,25 @@ namespace osu.Game.Screens.SelectV2 foreach (var mod in mods.Value.OfType()) mod.ApplyToDifficulty(originalDifficulty); - var rateAdjustedDifficulty = originalDifficulty; + Ruleset rulesetInstance = ruleset.Value.CreateInstance(); - if (ruleset.Value != null) - { - double rate = ModUtils.CalculateRateWithMods(mods.Value); + double rate = ModUtils.CalculateRateWithMods(mods.Value); - rateAdjustedDifficulty = ruleset.Value.CreateInstance().GetRateAdjustedDisplayDifficulty(originalDifficulty, rate); - difficultyStatisticsDisplay.TooltipContent = new AdjustedAttributesTooltip.Data(originalDifficulty, rateAdjustedDifficulty); - } + BeatmapDifficulty rateAdjustedDifficulty = rulesetInstance.GetRateAdjustedDisplayDifficulty(originalDifficulty, rate); + difficultyStatisticsDisplay.TooltipContent = new AdjustedAttributesTooltip.Data(originalDifficulty, rateAdjustedDifficulty); StatisticDifficulty.Data firstStatistic; - switch (ruleset.Value?.OnlineID) + switch (ruleset.Value.OnlineID) { case 3: // Account for mania differences locally for now. // Eventually this should be handled in a more modular way, allowing rulesets to return arbitrary difficulty attributes. - ILegacyRuleset legacyRuleset = (ILegacyRuleset)ruleset.Value.CreateInstance(); + ILegacyRuleset legacyRuleset = (ILegacyRuleset)rulesetInstance; // For the time being, the key count is static no matter what, because: - // a) The method doesn't have knowledge of the active keymods. Doing so may require considerations for filtering. - // b) Using the difficulty adjustment mod to adjust OD doesn't have an effect on conversion. + // - The method doesn't have knowledge of the active keymods. Doing so may require considerations for filtering. + // - Using the difficulty adjustment mod to adjust OD doesn't have an effect on conversion. int keyCount = legacyRuleset.GetKeyCount(beatmap.Value.BeatmapInfo, mods.Value); firstStatistic = new StatisticDifficulty.Data(BeatmapsetsStrings.ShowStatsCsMania, keyCount, keyCount, 10); diff --git a/osu.Game/Screens/SelectV2/PanelBeatmap.cs b/osu.Game/Screens/SelectV2/PanelBeatmap.cs index 30d27cd7f0..497fce17ca 100644 --- a/osu.Game/Screens/SelectV2/PanelBeatmap.cs +++ b/osu.Game/Screens/SelectV2/PanelBeatmap.cs @@ -37,7 +37,7 @@ namespace osu.Game.Screens.SelectV2 private OsuSpriteText difficultyText = null!; private OsuSpriteText authorText = null!; - private IBindable? starDifficultyBindable; + private IBindable? starDifficultyBindable; private CancellationTokenSource? starDifficultyCancellationSource; [Resolved] diff --git a/osu.Game/Screens/SelectV2/PanelBeatmapStandalone.cs b/osu.Game/Screens/SelectV2/PanelBeatmapStandalone.cs index 74a32a11ba..6c0779bab6 100644 --- a/osu.Game/Screens/SelectV2/PanelBeatmapStandalone.cs +++ b/osu.Game/Screens/SelectV2/PanelBeatmapStandalone.cs @@ -51,7 +51,7 @@ namespace osu.Game.Screens.SelectV2 [Resolved] private BeatmapDifficultyCache difficultyCache { get; set; } = null!; - private IBindable? starDifficultyBindable; + private IBindable? starDifficultyBindable; private CancellationTokenSource? starDifficultyCancellationSource; private PanelSetBackground background = null!; diff --git a/osu.Game/Skinning/Components/BeatmapAttributeText.cs b/osu.Game/Skinning/Components/BeatmapAttributeText.cs index d9f7eedfb5..76c8d54f50 100644 --- a/osu.Game/Skinning/Components/BeatmapAttributeText.cs +++ b/osu.Game/Skinning/Components/BeatmapAttributeText.cs @@ -48,7 +48,7 @@ namespace osu.Game.Skinning.Components private BeatmapDifficultyCache difficultyCache { get; set; } = null!; private readonly OsuSpriteText text; - private IBindable? difficultyBindable; + private IBindable? difficultyBindable; private CancellationTokenSource? difficultyCancellationSource; private ModSettingChangeTracker? modSettingTracker; private StarDifficulty? starDifficulty;