From 09050ba3fa5078d6c3d154fe3fbee80eed34130d Mon Sep 17 00:00:00 2001 From: MingxuanGame Date: Tue, 7 Jul 2026 18:11:01 +0800 Subject: [PATCH 1/2] Allow to hide rank display during gameplay --- .../Localisation/DefaultRankDisplayStrings.cs | 7 +++- .../Screens/Play/HUD/DefaultRankDisplay.cs | 30 +++++++++++++++-- osu.Game/Skinning/LegacyRankDisplay.cs | 33 ++++++++++++++++--- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/osu.Game/Localisation/DefaultRankDisplayStrings.cs b/osu.Game/Localisation/DefaultRankDisplayStrings.cs index 88e3b4309ab3..aafddb26e6e6 100644 --- a/osu.Game/Localisation/DefaultRankDisplayStrings.cs +++ b/osu.Game/Localisation/DefaultRankDisplayStrings.cs @@ -14,6 +14,11 @@ public static class DefaultRankDisplayStrings /// public static LocalisableString PlaySamplesOnRankChange => new TranslatableString(getKey(@"play_samples_on_rank_change"), @"Play samples on rank change"); + /// + /// "Hide during gameplay" + /// + public static LocalisableString HideDuringGameplay => new TranslatableString(getKey(@"hide_during_gameplay"), @"Hide during gameplay"); + private static string getKey(string key) => $@"{prefix}:{key}"; } -} \ No newline at end of file +} diff --git a/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs index d768fedca40d..d1b89d930fa4 100644 --- a/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs @@ -27,16 +27,24 @@ public partial class DefaultRankDisplay : CompositeDrawable, ISerialisableDrawab [SettingSource(typeof(DefaultRankDisplayStrings), nameof(DefaultRankDisplayStrings.PlaySamplesOnRankChange))] public BindableBool PlaySamples { get; set; } = new BindableBool(true); + [SettingSource(typeof(DefaultRankDisplayStrings), nameof(DefaultRankDisplayStrings.HideDuringGameplay))] + public BindableBool HideDuringGameplay { get; set; } = new BindableBool(); + private UpdateableRank rankDisplay = null!; private SkinnableSound rankDownSample = null!; private SkinnableSound rankUpSample = null!; private Bindable lastSamplePlayback = null!; + private readonly IBindable userPlayingState = new Bindable(); + private readonly IBindable holdingForHUD = new Bindable(); private double lastChangeTime; + private bool lastHiddenStatus; private ScoreRank? displayedRank; + private bool isHidden => HideDuringGameplay.Value && userPlayingState.Value == LocalUserPlayingState.Playing && !holdingForHUD.Value; + private const int time_between_changes = 1500; public DefaultRankDisplay() @@ -45,7 +53,7 @@ public DefaultRankDisplay() } [BackgroundDependencyLoader] - private void load(SkinEditor? skinEditor, SessionStatics statics) + private void load(SkinEditor? skinEditor, SessionStatics statics, GameplayState? gameplayState, HUDOverlay? hudOverlay) { InternalChildren = new Drawable[] { @@ -61,6 +69,12 @@ private void load(SkinEditor? skinEditor, SessionStatics statics) PlaySamples.Value = false; lastSamplePlayback = statics.GetBindable(Static.LastRankChangeSamplePlaybackTime); + + if (gameplayState != null) + userPlayingState.BindTo(gameplayState.PlayingState); + + if (hudOverlay != null) + holdingForHUD.BindTo(hudOverlay.HoldingForHUD); } protected override void LoadComplete() @@ -76,6 +90,10 @@ protected override void Update() var currentRank = scoreProcessor.Rank.Value; + bool currentHiddenStatus = isHidden; + if (currentHiddenStatus != lastHiddenStatus) + updateDisplayStatus(currentHiddenStatus); + if (currentRank == displayedRank) return; @@ -83,6 +101,12 @@ protected override void Update() updateRank(currentRank); } + private void updateDisplayStatus(bool currentHiddenStatus) + { + rankDisplay.Alpha = currentHiddenStatus ? 0 : 1; + lastHiddenStatus = currentHiddenStatus; + } + private void updateRank(ScoreRank rank) { rankDisplay.Rank = rank; @@ -90,8 +114,8 @@ private void updateRank(ScoreRank rank) // 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 (displayedRank != null && rank > ScoreRank.F && PlaySamples.Value && enoughSampleTimeElapsed) + // Also don't play rank-down sfx on quit/retry/initial update or being hidden. + if (displayedRank != null && rank > ScoreRank.F && PlaySamples.Value && enoughSampleTimeElapsed && !isHidden) { if (rank > displayedRank) rankUpSample.Play(); diff --git a/osu.Game/Skinning/LegacyRankDisplay.cs b/osu.Game/Skinning/LegacyRankDisplay.cs index 64376f0dbdb9..268c6ec09aed 100644 --- a/osu.Game/Skinning/LegacyRankDisplay.cs +++ b/osu.Game/Skinning/LegacyRankDisplay.cs @@ -12,6 +12,7 @@ using osu.Game.Overlays.SkinEditor; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Screens.Play; using osuTK; namespace osu.Game.Skinning @@ -29,16 +30,24 @@ public partial class LegacyRankDisplay : CompositeDrawable, ISerialisableDrawabl [SettingSource(typeof(DefaultRankDisplayStrings), nameof(DefaultRankDisplayStrings.PlaySamplesOnRankChange))] public BindableBool PlaySamples { get; set; } = new BindableBool(true); + [SettingSource(typeof(DefaultRankDisplayStrings), nameof(DefaultRankDisplayStrings.HideDuringGameplay))] + public BindableBool HideDuringGameplay { get; set; } = new BindableBool(); + private readonly Sprite rankDisplay; private SkinnableSound rankDownSample = null!; private SkinnableSound rankUpSample = null!; private Bindable lastSamplePlayback = null!; + private readonly IBindable userPlayingState = new Bindable(); + private readonly IBindable holdingForHUD = new Bindable(); private double lastChangeTime; + private bool lastHiddenStatus; private ScoreRank? displayedRank; + private bool isHidden => HideDuringGameplay.Value && userPlayingState.Value == LocalUserPlayingState.Playing && !holdingForHUD.Value; + private const int time_between_changes = 1500; public LegacyRankDisplay() @@ -53,7 +62,7 @@ public LegacyRankDisplay() } [BackgroundDependencyLoader] - private void load(SkinEditor? skinEditor, SessionStatics statics) + private void load(SkinEditor? skinEditor, SessionStatics statics, GameplayState? gameplayState, HUDOverlay? hudOverlay) { AddRangeInternal(new Drawable[] { @@ -65,6 +74,12 @@ private void load(SkinEditor? skinEditor, SessionStatics statics) PlaySamples.Value = false; lastSamplePlayback = statics.GetBindable(Static.LastRankChangeSamplePlaybackTime); + + if (gameplayState != null) + userPlayingState.BindTo(gameplayState.PlayingState); + + if (hudOverlay != null) + holdingForHUD.BindTo(hudOverlay.HoldingForHUD); } protected override void LoadComplete() @@ -80,6 +95,10 @@ protected override void Update() var currentRank = scoreProcessor.Rank.Value; + bool currentHiddenStatus = isHidden; + if (currentHiddenStatus != lastHiddenStatus) + updateDisplayStatus(currentHiddenStatus); + if (currentRank == displayedRank) return; @@ -87,13 +106,19 @@ protected override void Update() updateRank(currentRank); } + private void updateDisplayStatus(bool currentHiddenStatus) + { + rankDisplay.Alpha = currentHiddenStatus ? 0 : 1; + lastHiddenStatus = currentHiddenStatus; + } + private void updateRank(ScoreRank rank) { var texture = source.GetTexture($"ranking-{rank}-small"); rankDisplay.Texture = texture; - if (texture != null && displayedRank != null) + if (texture != null && displayedRank != null && !isHidden) { var transientRank = new Sprite { @@ -114,8 +139,8 @@ private void updateRank(ScoreRank rank) // 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 (displayedRank != null && rank > ScoreRank.F && PlaySamples.Value && enoughSampleTimeElapsed) + // Also don't play rank-down sfx on quit/retry/initial update or being hidden. + if (displayedRank != null && rank > ScoreRank.F && PlaySamples.Value && enoughSampleTimeElapsed && !isHidden) { if (rank > displayedRank) rankUpSample.Play(); From 3eed3fc2c5346b3279be99eac7906dfa1ae0f50b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Jul 2026 20:54:04 +0900 Subject: [PATCH 2/2] Use existing localisation --- osu.Game/Localisation/DefaultRankDisplayStrings.cs | 5 ----- osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs | 2 +- osu.Game/Skinning/LegacyRankDisplay.cs | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game/Localisation/DefaultRankDisplayStrings.cs b/osu.Game/Localisation/DefaultRankDisplayStrings.cs index aafddb26e6e6..bd7b262ad5b6 100644 --- a/osu.Game/Localisation/DefaultRankDisplayStrings.cs +++ b/osu.Game/Localisation/DefaultRankDisplayStrings.cs @@ -14,11 +14,6 @@ public static class DefaultRankDisplayStrings /// public static LocalisableString PlaySamplesOnRankChange => new TranslatableString(getKey(@"play_samples_on_rank_change"), @"Play samples on rank change"); - /// - /// "Hide during gameplay" - /// - public static LocalisableString HideDuringGameplay => new TranslatableString(getKey(@"hide_during_gameplay"), @"Hide during gameplay"); - private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs index d1b89d930fa4..cc4eb7d9fe8a 100644 --- a/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultRankDisplay.cs @@ -27,7 +27,7 @@ public partial class DefaultRankDisplay : CompositeDrawable, ISerialisableDrawab [SettingSource(typeof(DefaultRankDisplayStrings), nameof(DefaultRankDisplayStrings.PlaySamplesOnRankChange))] public BindableBool PlaySamples { get; set; } = new BindableBool(true); - [SettingSource(typeof(DefaultRankDisplayStrings), nameof(DefaultRankDisplayStrings.HideDuringGameplay))] + [SettingSource(typeof(GameplaySettingsStrings), nameof(GameplaySettingsStrings.HideDuringGameplay))] public BindableBool HideDuringGameplay { get; set; } = new BindableBool(); private UpdateableRank rankDisplay = null!; diff --git a/osu.Game/Skinning/LegacyRankDisplay.cs b/osu.Game/Skinning/LegacyRankDisplay.cs index 268c6ec09aed..c169f4a906b2 100644 --- a/osu.Game/Skinning/LegacyRankDisplay.cs +++ b/osu.Game/Skinning/LegacyRankDisplay.cs @@ -30,7 +30,7 @@ public partial class LegacyRankDisplay : CompositeDrawable, ISerialisableDrawabl [SettingSource(typeof(DefaultRankDisplayStrings), nameof(DefaultRankDisplayStrings.PlaySamplesOnRankChange))] public BindableBool PlaySamples { get; set; } = new BindableBool(true); - [SettingSource(typeof(DefaultRankDisplayStrings), nameof(DefaultRankDisplayStrings.HideDuringGameplay))] + [SettingSource(typeof(GameplaySettingsStrings), nameof(GameplaySettingsStrings.HideDuringGameplay))] public BindableBool HideDuringGameplay { get; set; } = new BindableBool(); private readonly Sprite rankDisplay;