From 68945daa4094455cb3361c0b1151e14cdadf82da Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2024 19:27:20 +0900 Subject: [PATCH] Add confirmation when pressing 'q' to quit at the main menu Kinda a weird key. I feel like this deserves a confirmation step unlike mouse clicking the exit button. Addresses https://github.com/ppy/osu/discussions/30471. --- .../TestSceneDailyChallengeIntro.cs | 2 +- .../UserInterface/TestSceneButtonSystem.cs | 2 +- .../UserInterface/TestSceneMainMenuButton.cs | 6 ++--- osu.Game/Screens/Menu/ButtonSystem.cs | 26 +++++++++---------- osu.Game/Screens/Menu/DailyChallengeButton.cs | 3 ++- osu.Game/Screens/Menu/MainMenu.cs | 4 +-- osu.Game/Screens/Menu/MainMenuButton.cs | 12 ++++----- 7 files changed, 28 insertions(+), 27 deletions(-) diff --git a/osu.Game.Tests/Visual/DailyChallenge/TestSceneDailyChallengeIntro.cs b/osu.Game.Tests/Visual/DailyChallenge/TestSceneDailyChallengeIntro.cs index f1a2d6b5f2a3..7619328e688b 100644 --- a/osu.Game.Tests/Visual/DailyChallenge/TestSceneDailyChallengeIntro.cs +++ b/osu.Game.Tests/Visual/DailyChallenge/TestSceneDailyChallengeIntro.cs @@ -38,7 +38,7 @@ private void load() Add(metadataClient); // add button to observe for daily challenge changes and perform its logic. - Add(new DailyChallengeButton(@"button-default-select", new Color4(102, 68, 204, 255), _ => { }, 0, Key.D)); + Add(new DailyChallengeButton(@"button-default-select", new Color4(102, 68, 204, 255), (_, _) => { }, 0, Key.D)); } [Test] diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs index 8f72be37df6f..d8baca6d232f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs @@ -110,7 +110,7 @@ public void TestShortcutKeys(Key key, Key? subMenuEnterKey) break; case Key.Q: - buttons.OnExit = action; + buttons.OnExit = _ => action(); break; case Key.O: diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneMainMenuButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneMainMenuButton.cs index 41543669ebbe..4925facd8a8a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneMainMenuButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneMainMenuButton.cs @@ -30,7 +30,7 @@ public partial class TestSceneMainMenuButton : OsuTestScene public void TestStandardButton() { AddStep("add button", () => Child = new MainMenuButton( - ButtonSystemStrings.Solo, @"button-default-select", OsuIcon.Player, new Color4(102, 68, 204, 255), _ => { }, 0, Key.P) + ButtonSystemStrings.Solo, @"button-default-select", OsuIcon.Player, new Color4(102, 68, 204, 255), (_, _) => { }, 0, Key.P) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -87,7 +87,7 @@ public void TestDailyChallengeButton() Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, CachedDependencies = [(typeof(INotificationOverlay), notificationOverlay)], - Child = new DailyChallengeButton(@"button-default-select", new Color4(102, 68, 204, 255), _ => { }, 0, Key.D) + Child = new DailyChallengeButton(@"button-default-select", new Color4(102, 68, 204, 255), (_, _) => { }, 0, Key.D) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -161,7 +161,7 @@ public void TestDailyChallengeButtonOldChallenge() Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, CachedDependencies = [(typeof(INotificationOverlay), notificationOverlay)], - Child = new DailyChallengeButton(@"button-default-select", new Color4(102, 68, 204, 255), _ => { }, 0, Key.D) + Child = new DailyChallengeButton(@"button-default-select", new Color4(102, 68, 204, 255), (_, _) => { }, 0, Key.D) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 0997ab80039f..41920605b07e 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -41,7 +41,7 @@ public partial class ButtonSystem : Container, IStateful, IKe public Action? OnEditBeatmap; public Action? OnEditSkin; - public Action? OnExit; + public Action? OnExit; public Action? OnBeatmapListing; public Action? OnSolo; public Action? OnSettings; @@ -104,11 +104,11 @@ public ButtonSystem() buttonArea.AddRange(new Drawable[] { - new MainMenuButton(ButtonSystemStrings.Settings, string.Empty, OsuIcon.Settings, new Color4(85, 85, 85, 255), _ => OnSettings?.Invoke(), Key.O, Key.S) + new MainMenuButton(ButtonSystemStrings.Settings, string.Empty, OsuIcon.Settings, new Color4(85, 85, 85, 255), (_, _) => OnSettings?.Invoke(), Key.O, Key.S) { Padding = new MarginPadding { Right = WEDGE_WIDTH }, }, - backButton = new MainMenuButton(ButtonSystemStrings.Back, @"back-to-top", OsuIcon.PrevCircle, new Color4(51, 58, 94, 255), _ => State = ButtonSystemState.TopLevel) + backButton = new MainMenuButton(ButtonSystemStrings.Back, @"back-to-top", OsuIcon.PrevCircle, new Color4(51, 58, 94, 255), (_, _) => State = ButtonSystemState.TopLevel) { Padding = new MarginPadding { Right = WEDGE_WIDTH }, VisibleStateMin = ButtonSystemState.Play, @@ -132,7 +132,7 @@ public ButtonSystem() [BackgroundDependencyLoader] private void load(AudioManager audio, IdleTracker? idleTracker, GameHost host) { - buttonsPlay.Add(new MainMenuButton(ButtonSystemStrings.Solo, @"button-default-select", OsuIcon.Player, new Color4(102, 68, 204, 255), _ => OnSolo?.Invoke(), Key.P) + buttonsPlay.Add(new MainMenuButton(ButtonSystemStrings.Solo, @"button-default-select", OsuIcon.Player, new Color4(102, 68, 204, 255), (_, _) => OnSolo?.Invoke(), Key.P) { Padding = new MarginPadding { Left = WEDGE_WIDTH }, }); @@ -141,22 +141,22 @@ private void load(AudioManager audio, IdleTracker? idleTracker, GameHost host) buttonsPlay.Add(new DailyChallengeButton(@"button-daily-select", new Color4(94, 63, 186, 255), onDailyChallenge, Key.D)); buttonsPlay.ForEach(b => b.VisibleState = ButtonSystemState.Play); - buttonsEdit.Add(new MainMenuButton(EditorStrings.BeatmapEditor.ToLower(), @"button-default-select", OsuIcon.Beatmap, new Color4(238, 170, 0, 255), _ => OnEditBeatmap?.Invoke(), Key.B, Key.E) + buttonsEdit.Add(new MainMenuButton(EditorStrings.BeatmapEditor.ToLower(), @"button-default-select", OsuIcon.Beatmap, new Color4(238, 170, 0, 255), (_, _) => OnEditBeatmap?.Invoke(), Key.B, Key.E) { Padding = new MarginPadding { Left = WEDGE_WIDTH }, }); - buttonsEdit.Add(new MainMenuButton(SkinEditorStrings.SkinEditor.ToLower(), @"button-default-select", OsuIcon.SkinB, new Color4(220, 160, 0, 255), _ => OnEditSkin?.Invoke(), Key.S)); + buttonsEdit.Add(new MainMenuButton(SkinEditorStrings.SkinEditor.ToLower(), @"button-default-select", OsuIcon.SkinB, new Color4(220, 160, 0, 255), (_, _) => OnEditSkin?.Invoke(), Key.S)); buttonsEdit.ForEach(b => b.VisibleState = ButtonSystemState.Edit); - buttonsTopLevel.Add(new MainMenuButton(ButtonSystemStrings.Play, @"button-play-select", OsuIcon.Logo, new Color4(102, 68, 204, 255), _ => State = ButtonSystemState.Play, Key.P, Key.M, Key.L) + buttonsTopLevel.Add(new MainMenuButton(ButtonSystemStrings.Play, @"button-play-select", OsuIcon.Logo, new Color4(102, 68, 204, 255), (_, _) => State = ButtonSystemState.Play, Key.P, Key.M, Key.L) { Padding = new MarginPadding { Left = WEDGE_WIDTH }, }); - buttonsTopLevel.Add(new MainMenuButton(ButtonSystemStrings.Edit, @"button-play-select", OsuIcon.EditCircle, new Color4(238, 170, 0, 255), _ => State = ButtonSystemState.Edit, Key.E)); - buttonsTopLevel.Add(new MainMenuButton(ButtonSystemStrings.Browse, @"button-default-select", OsuIcon.Beatmap, new Color4(165, 204, 0, 255), _ => OnBeatmapListing?.Invoke(), Key.B, Key.D)); + buttonsTopLevel.Add(new MainMenuButton(ButtonSystemStrings.Edit, @"button-play-select", OsuIcon.EditCircle, new Color4(238, 170, 0, 255), (_, _) => State = ButtonSystemState.Edit, Key.E)); + buttonsTopLevel.Add(new MainMenuButton(ButtonSystemStrings.Browse, @"button-default-select", OsuIcon.Beatmap, new Color4(165, 204, 0, 255), (_, _) => OnBeatmapListing?.Invoke(), Key.B, Key.D)); if (host.CanExit) - buttonsTopLevel.Add(new MainMenuButton(ButtonSystemStrings.Exit, string.Empty, OsuIcon.CrossCircle, new Color4(238, 51, 153, 255), _ => OnExit?.Invoke(), Key.Q)); + buttonsTopLevel.Add(new MainMenuButton(ButtonSystemStrings.Exit, string.Empty, OsuIcon.CrossCircle, new Color4(238, 51, 153, 255), (_, e) => OnExit?.Invoke(e), Key.Q)); buttonArea.AddRange(buttonsPlay); buttonArea.AddRange(buttonsEdit); @@ -179,7 +179,7 @@ private void load(AudioManager audio, IdleTracker? idleTracker, GameHost host) sampleLogoSwoosh = audio.Samples.Get(@"Menu/osu-logo-swoosh"); } - private void onMultiplayer(MainMenuButton _) + private void onMultiplayer(MainMenuButton mainMenuButton, UIEvent uiEvent) { if (api.State.Value != APIState.Online) { @@ -190,7 +190,7 @@ private void onMultiplayer(MainMenuButton _) OnMultiplayer?.Invoke(); } - private void onPlaylists(MainMenuButton _) + private void onPlaylists(MainMenuButton mainMenuButton, UIEvent uiEvent) { if (api.State.Value != APIState.Online) { @@ -201,7 +201,7 @@ private void onPlaylists(MainMenuButton _) OnPlaylists?.Invoke(); } - private void onDailyChallenge(MainMenuButton button) + private void onDailyChallenge(MainMenuButton button, UIEvent uiEvent) { if (api.State.Value != APIState.Online) { diff --git a/osu.Game/Screens/Menu/DailyChallengeButton.cs b/osu.Game/Screens/Menu/DailyChallengeButton.cs index 4dbebf0ae9ec..44a53efa7b95 100644 --- a/osu.Game/Screens/Menu/DailyChallengeButton.cs +++ b/osu.Game/Screens/Menu/DailyChallengeButton.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; using osu.Framework.Threading; using osu.Framework.Utils; using osu.Game.Beatmaps.Drawables; @@ -50,7 +51,7 @@ public partial class DailyChallengeButton : MainMenuButton [Resolved] private SessionStatics statics { get; set; } = null!; - public DailyChallengeButton(string sampleName, Color4 colour, Action? clickAction = null, params Key[] triggerKeys) + public DailyChallengeButton(string sampleName, Color4 colour, Action? clickAction = null, params Key[] triggerKeys) : base(ButtonSystemStrings.DailyChallenge, sampleName, OsuIcon.DailyChallenge, colour, clickAction, triggerKeys) { BaseSize = new Vector2(ButtonSystem.BUTTON_WIDTH * 1.3f, ButtonArea.BUTTON_AREA_HEIGHT); diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 346bdcb75117..35c6bab81b7b 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -153,9 +153,9 @@ private void load(BeatmapListingOverlay beatmapListing, SettingsOverlay settings else this.Push(new DailyChallengeIntro(room)); }, - OnExit = () => + OnExit = e => { - exitConfirmedViaHoldOrClick = true; + exitConfirmedViaHoldOrClick = e is MouseEvent; this.Exit(); } } diff --git a/osu.Game/Screens/Menu/MainMenuButton.cs b/osu.Game/Screens/Menu/MainMenuButton.cs index 4df5e6d309c9..f8824795d8b0 100644 --- a/osu.Game/Screens/Menu/MainMenuButton.cs +++ b/osu.Game/Screens/Menu/MainMenuButton.cs @@ -64,7 +64,7 @@ public ButtonSystemState VisibleState protected Vector2 BaseSize { get; init; } = new Vector2(ButtonSystem.BUTTON_WIDTH, ButtonArea.BUTTON_AREA_HEIGHT); - private readonly Action? clickAction; + private readonly Action? clickAction; private readonly Container background; private readonly Drawable backgroundContent; @@ -84,7 +84,7 @@ public ButtonSystemState VisibleState public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => background.ReceivePositionalInputAt(screenSpacePos); - public MainMenuButton(LocalisableString text, string sampleName, IconUsage symbol, Color4 colour, Action? clickAction = null, params Key[] triggerKeys) + public MainMenuButton(LocalisableString text, string sampleName, IconUsage symbol, Color4 colour, Action? clickAction = null, params Key[] triggerKeys) { this.sampleName = sampleName; this.clickAction = clickAction; @@ -263,7 +263,7 @@ protected override void OnMouseUp(MouseUpEvent e) protected override bool OnClick(ClickEvent e) { - trigger(); + trigger(e); return true; } @@ -274,19 +274,19 @@ protected override bool OnKeyDown(KeyDownEvent e) if (TriggerKeys.Contains(e.Key)) { - trigger(); + trigger(e); return true; } return false; } - private void trigger() + private void trigger(UIEvent e) { sampleChannel = sampleClick?.GetChannel(); sampleChannel?.Play(); - clickAction?.Invoke(this); + clickAction?.Invoke(this, e); boxHoverLayer.ClearTransforms(); boxHoverLayer.Alpha = 0.9f;