diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 312781ef1a..898417811c 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -611,7 +611,7 @@ namespace osu.Game.Tests.Visual.Navigation AddAssert("ensure score is databased", () => Game.Realm.Run(r => r.Find(score.ID)?.DeletePending == false)); - AddStep("press back button", () => Game.ChildrenOfType().First().Action()); + AddStep("press back button", () => Game.ChildrenOfType().First().Action!.Invoke()); AddStep("show local scores", () => Game.ChildrenOfType().First().Current.Value = new BeatmapDetailAreaLeaderboardTabItem(BeatmapLeaderboardScope.Local)); @@ -644,7 +644,7 @@ namespace osu.Game.Tests.Visual.Navigation AddAssert("ensure score is databased", () => Game.Realm.Run(r => r.Find(score.ID)?.DeletePending == false)); - AddStep("press back button", () => Game.ChildrenOfType().First().Action()); + AddStep("press back button", () => Game.ChildrenOfType().First().Action!.Invoke()); AddStep("show local scores", () => Game.ChildrenOfType().First().Current.Value = new BeatmapDetailAreaLeaderboardTabItem(BeatmapLeaderboardScope.Local)); @@ -734,7 +734,7 @@ namespace osu.Game.Tests.Visual.Navigation public void TestPushSongSelectAndPressBackButtonImmediately() { AddStep("push song select", () => Game.ScreenStack.Push(new TestPlaySongSelect())); - AddStep("press back button", () => Game.ChildrenOfType().First().Action()); + AddStep("press back button", () => Game.ChildrenOfType().First().Action!.Invoke()); AddWaitStep("wait two frames", 2); } @@ -914,7 +914,7 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("wait for lounge", () => multiplayerComponents.ChildrenOfType().SingleOrDefault()?.IsLoaded == true); AddStep("open room", () => multiplayerComponents.ChildrenOfType().Single().Open()); - AddStep("press back button", () => Game.ChildrenOfType().First().Action()); + AddStep("press back button", () => Game.ChildrenOfType().First().Action!.Invoke()); AddWaitStep("wait two frames", 2); AddStep("exit lounge", () => Game.ScreenStack.Exit()); diff --git a/osu.Game.Tests/Visual/SongSelectV2/SongSelectTestScene.cs b/osu.Game.Tests/Visual/SongSelectV2/SongSelectTestScene.cs index f28527e394..97a92ff0b7 100644 --- a/osu.Game.Tests/Visual/SongSelectV2/SongSelectTestScene.cs +++ b/osu.Game.Tests/Visual/SongSelectV2/SongSelectTestScene.cs @@ -66,7 +66,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2 }, screenFooter = new ScreenFooter { - OnBack = () => Stack.CurrentScreen.Exit(), + BackButtonPressed = () => Stack.CurrentScreen.Exit(), }, logo = new OsuLogo { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs index 7aaf616767..ba3f2f637c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs @@ -13,9 +13,10 @@ namespace osu.Game.Tests.Visual.UserInterface { public partial class TestSceneBackButton : OsuTestScene { + private readonly BackButton? button; + public TestSceneBackButton() { - BackButton button; ScreenFooter.BackReceptor receptor = new ScreenFooter.BackReceptor(); Child = new Container @@ -34,14 +35,13 @@ namespace osu.Game.Tests.Visual.UserInterface }, button = new BackButton(receptor) { + Action = () => button?.Hide(), Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, } } }; - button.Action = () => button.Hide(); - AddStep("show button", () => button.Show()); AddStep("hide button", () => button.Hide()); } diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 29bac8fbae..a85a1fc926 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -1,8 +1,6 @@ // 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; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -14,11 +12,11 @@ namespace osu.Game.Graphics.UserInterface // todo: remove this once all screens migrate to display the new game footer and back button. public partial class BackButton : VisibilityContainer { - public Action Action; + public Action? Action { get; init; } private readonly TwoLayerButton button; - public BackButton(ScreenFooter.BackReceptor receptor = null) + public BackButton(ScreenFooter.BackReceptor? receptor = null) { Size = TwoLayerButton.SIZE_EXTENDED; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index cce2828b49..2bf6572362 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1105,7 +1105,7 @@ namespace osu.Game { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Action = () => ScreenFooter.OnBack?.Invoke(), + Action = handleBackButton, }, logoContainer = new Container { RelativeSizeAxes = Axes.Both }, footerBasedOverlayContent = new Container @@ -1120,14 +1120,7 @@ namespace osu.Game Child = ScreenFooter = new ScreenFooter(backReceptor) { RequestLogoInFront = inFront => ScreenContainer.ChangeChildDepth(logoContainer, inFront ? float.MinValue : 0), - OnBack = () => - { - if (!(ScreenStack.CurrentScreen is IOsuScreen currentScreen)) - return; - - if (!((Drawable)currentScreen).IsLoaded || (currentScreen.AllowUserExit && !currentScreen.OnBackButton())) - ScreenStack.Exit(); - } + BackButtonPressed = handleBackButton }, }, } @@ -1308,6 +1301,13 @@ namespace osu.Game handleStartupImport(); } + private void handleBackButton() + { + if (!(ScreenStack.CurrentScreen is IOsuScreen currentScreen)) return; + + if (!((Drawable)currentScreen).IsLoaded || (currentScreen.AllowUserExit && !currentScreen.OnBackButton())) ScreenStack.Exit(); + } + private void handleStartupImport() { if (args?.Length > 0) diff --git a/osu.Game/Screens/Footer/ScreenFooter.cs b/osu.Game/Screens/Footer/ScreenFooter.cs index b2f2903d41..fcf3cb1c8c 100644 --- a/osu.Game/Screens/Footer/ScreenFooter.cs +++ b/osu.Game/Screens/Footer/ScreenFooter.cs @@ -23,12 +23,24 @@ namespace osu.Game.Screens.Footer { public partial class ScreenFooter : OverlayContainer { + public ScreenBackButton BackButton { get; private set; } = null!; + + /// + /// Called when logo tracking begins, intended to bring the osu! logo to the frontmost visually. + /// + public Action? RequestLogoInFront { private get; init; } + + /// + /// The back button was pressed. + /// + public Action? BackButtonPressed { private get; init; } + + public const int HEIGHT = 50; + private const int padding = 60; private const float delay_per_button = 30; private const double transition_duration = 400; - public const int HEIGHT = 50; - private readonly List overlays = new List(); private Box background = null!; @@ -40,15 +52,6 @@ namespace osu.Game.Screens.Footer [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine); - [Resolved] - private OsuGame? game { get; set; } - - public ScreenBackButton BackButton { get; private set; } = null!; - - public Action? RequestLogoInFront { get; set; } - - public Action? OnBack; - public ScreenFooter(BackReceptor? receptor = null) { RelativeSizeAxes = Axes.X; @@ -144,8 +147,7 @@ namespace osu.Game.Screens.Footer { logoTrackingContainer.StopTracking(); - if (game != null) - changeLogoDepthDelegate = Scheduler.AddDelayed(() => RequestLogoInFront?.Invoke(false), transition_duration); + changeLogoDepthDelegate = Scheduler.AddDelayed(() => RequestLogoInFront?.Invoke(false), transition_duration); } protected override void PopIn() @@ -326,7 +328,7 @@ namespace osu.Game.Screens.Footer return; } - OnBack?.Invoke(); + BackButtonPressed?.Invoke(); } public partial class BackReceptor : Drawable, IKeyBindingHandler