From 1744d7e4f0cd7130b0dad22da73bb708d9295c96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 4 May 2022 21:53:04 +0200 Subject: [PATCH] Fix new mod select overlay dimming itself --- .../Containers/OsuFocusedOverlayContainer.cs | 6 +-- osu.Game/OsuGame.cs | 45 ++++++++++++++++++- osu.Game/Screens/Select/SongSelect.cs | 21 ++++++++- 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 68351acd7e..0e8e481e9d 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -127,14 +127,14 @@ namespace osu.Game.Graphics.Containers if (didChange) samplePopIn?.Play(); - if (BlockScreenWideMouse && DimMainContent) game?.AddBlockingOverlay(this); + if (BlockScreenWideMouse && DimMainContent) game?.ShowBlockingOverlay(this); break; case Visibility.Hidden: if (didChange) samplePopOut?.Play(); - if (BlockScreenWideMouse) game?.RemoveBlockingOverlay(this); + if (BlockScreenWideMouse) game?.HideBlockingOverlay(this); break; } @@ -150,7 +150,7 @@ namespace osu.Game.Graphics.Containers protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - game?.RemoveBlockingOverlay(this); + game?.HideBlockingOverlay(this); } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e9fe8c43de..da8cdde944 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -171,6 +171,7 @@ namespace osu.Game private readonly string[] args; private readonly List focusedOverlays = new List(); + private readonly List externalOverlays = new List(); private readonly List visibleBlockingOverlays = new List(); @@ -186,19 +187,59 @@ namespace osu.Game private void updateBlockingOverlayFade() => ScreenContainer.FadeColour(visibleBlockingOverlays.Any() ? OsuColour.Gray(0.5f) : Color4.White, 500, Easing.OutQuint); - public void AddBlockingOverlay(OverlayContainer overlay) + /// + /// Registers a blocking that was not created by itself for later use. + /// + /// + /// The goal of this method is to allow child screens, like to register their own full-screen blocking overlays + /// with background dim. + /// In those cases, for the dim to work correctly, the overlays need to be added at the `OsuGame` level directly, rather as children of the screens. + /// + /// + /// An that should be disposed of when the should be unregistered. + /// Disposing of this will automatically expire the . + /// + internal IDisposable RegisterBlockingOverlay(OverlayContainer overlayContainer) + { + if (overlayContainer.Parent != null) + throw new ArgumentException($@"Overlays registered via {nameof(RegisterBlockingOverlay)} should not be added to the scene graph."); + + if (externalOverlays.Contains(overlayContainer)) + throw new ArgumentException($@"{overlayContainer} has already been registered via {nameof(RegisterBlockingOverlay)} once."); + + externalOverlays.Add(overlayContainer); + overlayContent.Add(overlayContainer); + return new InvokeOnDisposal(() => unregisterBlockingOverlay(overlayContainer)); + } + + /// + /// Should be called when has been shown and should begin blocking background input. + /// + internal void ShowBlockingOverlay(OverlayContainer overlay) { if (!visibleBlockingOverlays.Contains(overlay)) visibleBlockingOverlays.Add(overlay); updateBlockingOverlayFade(); } - public void RemoveBlockingOverlay(OverlayContainer overlay) => Schedule(() => + /// + /// Should be called when a blocking has been hidden and should stop blocking background input. + /// + internal void HideBlockingOverlay(OverlayContainer overlay) => Schedule(() => { visibleBlockingOverlays.Remove(overlay); updateBlockingOverlayFade(); }); + /// + /// Unregisters a blocking that was not created by itself. + /// + private void unregisterBlockingOverlay(OverlayContainer overlayContainer) + { + externalOverlays.Remove(overlayContainer); + overlayContainer.Expire(); + } + /// /// Close all game-wide overlays. /// diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 3c46433b45..448e702b96 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -35,6 +35,7 @@ using osu.Framework.Input.Bindings; using osu.Game.Collections; using osu.Game.Graphics.UserInterface; using System.Diagnostics; +using JetBrains.Annotations; using osu.Game.Screens.Play; using osu.Game.Database; using osu.Game.Skinning; @@ -116,9 +117,15 @@ namespace osu.Game.Screens.Select private double audioFeedbackLastPlaybackTime; + [CanBeNull] + private IDisposable modSelectOverlayRegistration; + [Resolved] private MusicController music { get; set; } + [Resolved(CanBeNull = true)] + private OsuGame game { get; set; } + [BackgroundDependencyLoader(true)] private void load(AudioManager audio, IDialogOverlay dialog, OsuColour colours, ManageCollectionsDialog manageCollectionsDialog, DifficultyRecommender recommender) { @@ -264,10 +271,13 @@ namespace osu.Game.Screens.Select } }, Footer = new Footer(), - ModSelect = CreateModSelectOverlay() }); } + // preload the mod select overlay for later use in `LoadComplete()`. + // therein it will be registered at the `OsuGame` level to properly function as a blocking overlay. + LoadComponent(ModSelect = CreateModSelectOverlay()); + if (Footer != null) { foreach (var (button, overlay) in CreateFooterButtons()) @@ -301,6 +311,13 @@ namespace osu.Game.Screens.Select } } + protected override void LoadComplete() + { + base.LoadComplete(); + + modSelectOverlayRegistration = game?.RegisterBlockingOverlay(ModSelect); + } + /// /// Creates the buttons to be displayed in the footer. /// @@ -700,6 +717,8 @@ namespace osu.Game.Screens.Select if (music != null) music.TrackChanged -= ensureTrackLooping; + + modSelectOverlayRegistration?.Dispose(); } ///