From bd8409219f079bcdd922ae2169d676608e512364 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 8 Nov 2023 06:37:29 +0300 Subject: [PATCH] Unload beatmap storyboard background when no longer present --- .../BeatmapBackgroundWithStoryboard.cs | 50 +++++++++++++++++-- osu.Game/Screens/BackgroundScreen.cs | 3 +- osu.Game/Screens/BackgroundScreenStack.cs | 3 ++ .../Backgrounds/BackgroundScreenDefault.cs | 22 ++++++++ 4 files changed, 72 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/Backgrounds/BeatmapBackgroundWithStoryboard.cs b/osu.Game/Graphics/Backgrounds/BeatmapBackgroundWithStoryboard.cs index 9c0d109ce4..e78a93396e 100644 --- a/osu.Game/Graphics/Backgrounds/BeatmapBackgroundWithStoryboard.cs +++ b/osu.Game/Graphics/Backgrounds/BeatmapBackgroundWithStoryboard.cs @@ -1,15 +1,21 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Threading; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Overlays; using osu.Game.Rulesets.Mods; +using osu.Game.Screens; using osu.Game.Storyboards.Drawables; namespace osu.Game.Graphics.Backgrounds @@ -18,6 +24,10 @@ namespace osu.Game.Graphics.Backgrounds { private readonly InterpolatingFramedClock storyboardClock; + private AudioContainer storyboardContainer = null!; + private DrawableStoryboard? drawableStoryboard; + private CancellationTokenSource? loadCancellationSource = new CancellationTokenSource(); + [Resolved(CanBeNull = true)] private MusicController? musicController { get; set; } @@ -33,18 +43,48 @@ namespace osu.Game.Graphics.Backgrounds [BackgroundDependencyLoader] private void load() { + AddInternal(storyboardContainer = new AudioContainer + { + RelativeSizeAxes = Axes.Both, + Volume = { Value = 0 }, + }); + + LoadStoryboard(); + } + + public void LoadStoryboard() + { + Debug.Assert(drawableStoryboard == null); + if (!Beatmap.Storyboard.HasDrawable) return; if (Beatmap.Storyboard.ReplacesBackground) Sprite.Alpha = 0; - LoadComponentAsync(new AudioContainer + LoadComponentAsync(drawableStoryboard = new DrawableStoryboard(Beatmap.Storyboard, mods.Value) { - RelativeSizeAxes = Axes.Both, - Volume = { Value = 0 }, - Child = new DrawableStoryboard(Beatmap.Storyboard, mods.Value) { Clock = storyboardClock } - }, AddInternal); + Clock = storyboardClock + }, s => + { + storyboardContainer.FadeInFromZero(BackgroundScreen.TRANSITION_LENGTH, Easing.OutQuint); + storyboardContainer.Add(s); + }, (loadCancellationSource = new CancellationTokenSource()).Token); + } + + public void UnloadStoryboard(Action scheduleStoryboardRemoval) + { + Debug.Assert(drawableStoryboard != null); + + loadCancellationSource.AsNonNull().Cancel(); + loadCancellationSource = null; + + DrawableStoryboard s = drawableStoryboard; + + storyboardContainer.FadeOut(BackgroundScreen.TRANSITION_LENGTH, Easing.OutQuint); + scheduleStoryboardRemoval(s); + + drawableStoryboard = null; } protected override void LoadComplete() diff --git a/osu.Game/Screens/BackgroundScreen.cs b/osu.Game/Screens/BackgroundScreen.cs index a7502f22d5..73af9b1bf2 100644 --- a/osu.Game/Screens/BackgroundScreen.cs +++ b/osu.Game/Screens/BackgroundScreen.cs @@ -13,7 +13,8 @@ namespace osu.Game.Screens { public abstract partial class BackgroundScreen : Screen, IEquatable { - protected const float TRANSITION_LENGTH = 500; + public const float TRANSITION_LENGTH = 500; + private const float x_movement_amount = 50; private readonly bool animateOnEnter; diff --git a/osu.Game/Screens/BackgroundScreenStack.cs b/osu.Game/Screens/BackgroundScreenStack.cs index 99ca383b9f..3ec1835669 100644 --- a/osu.Game/Screens/BackgroundScreenStack.cs +++ b/osu.Game/Screens/BackgroundScreenStack.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Screens; +using osu.Game.Storyboards.Drawables; namespace osu.Game.Screens { @@ -33,5 +34,7 @@ namespace osu.Game.Screens base.Push(screen); return true; } + + public void ScheduleStoryboardDisposal(DrawableStoryboard storyboard) => Scheduler.AddDelayed(storyboard.RemoveAndDisposeImmediately, BackgroundScreen.TRANSITION_LENGTH); } } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index d9554c10e2..66835363b4 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -3,11 +3,14 @@ #nullable disable +using System.Diagnostics; using System.Threading; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Logging; +using osu.Framework.Screens; using osu.Framework.Threading; using osu.Framework.Utils; using osu.Game.Beatmaps; @@ -71,6 +74,25 @@ namespace osu.Game.Screens.Backgrounds void next() => Next(); } + public override void OnSuspending(ScreenTransitionEvent e) + { + var backgroundScreenStack = Parent as BackgroundScreenStack; + Debug.Assert(backgroundScreenStack != null); + + if (background is BeatmapBackgroundWithStoryboard storyboardBackground) + storyboardBackground.UnloadStoryboard(backgroundScreenStack.ScheduleStoryboardDisposal); + + base.OnSuspending(e); + } + + public override void OnResuming(ScreenTransitionEvent e) + { + if (background is BeatmapBackgroundWithStoryboard storyboardBackground) + storyboardBackground.LoadStoryboard(); + + base.OnResuming(e); + } + private ScheduledDelegate nextTask; private CancellationTokenSource cancellationTokenSource;