From 435128ebaa534401f927fd2d7364b01c4b9a950a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Jun 2025 15:16:29 +0900 Subject: [PATCH] Update logo tracking operations to use `IDisposable` flow --- .../TestSceneLogoTrackingContainer.cs | 9 ++++++-- .../Containers/LogoTrackingContainer.cs | 22 +++++++++++-------- osu.Game/Screens/Footer/ScreenFooter.cs | 7 ++++-- osu.Game/Screens/Menu/ButtonSystem.cs | 11 ++++++---- osu.Game/Screens/Play/PlayerLoader.cs | 15 +++++++++---- 5 files changed, 43 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs index 8d5c961265..931b5afa12 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs @@ -5,6 +5,7 @@ using System; using System.Linq; +using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -28,6 +29,9 @@ namespace osu.Game.Tests.Visual.UserInterface private Drawable logoFacade; private bool randomPositions; + [CanBeNull] + private IDisposable logoTracking; + private const float visual_box_size = 72; [SetUpSteps] @@ -150,14 +154,15 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Perform logo movements", () => { - trackingContainer.StopTracking(); + logoTracking?.Dispose(); + logo.MoveTo(new Vector2(0.5f), 500, Easing.InOutExpo); visualBox.Colour = Color4.White; Scheduler.AddDelayed(() => { - trackingContainer.StartTracking(logo, 1000, Easing.InOutExpo); + logoTracking = trackingContainer.StartTracking(logo, 1000, Easing.InOutExpo); visualBox.Colour = Color4.Tomato; }, 700); }); diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index 6819d97bc5..25ad526af6 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Utils; @@ -32,7 +34,7 @@ namespace osu.Game.Graphics.Containers /// The instance of the logo to be used for tracking. /// The duration of the initial transform. Default is instant. /// The easing type of the initial transform. - public void StartTracking(OsuLogo logo, double duration = 0, Easing easing = Easing.None) + public IDisposable StartTracking(OsuLogo logo, double duration = 0, Easing easing = Easing.None) { if (Logo != null && Logo != logo) throw new InvalidOperationException("A different logo is already being tracked."); @@ -50,19 +52,21 @@ namespace osu.Game.Graphics.Containers startTime = null; startPosition = null; + + return new InvokeOnDisposal(stopTracking); + + void stopTracking() + { + Debug.Assert(Logo != null); + + Logo.IsTracking = false; + Logo = null; + } } /// /// Stops the logo assigned in from tracking the facade's position. /// - public void StopTracking() - { - if (Logo == null) return; - - Logo.IsTracking = false; - Logo = null; - } - /// /// Gets the position that the logo should move to with respect to the . /// Manually performs a conversion of the Facade's position to the Logo's parent's relative space. diff --git a/osu.Game/Screens/Footer/ScreenFooter.cs b/osu.Game/Screens/Footer/ScreenFooter.cs index 1baa4ae0ef..7fd5e8537a 100644 --- a/osu.Game/Screens/Footer/ScreenFooter.cs +++ b/osu.Game/Screens/Footer/ScreenFooter.cs @@ -48,7 +48,9 @@ namespace osu.Game.Screens.Footer private FillFlowContainer buttonsFlow = null!; private Container footerContentContainer = null!; private Container hiddenButtonsContainer = null!; + private LogoTrackingContainer logoTrackingContainer = null!; + private IDisposable? logoTracking; // TODO: This has some weird update logic local in this class, but it only works for overlay containers. // This is not what we want. The footer is to be displayed on *screens* with different colour schemes. @@ -145,13 +147,14 @@ namespace osu.Game.Screens.Footer changeLogoDepthDelegate?.Cancel(); changeLogoDepthDelegate = null; - logoTrackingContainer.StartTracking(logo, duration, easing); + logoTracking = logoTrackingContainer.StartTracking(logo, duration, easing); RequestLogoInFront?.Invoke(true); } public void StopTrackingLogo() { - logoTrackingContainer.StopTracking(); + logoTracking?.Dispose(); + logoTracking = null; changeLogoDepthDelegate = Scheduler.AddDelayed(() => RequestLogoInFront?.Invoke(false), transition_duration); } diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 25fa689d4c..4e41f4f35f 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -73,7 +73,8 @@ namespace osu.Game.Screens.Menu else { // We should stop tracking as the facade is now out of scope. - logoTrackingContainer.StopTracking(); + logoTracking?.Dispose(); + logoTracking = null; } } @@ -390,6 +391,7 @@ namespace osu.Game.Screens.Menu } private ScheduledDelegate? logoDelayedAction; + private IDisposable? logoTracking; private void updateLogoState(ButtonSystemState lastState = ButtonSystemState.Initial) { @@ -402,7 +404,8 @@ namespace osu.Game.Screens.Menu logoDelayedAction?.Cancel(); logoDelayedAction = Scheduler.AddDelayed(() => { - logoTrackingContainer.StopTracking(); + logoTracking?.Dispose(); + logoTracking = null; game?.Toolbar.Hide(); @@ -429,7 +432,7 @@ namespace osu.Game.Screens.Menu logo.ScaleTo(0.5f, 200, Easing.In); - logoTrackingContainer.StartTracking(logo, 200, Easing.In); + logoTracking = logoTrackingContainer.StartTracking(logo, 200, Easing.In); logoDelayedAction?.Cancel(); logoDelayedAction = Scheduler.AddDelayed(() => @@ -451,7 +454,7 @@ namespace osu.Game.Screens.Menu break; case ButtonSystemState.EnteringMode: - logoTrackingContainer.StartTracking(logo, lastState == ButtonSystemState.Initial ? MainMenu.FADE_OUT_DURATION : 0, Easing.InSine); + logoTracking = logoTrackingContainer.StartTracking(logo, lastState == ButtonSystemState.Initial ? MainMenu.FADE_OUT_DURATION : 0, Easing.InSine); break; } } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index d22717abd4..94148c13d0 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -144,6 +144,7 @@ namespace osu.Game.Screens.Play private bool playerConsumed; private LogoTrackingContainer content = null!; + private IDisposable? logoTracking; private bool hideOverlays; @@ -379,21 +380,26 @@ namespace osu.Game.Screens.Play Scheduler.AddDelayed(() => { if (this.IsCurrentScreen()) - content.StartTracking(logo, resuming ? 0 : 500, Easing.InOutExpo); + logoTracking = content.StartTracking(logo, resuming ? 0 : 500, Easing.InOutExpo); }, resuming ? 0 : 250); } protected override void LogoExiting(OsuLogo logo) { base.LogoExiting(logo); - content.StopTracking(); + + logoTracking?.Dispose(); + logoTracking = null; + osuLogo = null; } protected override void LogoSuspending(OsuLogo logo) { base.LogoSuspending(logo); - content.StopTracking(); + + logoTracking?.Dispose(); + logoTracking = null; logo .FadeOut(CONTENT_OUT_DURATION / 2, Easing.OutQuint) @@ -538,7 +544,8 @@ namespace osu.Game.Screens.Play protected virtual void ContentOut() { // Ensure the logo is no longer tracking before we scale the content - content.StopTracking(); + logoTracking?.Dispose(); + logoTracking = null; content.ScaleTo(0.7f, CONTENT_OUT_DURATION * 2, Easing.OutQuint); content.FadeOut(CONTENT_OUT_DURATION, Easing.OutQuint)