Extract interface for overlay management

This commit is contained in:
Bartłomiej Dach 2022-05-05 15:47:10 +02:00
parent 66473972da
commit a56eab2c47
No known key found for this signature in database
GPG Key ID: BCECCD4FA41F6497
6 changed files with 69 additions and 37 deletions

View File

@ -34,7 +34,7 @@ public abstract class OsuFocusedOverlayContainer : FocusedOverlayContainer, IPre
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 @@ private void load(AudioManager audio)
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 @@ protected override void UpdateState(ValueChangedEvent<Visibility> state)
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 @@ protected override void PopOut()
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
game?.HideBlockingOverlay(this);
overlayManager?.HideBlockingOverlay(this);
}
}
}

View File

@ -63,7 +63,7 @@ namespace osu.Game
/// The full osu! experience. Builds on top of <see cref="OsuGameBase"/> to add menus and binding logic
/// for initial components that are generally retrieved via DI.
/// </summary>
public class OsuGame : OsuGameBase, IKeyBindingHandler<GlobalAction>, ILocalUserPlayInfo, IPerformFromScreenRunner
public class OsuGame : OsuGameBase, IKeyBindingHandler<GlobalAction>, ILocalUserPlayInfo, IPerformFromScreenRunner, IOverlayManager
{
/// <summary>
/// The amount of global offset to apply when a left/right anchored overlay is displayed (ie. settings or notifications).
@ -184,48 +184,34 @@ public OsuGame(string[] args = null)
SentryLogger = new SentryLogger(this);
}
#region IOverlayManager
IBindable<OverlayActivation> IOverlayManager.OverlayActivationMode => OverlayActivationMode;
private void updateBlockingOverlayFade() =>
ScreenContainer.FadeColour(visibleBlockingOverlays.Any() ? OsuColour.Gray(0.5f) : Color4.White, 500, Easing.OutQuint);
/// <summary>
/// Registers a blocking <see cref="OverlayContainer"/> that was not created by <see cref="OsuGame"/> itself for later use.
/// </summary>
/// <remarks>
/// The goal of this method is to allow child screens, like <see cref="SongSelect"/> 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.
/// </remarks>
/// <returns>
/// An <see cref="IDisposable"/> that should be disposed of when the <paramref name="overlayContainer"/> should be unregistered.
/// Disposing of this <see cref="IDisposable"/> will automatically expire the <paramref name="overlayContainer"/>.
/// </returns>
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));
}
/// <summary>
/// Should be called when <paramref name="overlay"/> has been shown and should begin blocking background input.
/// </summary>
internal void ShowBlockingOverlay(OverlayContainer overlay)
void IOverlayManager.ShowBlockingOverlay(OverlayContainer overlay)
{
if (!visibleBlockingOverlays.Contains(overlay))
visibleBlockingOverlays.Add(overlay);
updateBlockingOverlayFade();
}
/// <summary>
/// Should be called when a blocking <paramref name="overlay"/> has been hidden and should stop blocking background input.
/// </summary>
internal void HideBlockingOverlay(OverlayContainer overlay) => Schedule(() =>
void IOverlayManager.HideBlockingOverlay(OverlayContainer overlay) => Schedule(() =>
{
visibleBlockingOverlays.Remove(overlay);
updateBlockingOverlayFade();
@ -240,6 +226,8 @@ private void unregisterBlockingOverlay(OverlayContainer overlayContainer)
overlayContainer.Expire();
}
#endregion
/// <summary>
/// Close all game-wide overlays.
/// </summary>

View File

@ -0,0 +1,44 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. 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
{
/// <summary>
/// Whether overlays should be able to be opened game-wide. Value is sourced from the current active screen.
/// </summary>
IBindable<OverlayActivation> OverlayActivationMode { get; }
/// <summary>
/// Registers a blocking <see cref="OverlayContainer"/> that was not created by <see cref="OsuGame"/> itself for later use.
/// </summary>
/// <remarks>
/// The goal of this method is to allow child screens, like <see cref="SongSelect"/> 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.
/// </remarks>
/// <returns>
/// An <see cref="IDisposable"/> that should be disposed of when the <paramref name="overlayContainer"/> should be unregistered.
/// Disposing of this <see cref="IDisposable"/> will automatically expire the <paramref name="overlayContainer"/>.
/// </returns>
IDisposable RegisterBlockingOverlay(OverlayContainer overlayContainer);
/// <summary>
/// Should be called when <paramref name="overlay"/> has been shown and should begin blocking background input.
/// </summary>
void ShowBlockingOverlay(OverlayContainer overlay);
/// <summary>
/// Should be called when a blocking <paramref name="overlay"/> has been hidden and should stop blocking background input.
/// </summary>
void HideBlockingOverlay(OverlayContainer overlay);
}
}

View File

@ -58,8 +58,8 @@ public abstract class RoomSubScreen : OnlinePlaySubScreen, IPreviewTrackOwner
protected readonly IBindable<long?> RoomId = new Bindable<long?>();
[Resolved]
private OsuGame game { get; set; }
[Resolved(CanBeNull = true)]
private IOverlayManager overlayManager { get; set; }
[Resolved]
private MusicController music { get; set; }
@ -264,7 +264,7 @@ protected override void LoadComplete()
beatmapAvailabilityTracker.SelectedItem.BindTo(SelectedItem);
beatmapAvailabilityTracker.Availability.BindValueChanged(_ => updateWorkingBeatmap());
userModsSelectOverlayRegistration = game?.RegisterBlockingOverlay(userModsSelectOverlay);
userModsSelectOverlayRegistration = overlayManager?.RegisterBlockingOverlay(userModsSelectOverlay);
}
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)

View File

@ -53,7 +53,7 @@ public abstract class OnlinePlaySongSelect : SongSelect, IOnlinePlaySubScreen
private IReadOnlyList<Mod> initialMods;
private bool itemSelected;
private FreeModSelectScreen freeModSelectOverlay;
private readonly FreeModSelectScreen freeModSelectOverlay;
private IDisposable freeModSelectOverlayRegistration;
protected OnlinePlaySongSelect(Room room)
@ -98,7 +98,7 @@ protected override void LoadComplete()
Mods.BindValueChanged(onModsChanged);
Ruleset.BindValueChanged(onRulesetChanged);
freeModSelectOverlayRegistration = Game?.RegisterBlockingOverlay(freeModSelectOverlay);
freeModSelectOverlayRegistration = OverlayManager?.RegisterBlockingOverlay(freeModSelectOverlay);
}
private void onModsChanged(ValueChangedEvent<IReadOnlyList<Mod>> mods)

View File

@ -124,7 +124,7 @@ public abstract class SongSelect : ScreenWithBeatmapBackground, IKeyBindingHandl
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 @@ protected override void LoadComplete()
{
base.LoadComplete();
modSelectOverlayRegistration = Game?.RegisterBlockingOverlay(ModSelect);
modSelectOverlayRegistration = OverlayManager?.RegisterBlockingOverlay(ModSelect);
}
/// <summary>