diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 0e8e481e9d..512602d120 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -34,7 +34,7 @@ namespace osu.Game.Graphics.Containers protected virtual bool DimMainContent => true; [Resolved(CanBeNull = true)] - private OsuGame game { get; set; } + private IOverlayManager overlayManager { get; set; } [Resolved] private PreviewTrackManager previewTrackManager { get; set; } @@ -50,8 +50,8 @@ namespace osu.Game.Graphics.Containers protected override void LoadComplete() { - if (game != null) - OverlayActivationMode.BindTo(game.OverlayActivationMode); + if (overlayManager != null) + OverlayActivationMode.BindTo(overlayManager.OverlayActivationMode); OverlayActivationMode.BindValueChanged(mode => { @@ -127,14 +127,14 @@ namespace osu.Game.Graphics.Containers if (didChange) samplePopIn?.Play(); - if (BlockScreenWideMouse && DimMainContent) game?.ShowBlockingOverlay(this); + if (BlockScreenWideMouse && DimMainContent) overlayManager?.ShowBlockingOverlay(this); break; case Visibility.Hidden: if (didChange) samplePopOut?.Play(); - if (BlockScreenWideMouse) game?.HideBlockingOverlay(this); + if (BlockScreenWideMouse) overlayManager?.HideBlockingOverlay(this); break; } @@ -150,7 +150,7 @@ namespace osu.Game.Graphics.Containers protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - game?.HideBlockingOverlay(this); + overlayManager?.HideBlockingOverlay(this); } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index da8cdde944..fcf5889a7e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -63,7 +63,7 @@ namespace osu.Game /// The full osu! experience. Builds on top of to add menus and binding logic /// for initial components that are generally retrieved via DI. /// - public class OsuGame : OsuGameBase, IKeyBindingHandler, ILocalUserPlayInfo, IPerformFromScreenRunner + public class OsuGame : OsuGameBase, IKeyBindingHandler, ILocalUserPlayInfo, IPerformFromScreenRunner, IOverlayManager { /// /// The amount of global offset to apply when a left/right anchored overlay is displayed (ie. settings or notifications). @@ -184,48 +184,34 @@ namespace osu.Game SentryLogger = new SentryLogger(this); } + #region IOverlayManager + + IBindable IOverlayManager.OverlayActivationMode => OverlayActivationMode; + private void updateBlockingOverlayFade() => ScreenContainer.FadeColour(visibleBlockingOverlays.Any() ? OsuColour.Gray(0.5f) : Color4.White, 500, Easing.OutQuint); - /// - /// 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) + IDisposable IOverlayManager.RegisterBlockingOverlay(OverlayContainer overlayContainer) { if (overlayContainer.Parent != null) - throw new ArgumentException($@"Overlays registered via {nameof(RegisterBlockingOverlay)} should not be added to the scene graph."); + throw new ArgumentException($@"Overlays registered via {nameof(IOverlayManager.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."); + throw new ArgumentException($@"{overlayContainer} has already been registered via {nameof(IOverlayManager.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) + void IOverlayManager.ShowBlockingOverlay(OverlayContainer overlay) { if (!visibleBlockingOverlays.Contains(overlay)) visibleBlockingOverlays.Add(overlay); updateBlockingOverlayFade(); } - /// - /// Should be called when a blocking has been hidden and should stop blocking background input. - /// - internal void HideBlockingOverlay(OverlayContainer overlay) => Schedule(() => + void IOverlayManager.HideBlockingOverlay(OverlayContainer overlay) => Schedule(() => { visibleBlockingOverlays.Remove(overlay); updateBlockingOverlayFade(); @@ -240,6 +226,8 @@ namespace osu.Game overlayContainer.Expire(); } + #endregion + /// /// Close all game-wide overlays. /// diff --git a/osu.Game/Overlays/IOverlayManager.cs b/osu.Game/Overlays/IOverlayManager.cs new file mode 100644 index 0000000000..940ee2d8db --- /dev/null +++ b/osu.Game/Overlays/IOverlayManager.cs @@ -0,0 +1,44 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; +using osu.Game.Screens.Select; + +namespace osu.Game.Overlays +{ + [Cached] + internal interface IOverlayManager + { + /// + /// Whether overlays should be able to be opened game-wide. Value is sourced from the current active screen. + /// + IBindable OverlayActivationMode { get; } + + /// + /// 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 a game 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 . + /// + IDisposable RegisterBlockingOverlay(OverlayContainer overlayContainer); + + /// + /// Should be called when has been shown and should begin blocking background input. + /// + void ShowBlockingOverlay(OverlayContainer overlay); + + /// + /// Should be called when a blocking has been hidden and should stop blocking background input. + /// + void HideBlockingOverlay(OverlayContainer overlay); + } +} diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 5b892e1925..b7a9b45bb8 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -58,8 +58,8 @@ namespace osu.Game.Screens.OnlinePlay.Match protected readonly IBindable RoomId = new Bindable(); - [Resolved] - private OsuGame game { get; set; } + [Resolved(CanBeNull = true)] + private IOverlayManager overlayManager { get; set; } [Resolved] private MusicController music { get; set; } @@ -264,7 +264,7 @@ namespace osu.Game.Screens.OnlinePlay.Match beatmapAvailabilityTracker.SelectedItem.BindTo(SelectedItem); beatmapAvailabilityTracker.Availability.BindValueChanged(_ => updateWorkingBeatmap()); - userModsSelectOverlayRegistration = game?.RegisterBlockingOverlay(userModsSelectOverlay); + userModsSelectOverlayRegistration = overlayManager?.RegisterBlockingOverlay(userModsSelectOverlay); } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs index 659084addf..c262544d6c 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs @@ -53,7 +53,7 @@ namespace osu.Game.Screens.OnlinePlay private IReadOnlyList initialMods; private bool itemSelected; - private FreeModSelectScreen freeModSelectOverlay; + private readonly FreeModSelectScreen freeModSelectOverlay; private IDisposable freeModSelectOverlayRegistration; protected OnlinePlaySongSelect(Room room) @@ -98,7 +98,7 @@ namespace osu.Game.Screens.OnlinePlay Mods.BindValueChanged(onModsChanged); Ruleset.BindValueChanged(onRulesetChanged); - freeModSelectOverlayRegistration = Game?.RegisterBlockingOverlay(freeModSelectOverlay); + freeModSelectOverlayRegistration = OverlayManager?.RegisterBlockingOverlay(freeModSelectOverlay); } private void onModsChanged(ValueChangedEvent> mods) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 55d28ec8a4..bb2746ee95 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -124,7 +124,7 @@ namespace osu.Game.Screens.Select private MusicController music { get; set; } [Resolved(CanBeNull = true)] - protected new OsuGame Game { get; private set; } + internal IOverlayManager OverlayManager { get; private set; } [BackgroundDependencyLoader(true)] private void load(AudioManager audio, IDialogOverlay dialog, OsuColour colours, ManageCollectionsDialog manageCollectionsDialog, DifficultyRecommender recommender) @@ -315,7 +315,7 @@ namespace osu.Game.Screens.Select { base.LoadComplete(); - modSelectOverlayRegistration = Game?.RegisterBlockingOverlay(ModSelect); + modSelectOverlayRegistration = OverlayManager?.RegisterBlockingOverlay(ModSelect); } ///