diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 16b2a54a45..91f22a291c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -174,6 +174,7 @@ namespace osu.Game.Tests.Visual.Gameplay holdForMenu.Action += () => activated = true; }); + AddStep("set hold button always visible", () => localConfig.SetValue(OsuSetting.AlwaysShowHoldForMenuButton, true)); AddStep("set showhud false", () => hudOverlay.ShowHud.Value = false); AddUntilStep("hidetarget is hidden", () => hideTarget.Alpha, () => Is.LessThanOrEqualTo(0)); @@ -214,6 +215,7 @@ namespace osu.Game.Tests.Visual.Gameplay progress.ChildrenOfType().Single().OnSeek += _ => seeked = true; }); + AddStep("set hold button always visible", () => localConfig.SetValue(OsuSetting.AlwaysShowHoldForMenuButton, true)); AddStep("set showhud false", () => hudOverlay.ShowHud.Value = false); AddUntilStep("hidetarget is hidden", () => hideTarget.Alpha, () => Is.LessThanOrEqualTo(0)); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs index 3c225d60e0..cd1334165b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs @@ -1,13 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Testing; +using osu.Game.Configuration; using osu.Game.Screens.Play.HUD; using osuTK; using osuTK.Input; @@ -21,11 +21,19 @@ namespace osu.Game.Tests.Visual.Gameplay protected override double TimePerAction => 100; // required for the early exit test, since hold-to-confirm delay is 200ms - private HoldForMenuButton holdForMenuButton; + private HoldForMenuButton holdForMenuButton = null!; + + [Resolved] + private OsuConfigManager config { get; set; } = null!; [SetUpSteps] public void SetUpSteps() { + AddStep("set button always on", () => + { + config.SetValue(OsuSetting.AlwaysShowHoldForMenuButton, true); + }); + AddStep("create button", () => { exitAction = false; diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 030f2592ed..6aa2c4e40d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -320,6 +320,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestExitViaHoldToExit() { + AddStep("set hold button always visible", () => LocalConfig.SetValue(OsuSetting.AlwaysShowHoldForMenuButton, true)); + AddStep("exit", () => { InputManager.MoveMouseTo(Player.HUDOverlay.HoldToQuit.First(c => c is HoldToConfirmContainer)); diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index d00856dd80..8d6c244b35 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -205,6 +205,8 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.EditorTimelineShowTimingChanges, true); SetDefault(OsuSetting.EditorTimelineShowTicks, true); + + SetDefault(OsuSetting.AlwaysShowHoldForMenuButton, false); } protected override bool CheckLookupContainsPrivateInformation(OsuSetting lookup) @@ -429,5 +431,6 @@ namespace osu.Game.Configuration HideCountryFlags, EditorTimelineShowTimingChanges, EditorTimelineShowTicks, + AlwaysShowHoldForMenuButton } } diff --git a/osu.Game/Localisation/GameplaySettingsStrings.cs b/osu.Game/Localisation/GameplaySettingsStrings.cs index 8ee76fdd55..6de61f7ebe 100644 --- a/osu.Game/Localisation/GameplaySettingsStrings.cs +++ b/osu.Game/Localisation/GameplaySettingsStrings.cs @@ -84,6 +84,11 @@ namespace osu.Game.Localisation /// public static LocalisableString AlwaysShowGameplayLeaderboard => new TranslatableString(getKey(@"gameplay_leaderboard"), @"Always show gameplay leaderboard"); + /// + /// "Always show hold for menu button" + /// + public static LocalisableString AlwaysShowHoldForMenuButton => new TranslatableString(getKey(@"always_show_hold_for_menu_button"), @"Always show hold for menu button"); + /// /// "Always play first combo break sound" /// diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs index 3e67b2f103..f4dd319152 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs @@ -41,6 +41,11 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay Current = config.GetBindable(OsuSetting.GameplayLeaderboard), }, new SettingsCheckbox + { + LabelText = GameplaySettingsStrings.AlwaysShowHoldForMenuButton, + Current = config.GetBindable(OsuSetting.AlwaysShowHoldForMenuButton), + }, + new SettingsCheckbox { ClassicDefault = false, LabelText = GameplaySettingsStrings.ShowHealthDisplayWhenCantFail, diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 6d045e5f01..89d083eca9 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -30,6 +30,8 @@ namespace osu.Game.Screens.Play.HUD { public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + public override bool PropagatePositionalInputSubTree => alwaysShow.Value || touchActive.Value; + public readonly Bindable IsPaused = new Bindable(); public readonly Bindable ReplayLoaded = new Bindable(); @@ -40,6 +42,8 @@ namespace osu.Game.Screens.Play.HUD private OsuSpriteText text; + private Bindable alwaysShow; + public HoldForMenuButton() { Direction = FillDirection.Horizontal; @@ -50,7 +54,7 @@ namespace osu.Game.Screens.Play.HUD } [BackgroundDependencyLoader(true)] - private void load(Player player) + private void load(Player player, OsuConfigManager config) { Children = new Drawable[] { @@ -71,6 +75,8 @@ namespace osu.Game.Screens.Play.HUD }; AutoSizeAxes = Axes.Both; + + alwaysShow = config.GetBindable(OsuSetting.AlwaysShowHoldForMenuButton); } [Resolved] @@ -117,9 +123,14 @@ namespace osu.Game.Screens.Play.HUD { base.Update(); + // While the button is hovered or still animating, keep fully visible. if (text.Alpha > 0 || button.Progress.Value > 0 || button.IsHovered) Alpha = 1; - else + // When touch input is detected, keep visible at a constant opacity. + else if (touchActive.Value) + Alpha = 0.5f; + // Otherwise, if the user chooses, show it when the mouse is nearby. + else if (alwaysShow.Value) { float minAlpha = touchActive.Value ? .08f : 0; @@ -127,6 +138,8 @@ namespace osu.Game.Screens.Play.HUD Math.Clamp(Clock.ElapsedFrameTime, 0, 200), Alpha, Math.Clamp(1 - positionalAdjust, minAlpha, 1), 0, 200, Easing.OutQuint); } + else + Alpha = 0; } private partial class HoldButton : HoldToConfirmContainer, IKeyBindingHandler