1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-21 02:19:55 +08:00

Merge pull request #33256 from peppy/beatmap-title-wedge-fixes

SongSelectV2: Change beatmap title wedge to use debounced difficulty retrieval
This commit is contained in:
Dean Herbert
2025-05-26 16:12:30 +09:00
committed by GitHub
Unverified
11 changed files with 44 additions and 79 deletions
@@ -32,7 +32,7 @@ namespace osu.Game.Tests.Beatmaps
private TestBeatmapDifficultyCache difficultyCache;
private IBindable<StarDifficulty?> starDifficultyBindable;
private IBindable<StarDifficulty> 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]
+3 -3
View File
@@ -99,8 +99,8 @@ namespace osu.Game.Beatmaps
/// <param name="beatmapInfo">The <see cref="BeatmapInfo"/> to get the difficulty of.</param>
/// <param name="cancellationToken">An optional <see cref="CancellationToken"/> which stops updating the star difficulty for the given <see cref="BeatmapInfo"/>.</param>
/// <param name="computationDelay">A delay in milliseconds before performing the </param>
/// <returns>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).</returns>
public IBindable<StarDifficulty?> GetBindableDifficulty(IBeatmapInfo beatmapInfo, CancellationToken cancellationToken = default, int computationDelay = 0)
/// <returns>A bindable that is updated to contain the star difficulty when it becomes available. May be an approximation while in an initial calculating state.</returns>
public IBindable<StarDifficulty> 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<StarDifficulty?>
private class BindableStarDifficulty : Bindable<StarDifficulty>
{
public readonly IBeatmapInfo BeatmapInfo;
public readonly CancellationToken CancellationToken;
@@ -54,7 +54,7 @@ namespace osu.Game.Overlays.Mods
protected IBindable<RulesetInfo> GameRuleset = null!;
private CancellationTokenSource? cancellationSource;
private IBindable<StarDifficulty?> starDifficulty = null!;
private IBindable<StarDifficulty> starDifficulty = null!;
public ITooltip<AdjustedAttributesTooltip.Data?> 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);
@@ -51,7 +51,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
private bool animationBegan;
private IBindable<StarDifficulty?> starDifficulty = null!;
private IBindable<StarDifficulty> 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)
{
@@ -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?> starDifficulty;
private IBindable<StarDifficulty> 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
+2 -2
View File
@@ -185,7 +185,7 @@ namespace osu.Game.Screens.Select
}
private CancellationTokenSource cancellationSource;
private IBindable<StarDifficulty?> starDifficulty;
private IBindable<StarDifficulty> 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)
@@ -91,7 +91,7 @@ namespace osu.Game.Screens.Select.Carousel
[Resolved]
private BeatmapManager? manager { get; set; }
private IBindable<StarDifficulty?> starDifficultyBindable = null!;
private IBindable<StarDifficulty> 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();
@@ -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<StarDifficulty>)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<StatisticDifficulty.Data>();
@@ -317,28 +301,25 @@ namespace osu.Game.Screens.SelectV2
foreach (var mod in mods.Value.OfType<IApplicableToDifficulty>())
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);
+1 -1
View File
@@ -37,7 +37,7 @@ namespace osu.Game.Screens.SelectV2
private OsuSpriteText difficultyText = null!;
private OsuSpriteText authorText = null!;
private IBindable<StarDifficulty?>? starDifficultyBindable;
private IBindable<StarDifficulty>? starDifficultyBindable;
private CancellationTokenSource? starDifficultyCancellationSource;
[Resolved]
@@ -51,7 +51,7 @@ namespace osu.Game.Screens.SelectV2
[Resolved]
private BeatmapDifficultyCache difficultyCache { get; set; } = null!;
private IBindable<StarDifficulty?>? starDifficultyBindable;
private IBindable<StarDifficulty>? starDifficultyBindable;
private CancellationTokenSource? starDifficultyCancellationSource;
private PanelSetBackground background = null!;
@@ -48,7 +48,7 @@ namespace osu.Game.Skinning.Components
private BeatmapDifficultyCache difficultyCache { get; set; } = null!;
private readonly OsuSpriteText text;
private IBindable<StarDifficulty?>? difficultyBindable;
private IBindable<StarDifficulty>? difficultyBindable;
private CancellationTokenSource? difficultyCancellationSource;
private ModSettingChangeTracker? modSettingTracker;
private StarDifficulty? starDifficulty;