From 45ef97c92cb78ca0b3969b2494942ad5d3fe0d2b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 Sep 2025 16:01:22 +0900 Subject: [PATCH] Simplify implementation --- .../Screens/Play/HUD/DefaultRankDisplay.cs | 55 +++++++++---------- osu.Game/Skinning/LegacyRankDisplay.cs | 54 +++++++++--------- 2 files changed, 52 insertions(+), 57 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs index 15901861c8..dd8c324c9e 100644 --- a/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs @@ -19,26 +19,23 @@ namespace osu.Game.Screens.Play.HUD { public partial class DefaultRankDisplay : CompositeDrawable, ISerialisableDrawable { + public bool UsesFixedAnchor { get; set; } + [Resolved] private ScoreProcessor scoreProcessor { get; set; } = null!; [SettingSource(typeof(DefaultRankDisplayStrings), nameof(DefaultRankDisplayStrings.PlaySamplesOnRankChange))] public BindableBool PlaySamples { get; set; } = new BindableBool(true); - public bool UsesFixedAnchor { get; set; } - private UpdateableRank rankDisplay = null!; private SkinnableSound rankDownSample = null!; private SkinnableSound rankUpSample = null!; - private Bindable lastSamplePlaybackTime = null!; + private Bindable lastSamplePlayback = null!; + private double lastRankUpdate; - private readonly Bindable lastRankChangeTime = new Bindable(); - - private IBindable rank = null!; - - private ScoreRank lastRank; + private ScoreRank displayedRank; private const int minimum_update_rate = 3000; @@ -63,44 +60,44 @@ namespace osu.Game.Screens.Play.HUD if (skinEditor != null) PlaySamples.Value = false; - lastSamplePlaybackTime = statics.GetBindable(Static.LastRankChangeSamplePlaybackTime); + lastSamplePlayback = statics.GetBindable(Static.LastRankChangeSamplePlaybackTime); } - protected override void LoadComplete() + protected override void Update() { - base.LoadComplete(); + base.Update(); - rank = scoreProcessor.Rank.GetBoundCopy(); - rank.BindValueChanged(r => + var currentRank = scoreProcessor.Rank.Value; + + if (currentRank != displayedRank) { - bool enoughTimeElapsed = !lastRankChangeTime.Value.HasValue || Time.Current - lastSamplePlaybackTime.Value >= minimum_update_rate; + bool enoughTimeElapsed = Time.Current - lastRankUpdate >= minimum_update_rate; - Scheduler.CancelDelayedTasks(); - if (enoughTimeElapsed || r.NewValue == ScoreRank.F) - onRankChange(r); - else - Scheduler.AddDelayed(onRankChange, r, (double)lastRankChangeTime.Value! - Time.Current + minimum_update_rate); - }, true); + if (enoughTimeElapsed || currentRank == ScoreRank.F) + updateRank(currentRank); + } } - private void onRankChange(ValueChangedEvent r) + private void updateRank(ScoreRank rank) { - bool enoughSampleTimeElapsed = !lastSamplePlaybackTime.Value.HasValue || Time.Current - lastSamplePlaybackTime.Value >= OsuGameBase.SAMPLE_DEBOUNCE_TIME; + rankDisplay.Rank = rank; - // Don't play rank-down sfx on quit/retry and entering - if (r.NewValue != lastRank && r.NewValue > ScoreRank.F && PlaySamples.Value && enoughSampleTimeElapsed && lastRankChangeTime.Value.HasValue) + // Check sample time separately to ensure two copies of the rank display don't both play samples on a change. + bool enoughSampleTimeElapsed = !lastSamplePlayback.Value.HasValue || Time.Current - lastSamplePlayback.Value >= OsuGameBase.SAMPLE_DEBOUNCE_TIME; + + // Also don't play rank-down sfx on quit/retry/initial update. + if (rank != displayedRank && rank > ScoreRank.F && PlaySamples.Value && enoughSampleTimeElapsed && lastRankUpdate > 0) { - if (r.NewValue > lastRank) + if (rank > displayedRank) rankUpSample.Play(); else rankDownSample.Play(); - lastSamplePlaybackTime.Value = Time.Current; + lastSamplePlayback.Value = Time.Current; } - rankDisplay.Rank = r.NewValue; - lastRank = r.NewValue; - lastRankChangeTime.Value = Time.Current; + displayedRank = rank; + lastRankUpdate = Time.Current; } } } diff --git a/osu.Game/Skinning/LegacyRankDisplay.cs b/osu.Game/Skinning/LegacyRankDisplay.cs index 216f7f3679..ee67d77487 100644 --- a/osu.Game/Skinning/LegacyRankDisplay.cs +++ b/osu.Game/Skinning/LegacyRankDisplay.cs @@ -34,13 +34,10 @@ namespace osu.Game.Skinning private SkinnableSound rankDownSample = null!; private SkinnableSound rankUpSample = null!; - private Bindable lastSamplePlaybackTime = null!; + private Bindable lastSamplePlayback = null!; + private double lastRankUpdate; - private readonly Bindable lastRankChangeTime = new Bindable(); - - private IBindable rank = null!; - - private ScoreRank lastRank; + private ScoreRank displayedRank; private const int minimum_update_rate = 3000; @@ -67,29 +64,27 @@ namespace osu.Game.Skinning if (skinEditor != null) PlaySamples.Value = false; - lastSamplePlaybackTime = statics.GetBindable(Static.LastRankChangeSamplePlaybackTime); + lastSamplePlayback = statics.GetBindable(Static.LastRankChangeSamplePlaybackTime); } - protected override void LoadComplete() + protected override void Update() { - rank = scoreProcessor.Rank.GetBoundCopy(); - rank.BindValueChanged(r => + base.Update(); + + var currentRank = scoreProcessor.Rank.Value; + + if (currentRank != displayedRank) { - bool enoughTimeElapsed = !lastRankChangeTime.Value.HasValue || Time.Current - lastRankChangeTime.Value >= minimum_update_rate; + bool enoughTimeElapsed = Time.Current - lastRankUpdate >= minimum_update_rate; - Scheduler.CancelDelayedTasks(); - if (enoughTimeElapsed || r.NewValue == ScoreRank.F) - onRankChange(r); - else - Scheduler.AddDelayed(onRankChange, r, (double)lastRankChangeTime.Value! - Time.Current + minimum_update_rate); - }, true); - - FinishTransforms(true); + if (enoughTimeElapsed || currentRank == ScoreRank.F) + updateRank(currentRank); + } } - private void onRankChange(ValueChangedEvent r) + private void updateRank(ScoreRank rank) { - var texture = source.GetTexture($"ranking-{r.NewValue}-small"); + var texture = source.GetTexture($"ranking-{rank}-small"); rankDisplay.Texture = texture; @@ -103,27 +98,30 @@ namespace osu.Game.Skinning Origin = Anchor.Centre, BypassAutoSizeAxes = Axes.Both, }; + AddInternal(transientRank); + transientRank.FadeOutFromOne(500, Easing.Out) .ScaleTo(new Vector2(1.625f), 500, Easing.Out) .Expire(); } - bool enoughSampleTimeElapsed = !lastSamplePlaybackTime.Value.HasValue || Time.Current - lastSamplePlaybackTime.Value >= OsuGameBase.SAMPLE_DEBOUNCE_TIME; + // Check sample time separately to ensure two copies of the rank display don't both play samples on a change. + bool enoughSampleTimeElapsed = !lastSamplePlayback.Value.HasValue || Time.Current - lastSamplePlayback.Value >= OsuGameBase.SAMPLE_DEBOUNCE_TIME; - // Don't play rank-down sfx on quit/retry and entering - if (r.NewValue != lastRank && r.NewValue > ScoreRank.F && PlaySamples.Value && enoughSampleTimeElapsed && lastRankChangeTime.Value.HasValue) + // Also don't play rank-down sfx on quit/retry/initial update. + if (rank != displayedRank && rank > ScoreRank.F && PlaySamples.Value && enoughSampleTimeElapsed && lastRankUpdate > 0) { - if (r.NewValue > lastRank) + if (rank > displayedRank) rankUpSample.Play(); else rankDownSample.Play(); - lastSamplePlaybackTime.Value = Time.Current; + lastSamplePlayback.Value = Time.Current; } - lastRank = r.NewValue; - lastRankChangeTime.Value = Time.Current; + displayedRank = rank; + lastRankUpdate = Time.Current; } } }