mirror of
https://github.com/ppy/osu.git
synced 2025-01-28 04:42:58 +08:00
Merge pull request #18111 from bdach/mod-overlay/integration
Replace old mod overlay with new design
This commit is contained in:
commit
3bb22dece6
@ -1,7 +1,6 @@
|
||||
// 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.Linq;
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
@ -283,7 +282,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
AddUntilStep("Song select has selection", () => songSelect.Carousel?.SelectedBeatmapInfo != null);
|
||||
AddStep("Set default user settings", () =>
|
||||
{
|
||||
SelectedMods.Value = SelectedMods.Value.Concat(new[] { new OsuModNoFail() }).ToArray();
|
||||
SelectedMods.Value = new[] { new OsuModNoFail() };
|
||||
songSelect.DimLevel.Value = 0.7f;
|
||||
songSelect.BlurLevel.Value = 0.4f;
|
||||
});
|
||||
|
@ -627,7 +627,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
AddStep("invoke on back button", () => multiplayerComponents.OnBackButton());
|
||||
|
||||
AddAssert("mod overlay is hidden", () => this.ChildrenOfType<UserModSelectOverlay>().Single().State.Value == Visibility.Hidden);
|
||||
AddAssert("mod overlay is hidden", () => this.ChildrenOfType<UserModSelectScreen>().Single().State.Value == Visibility.Hidden);
|
||||
|
||||
AddAssert("dialog overlay is hidden", () => DialogOverlay.State.Value == Visibility.Hidden);
|
||||
|
||||
|
@ -132,7 +132,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
private void assertHasFreeModButton(Type type, bool hasButton = true)
|
||||
{
|
||||
AddAssert($"{type.ReadableName()} {(hasButton ? "displayed" : "not displayed")} in freemod overlay",
|
||||
() => songSelect.ChildrenOfType<FreeModSelectOverlay>().Single().ChildrenOfType<ModButton>().All(b => b.Mod.GetType() != type));
|
||||
() => this.ChildrenOfType<FreeModSelectScreen>()
|
||||
.Single()
|
||||
.ChildrenOfType<ModPanel>()
|
||||
.Where(panel => !panel.Filtered.Value)
|
||||
.All(b => b.Mod.GetType() != type));
|
||||
}
|
||||
|
||||
private class TestMultiplayerMatchSongSelect : MultiplayerMatchSongSelect
|
||||
|
@ -168,8 +168,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
ClickButtonWhenEnabled<RoomSubScreen.UserModSelectButton>();
|
||||
|
||||
AddUntilStep("mod select contents loaded",
|
||||
() => this.ChildrenOfType<ModColumn>().Any() && this.ChildrenOfType<ModColumn>().All(col => col.IsLoaded && col.ItemsLoaded));
|
||||
AddUntilStep("mod select contains only double time mod",
|
||||
() => this.ChildrenOfType<UserModSelectOverlay>().SingleOrDefault()?.ChildrenOfType<ModButton>().SingleOrDefault()?.Mod is OsuModDoubleTime);
|
||||
() => this.ChildrenOfType<UserModSelectScreen>()
|
||||
.SingleOrDefault()?
|
||||
.ChildrenOfType<ModPanel>()
|
||||
.SingleOrDefault(panel => !panel.Filtered.Value)?.Mod is OsuModDoubleTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -253,12 +253,12 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show());
|
||||
AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible);
|
||||
AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(backButtonPosition));
|
||||
|
||||
// BackButton handles hover using its child button, so this checks whether or not any of BackButton's children are hovered.
|
||||
AddUntilStep("Back button is hovered", () => Game.ChildrenOfType<BackButton>().First().Children.Any(c => c.IsHovered));
|
||||
AddStep("Move mouse to dimmed area", () => InputManager.MoveMouseTo(new Vector2(
|
||||
songSelect.ScreenSpaceDrawQuad.TopLeft.X + 1,
|
||||
songSelect.ScreenSpaceDrawQuad.TopLeft.Y + songSelect.ScreenSpaceDrawQuad.Height / 2)));
|
||||
AddStep("Click left mouse button", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
AddStep("Click back button", () => InputManager.Click(MouseButton.Left));
|
||||
AddUntilStep("Overlay was hidden", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden);
|
||||
exitViaBackButtonAndConfirm();
|
||||
}
|
||||
@ -551,7 +551,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
public class TestPlaySongSelect : PlaySongSelect
|
||||
{
|
||||
public ModSelectOverlay ModSelectOverlay => ModSelect;
|
||||
public ModSelectScreen ModSelectOverlay => ModSelect;
|
||||
|
||||
public BeatmapOptionsOverlay BeatmapOptionsOverlay => BeatmapOptions;
|
||||
|
||||
|
@ -8,6 +8,7 @@ using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
@ -18,6 +19,7 @@ using osu.Game.Extensions;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
@ -918,6 +920,19 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
AddAssert("check ruleset is correct for score", () => Ruleset.Value.OnlineID == 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestModOverlayToggling()
|
||||
{
|
||||
changeRuleset(0);
|
||||
createSongSelect();
|
||||
|
||||
AddStep("toggle mod overlay on", () => InputManager.Key(Key.F1));
|
||||
AddUntilStep("mod overlay shown", () => songSelect.ModSelect.State.Value == Visibility.Visible);
|
||||
|
||||
AddStep("toggle mod overlay off", () => InputManager.Key(Key.F1));
|
||||
AddUntilStep("mod overlay hidden", () => songSelect.ModSelect.State.Value == Visibility.Hidden);
|
||||
}
|
||||
|
||||
private void waitForInitialSelection()
|
||||
{
|
||||
AddUntilStep("wait for initial selection", () => !Beatmap.IsDefault);
|
||||
@ -993,6 +1008,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
public WorkingBeatmap CurrentBeatmap => Beatmap.Value;
|
||||
public IWorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap;
|
||||
public new BeatmapCarousel Carousel => base.Carousel;
|
||||
public new ModSelectScreen ModSelect => base.ModSelect;
|
||||
|
||||
public new void PresentScore(ScoreInfo score) => base.PresentScore(score);
|
||||
|
||||
|
@ -66,7 +66,10 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
public class TestShearedOverlayContainer : ShearedOverlayContainer
|
||||
{
|
||||
protected override OverlayColourScheme ColourScheme => OverlayColourScheme.Green;
|
||||
public TestShearedOverlayContainer()
|
||||
: base(OverlayColourScheme.Green)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
|
@ -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?.AddBlockingOverlay(this);
|
||||
if (BlockScreenWideMouse && DimMainContent) overlayManager?.ShowBlockingOverlay(this);
|
||||
break;
|
||||
|
||||
case Visibility.Hidden:
|
||||
if (didChange)
|
||||
samplePopOut?.Play();
|
||||
|
||||
if (BlockScreenWideMouse) game?.RemoveBlockingOverlay(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?.RemoveBlockingOverlay(this);
|
||||
overlayManager?.HideBlockingOverlay(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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).
|
||||
@ -171,6 +171,7 @@ namespace osu.Game
|
||||
private readonly string[] args;
|
||||
|
||||
private readonly List<OsuFocusedOverlayContainer> focusedOverlays = new List<OsuFocusedOverlayContainer>();
|
||||
private readonly List<OverlayContainer> externalOverlays = new List<OverlayContainer>();
|
||||
|
||||
private readonly List<OverlayContainer> visibleBlockingOverlays = new List<OverlayContainer>();
|
||||
|
||||
@ -183,22 +184,50 @@ namespace osu.Game
|
||||
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);
|
||||
|
||||
public void AddBlockingOverlay(OverlayContainer overlay)
|
||||
IDisposable IOverlayManager.RegisterBlockingOverlay(OverlayContainer overlayContainer)
|
||||
{
|
||||
if (overlayContainer.Parent != null)
|
||||
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(IOverlayManager.RegisterBlockingOverlay)} once.");
|
||||
|
||||
externalOverlays.Add(overlayContainer);
|
||||
overlayContent.Add(overlayContainer);
|
||||
return new InvokeOnDisposal(() => unregisterBlockingOverlay(overlayContainer));
|
||||
}
|
||||
|
||||
void IOverlayManager.ShowBlockingOverlay(OverlayContainer overlay)
|
||||
{
|
||||
if (!visibleBlockingOverlays.Contains(overlay))
|
||||
visibleBlockingOverlays.Add(overlay);
|
||||
updateBlockingOverlayFade();
|
||||
}
|
||||
|
||||
public void RemoveBlockingOverlay(OverlayContainer overlay) => Schedule(() =>
|
||||
void IOverlayManager.HideBlockingOverlay(OverlayContainer overlay) => Schedule(() =>
|
||||
{
|
||||
visibleBlockingOverlays.Remove(overlay);
|
||||
updateBlockingOverlayFade();
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters a blocking <see cref="OverlayContainer"/> that was not created by <see cref="OsuGame"/> itself.
|
||||
/// </summary>
|
||||
private void unregisterBlockingOverlay(OverlayContainer overlayContainer)
|
||||
{
|
||||
externalOverlays.Remove(overlayContainer);
|
||||
overlayContainer.Expire();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Close all game-wide overlays.
|
||||
/// </summary>
|
||||
|
@ -31,8 +31,6 @@ namespace osu.Game.Overlays
|
||||
[Cached]
|
||||
public class FirstRunSetupOverlay : ShearedOverlayContainer
|
||||
{
|
||||
protected override OverlayColourScheme ColourScheme => OverlayColourScheme.Purple;
|
||||
|
||||
[Resolved]
|
||||
private IPerformFromScreenRunner performer { get; set; } = null!;
|
||||
|
||||
@ -70,6 +68,11 @@ namespace osu.Game.Overlays
|
||||
|
||||
private Container content = null!;
|
||||
|
||||
public FirstRunSetupOverlay()
|
||||
: base(OverlayColourScheme.Purple)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
|
44
osu.Game/Overlays/IOverlayManager.cs
Normal file
44
osu.Game/Overlays/IOverlayManager.cs
Normal 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);
|
||||
}
|
||||
}
|
@ -41,7 +41,7 @@ namespace osu.Game.Overlays.Mods
|
||||
private Func<Mod, bool>? filter;
|
||||
|
||||
/// <summary>
|
||||
/// Function determining whether each mod in the column should be displayed.
|
||||
/// A function determining whether each mod in the column should be displayed.
|
||||
/// A return value of <see langword="true"/> means that the mod is not filtered and therefore its corresponding panel should be displayed.
|
||||
/// A return value of <see langword="false"/> means that the mod is filtered out and therefore its corresponding panel should be hidden.
|
||||
/// </summary>
|
||||
@ -250,9 +250,8 @@ namespace osu.Game.Overlays.Mods
|
||||
private void load(OsuGameBase game, OverlayColourProvider colourProvider, OsuColour colours)
|
||||
{
|
||||
availableMods.BindTo(game.AvailableMods);
|
||||
// this `BindValueChanged` callback is intentionally here, to ensure that local available mods are constructed as early as possible.
|
||||
// this is needed to make sure no external changes to mods are dropped while mod panels are asynchronously loading.
|
||||
availableMods.BindValueChanged(_ => updateLocalAvailableMods(), true);
|
||||
updateLocalAvailableMods(asyncLoadContent: false);
|
||||
availableMods.BindValueChanged(_ => updateLocalAvailableMods(asyncLoadContent: true));
|
||||
|
||||
headerBackground.Colour = accentColour = colours.ForModType(ModType);
|
||||
|
||||
@ -279,7 +278,7 @@ namespace osu.Game.Overlays.Mods
|
||||
toggleAllCheckbox.LabelText = toggleAllCheckbox.Current.Value ? CommonStrings.DeselectAll : CommonStrings.SelectAll;
|
||||
}
|
||||
|
||||
private void updateLocalAvailableMods()
|
||||
private void updateLocalAvailableMods(bool asyncLoadContent)
|
||||
{
|
||||
var newMods = ModUtils.FlattenMods(availableMods.Value.GetValueOrDefault(ModType) ?? Array.Empty<Mod>())
|
||||
.Select(m => m.DeepClone())
|
||||
@ -290,11 +289,10 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
localAvailableMods = newMods;
|
||||
|
||||
if (!IsLoaded)
|
||||
// if we're coming from BDL, perform the first load synchronously to make sure everything is in place as early as possible.
|
||||
onPanelsLoaded(createPanels());
|
||||
else
|
||||
if (asyncLoadContent)
|
||||
asyncLoadPanels();
|
||||
else
|
||||
onPanelsLoaded(createPanels());
|
||||
}
|
||||
|
||||
private CancellationTokenSource? cancellationTokenSource;
|
||||
|
@ -20,10 +20,10 @@ using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
using osu.Game.Localisation;
|
||||
|
||||
namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
@ -31,13 +31,16 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
protected const int BUTTON_WIDTH = 200;
|
||||
|
||||
protected override OverlayColourScheme ColourScheme => OverlayColourScheme.Green;
|
||||
|
||||
[Cached]
|
||||
public Bindable<IReadOnlyList<Mod>> SelectedMods { get; private set; } = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
|
||||
|
||||
private Func<Mod, bool> isValidMod = m => true;
|
||||
|
||||
/// <summary>
|
||||
/// A function determining whether each mod in the column should be displayed.
|
||||
/// A return value of <see langword="true"/> means that the mod is not filtered and therefore its corresponding panel should be displayed.
|
||||
/// A return value of <see langword="false"/> means that the mod is filtered out and therefore its corresponding panel should be hidden.
|
||||
/// </summary>
|
||||
public Func<Mod, bool> IsValidMod
|
||||
{
|
||||
get => isValidMod;
|
||||
@ -57,31 +60,27 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
protected virtual ModColumn CreateModColumn(ModType modType, Key[]? toggleKeys = null) => new ModColumn(modType, false, toggleKeys);
|
||||
|
||||
protected virtual IEnumerable<ShearedButton> CreateFooterButtons() => new[]
|
||||
{
|
||||
customisationButton = new ShearedToggleButton(BUTTON_WIDTH)
|
||||
{
|
||||
Text = ModSelectScreenStrings.ModCustomisation,
|
||||
Active = { BindTarget = customisationVisible }
|
||||
},
|
||||
new ShearedButton(BUTTON_WIDTH)
|
||||
{
|
||||
Text = CommonStrings.DeselectAll,
|
||||
Action = DeselectAll
|
||||
}
|
||||
};
|
||||
protected virtual IReadOnlyList<Mod> ComputeNewModsFromSelection(IReadOnlyList<Mod> oldSelection, IReadOnlyList<Mod> newSelection) => newSelection;
|
||||
|
||||
protected virtual IEnumerable<ShearedButton> CreateFooterButtons() => createDefaultFooterButtons();
|
||||
|
||||
private readonly BindableBool customisationVisible = new BindableBool();
|
||||
|
||||
private DifficultyMultiplierDisplay? multiplierDisplay;
|
||||
private ModSettingsArea modSettingsArea = null!;
|
||||
private ColumnScrollContainer columnScroll = null!;
|
||||
private ColumnFlowContainer columnFlow = null!;
|
||||
|
||||
private FillFlowContainer<ShearedButton> footerButtonFlow = null!;
|
||||
private ShearedButton backButton = null!;
|
||||
|
||||
private DifficultyMultiplierDisplay? multiplierDisplay;
|
||||
|
||||
private ShearedToggleButton? customisationButton;
|
||||
|
||||
protected ModSelectScreen(OverlayColourScheme colourScheme = OverlayColourScheme.Green)
|
||||
: base(colourScheme)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
@ -185,14 +184,6 @@ namespace osu.Game.Overlays.Mods
|
||||
};
|
||||
}
|
||||
|
||||
private ColumnDimContainer createModColumnContent(ModType modType, Key[]? toggleKeys = null)
|
||||
=> new ColumnDimContainer(CreateModColumn(modType, toggleKeys))
|
||||
{
|
||||
AutoSizeAxes = Axes.X,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
RequestScroll = column => columnScroll.ScrollIntoView(column, extraScroll: 140)
|
||||
};
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
@ -216,6 +207,47 @@ namespace osu.Game.Overlays.Mods
|
||||
updateAvailableMods();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Select all visible mods in all columns.
|
||||
/// </summary>
|
||||
protected void SelectAll()
|
||||
{
|
||||
foreach (var column in columnFlow.Columns)
|
||||
column.SelectAll();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deselect all visible mods in all columns.
|
||||
/// </summary>
|
||||
protected void DeselectAll()
|
||||
{
|
||||
foreach (var column in columnFlow.Columns)
|
||||
column.DeselectAll();
|
||||
}
|
||||
|
||||
private ColumnDimContainer createModColumnContent(ModType modType, Key[]? toggleKeys = null)
|
||||
=> new ColumnDimContainer(CreateModColumn(modType, toggleKeys))
|
||||
{
|
||||
AutoSizeAxes = Axes.X,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
RequestScroll = column => columnScroll.ScrollIntoView(column, extraScroll: 140)
|
||||
};
|
||||
|
||||
private ShearedButton[] createDefaultFooterButtons()
|
||||
=> new[]
|
||||
{
|
||||
customisationButton = new ShearedToggleButton(BUTTON_WIDTH)
|
||||
{
|
||||
Text = ModSelectScreenStrings.ModCustomisation,
|
||||
Active = { BindTarget = customisationVisible }
|
||||
},
|
||||
new ShearedButton(BUTTON_WIDTH)
|
||||
{
|
||||
Text = CommonStrings.DeselectAll,
|
||||
Action = DeselectAll
|
||||
}
|
||||
};
|
||||
|
||||
private void updateMultiplier()
|
||||
{
|
||||
if (multiplierDisplay == null)
|
||||
@ -306,7 +338,7 @@ namespace osu.Game.Overlays.Mods
|
||||
SelectedMods.Value = ComputeNewModsFromSelection(SelectedMods.Value, candidateSelection);
|
||||
}
|
||||
|
||||
protected virtual IReadOnlyList<Mod> ComputeNewModsFromSelection(IReadOnlyList<Mod> oldSelection, IReadOnlyList<Mod> newSelection) => newSelection;
|
||||
#region Transition handling
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
@ -352,20 +384,17 @@ namespace osu.Game.Overlays.Mods
|
||||
}
|
||||
}
|
||||
|
||||
protected void SelectAll()
|
||||
{
|
||||
foreach (var column in columnFlow.Columns)
|
||||
column.SelectAll();
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected void DeselectAll()
|
||||
{
|
||||
foreach (var column in columnFlow.Columns)
|
||||
column.DeselectAll();
|
||||
}
|
||||
#region Input handling
|
||||
|
||||
public override bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||
{
|
||||
if (e.Repeat)
|
||||
return false;
|
||||
|
||||
// This is handled locally here because this overlay is being registered at the game level
|
||||
// and therefore takes away keyboard focus from the screen stack.
|
||||
if (e.Action == GlobalAction.Back)
|
||||
{
|
||||
if (customisationVisible.Value)
|
||||
@ -375,9 +404,27 @@ namespace osu.Game.Overlays.Mods
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnPressed(e);
|
||||
switch (e.Action)
|
||||
{
|
||||
case GlobalAction.ToggleModSelection:
|
||||
case GlobalAction.Select:
|
||||
{
|
||||
if (customisationVisible.Value)
|
||||
customisationVisible.Value = false;
|
||||
Hide();
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return base.OnPressed(e);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Manages horizontal scrolling of mod columns, along with the "active" states of each column based on visibility.
|
||||
/// </summary>
|
||||
internal class ColumnScrollContainer : OsuScrollContainer<ColumnFlowContainer>
|
||||
{
|
||||
public ColumnScrollContainer()
|
||||
@ -416,6 +463,9 @@ namespace osu.Game.Overlays.Mods
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages padding and layout of mod columns.
|
||||
/// </summary>
|
||||
internal class ColumnFlowContainer : FillFlowContainer<ColumnDimContainer>
|
||||
{
|
||||
public IEnumerable<ModColumn> Columns => Children.Select(dimWrapper => dimWrapper.Column);
|
||||
@ -452,11 +502,21 @@ namespace osu.Game.Overlays.Mods
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates a column and provides dim and input blocking based on an externally managed "active" state.
|
||||
/// </summary>
|
||||
internal class ColumnDimContainer : Container
|
||||
{
|
||||
public ModColumn Column { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Tracks whether this column is in an interactive state. Generally only the case when the column is on-screen.
|
||||
/// </summary>
|
||||
public readonly Bindable<bool> Active = new BindableBool();
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the column is clicked while not active, requesting a scroll to be performed to bring it on-screen.
|
||||
/// </summary>
|
||||
public Action<ColumnDimContainer>? RequestScroll { get; set; }
|
||||
|
||||
[Resolved]
|
||||
@ -511,6 +571,9 @@ namespace osu.Game.Overlays.Mods
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A container which blocks and handles input, managing the "return from customisation" state change.
|
||||
/// </summary>
|
||||
private class ClickToReturnContainer : Container
|
||||
{
|
||||
public BindableBool HandleMouse { get; } = new BindableBool();
|
||||
|
@ -51,17 +51,15 @@ namespace osu.Game.Overlays.Mods
|
||||
/// </summary>
|
||||
protected Container FooterContent { get; private set; }
|
||||
|
||||
protected abstract OverlayColourScheme ColourScheme { get; }
|
||||
|
||||
protected override bool StartHidden => true;
|
||||
|
||||
protected override bool BlockNonPositionalInput => true;
|
||||
|
||||
protected ShearedOverlayContainer()
|
||||
protected ShearedOverlayContainer(OverlayColourScheme colourScheme)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
ColourProvider = new OverlayColourProvider(ColourScheme);
|
||||
ColourProvider = new OverlayColourProvider(colourScheme);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
@ -12,6 +12,11 @@ namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
public class UserModSelectScreen : ModSelectScreen
|
||||
{
|
||||
public UserModSelectScreen(OverlayColourScheme colourScheme = OverlayColourScheme.Green)
|
||||
: base(colourScheme)
|
||||
{
|
||||
}
|
||||
|
||||
protected override ModColumn CreateModColumn(ModType modType, Key[] toggleKeys = null) => new UserModColumn(modType, false, toggleKeys);
|
||||
|
||||
protected override IReadOnlyList<Mod> ComputeNewModsFromSelection(IReadOnlyList<Mod> oldSelection, IReadOnlyList<Mod> newSelection)
|
||||
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Game.Overlays;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
@ -23,6 +24,7 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
}
|
||||
|
||||
public FreeModSelectScreen()
|
||||
: base(OverlayColourScheme.Plum)
|
||||
{
|
||||
IsValidMod = _ => true;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
@ -57,6 +58,9 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
|
||||
protected readonly IBindable<long?> RoomId = new Bindable<long?>();
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IOverlayManager overlayManager { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private MusicController music { get; set; }
|
||||
|
||||
@ -77,7 +81,11 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
public readonly Room Room;
|
||||
private readonly bool allowEdit;
|
||||
|
||||
private ModSelectOverlay userModsSelectOverlay;
|
||||
private ModSelectScreen userModsSelectOverlay;
|
||||
|
||||
[CanBeNull]
|
||||
private IDisposable userModsSelectOverlayRegistration;
|
||||
|
||||
private RoomSettingsOverlay settingsOverlay;
|
||||
private Drawable mainContent;
|
||||
|
||||
@ -180,11 +188,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Child = userModsSelectOverlay = new UserModSelectOverlay
|
||||
{
|
||||
SelectedMods = { BindTarget = UserMods },
|
||||
IsValidMod = _ => false
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -227,6 +230,12 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
LoadComponent(userModsSelectOverlay = new UserModSelectScreen(OverlayColourScheme.Plum)
|
||||
{
|
||||
SelectedMods = { BindTarget = UserMods },
|
||||
IsValidMod = _ => false
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@ -254,6 +263,8 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
|
||||
beatmapAvailabilityTracker.SelectedItem.BindTo(SelectedItem);
|
||||
beatmapAvailabilityTracker.Availability.BindValueChanged(_ => updateWorkingBeatmap());
|
||||
|
||||
userModsSelectOverlayRegistration = overlayManager?.RegisterBlockingOverlay(userModsSelectOverlay);
|
||||
}
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
@ -298,7 +309,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
|
||||
public override void OnSuspending(ScreenTransitionEvent e)
|
||||
{
|
||||
endHandlingTrack();
|
||||
onLeaving();
|
||||
base.OnSuspending(e);
|
||||
}
|
||||
|
||||
@ -316,7 +327,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
RoomManager?.PartRoom();
|
||||
Mods.Value = Array.Empty<Mod>();
|
||||
|
||||
endHandlingTrack();
|
||||
onLeaving();
|
||||
|
||||
return base.OnExiting(e);
|
||||
}
|
||||
@ -412,6 +423,12 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
Beatmap.BindValueChanged(applyLoopingToTrack, true);
|
||||
}
|
||||
|
||||
private void onLeaving()
|
||||
{
|
||||
userModsSelectOverlay.Hide();
|
||||
endHandlingTrack();
|
||||
}
|
||||
|
||||
private void endHandlingTrack()
|
||||
{
|
||||
Beatmap.ValueChanged -= applyLoopingToTrack;
|
||||
@ -459,5 +476,12 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
public class UserModSelectButton : PurpleTriangleButton
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
userModsSelectOverlayRegistration?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
@ -45,7 +46,6 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
|
||||
protected readonly Bindable<IReadOnlyList<Mod>> FreeMods = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
|
||||
|
||||
private readonly FreeModSelectOverlay freeModSelectOverlay;
|
||||
private readonly Room room;
|
||||
|
||||
private WorkingBeatmap initialBeatmap;
|
||||
@ -53,13 +53,16 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
private IReadOnlyList<Mod> initialMods;
|
||||
private bool itemSelected;
|
||||
|
||||
private readonly FreeModSelectScreen freeModSelectOverlay;
|
||||
private IDisposable freeModSelectOverlayRegistration;
|
||||
|
||||
protected OnlinePlaySongSelect(Room room)
|
||||
{
|
||||
this.room = room;
|
||||
|
||||
Padding = new MarginPadding { Horizontal = HORIZONTAL_OVERFLOW_PADDING };
|
||||
|
||||
freeModSelectOverlay = new FreeModSelectOverlay
|
||||
freeModSelectOverlay = new FreeModSelectScreen
|
||||
{
|
||||
SelectedMods = { BindTarget = FreeMods },
|
||||
IsValidMod = IsValidFreeMod,
|
||||
@ -75,7 +78,7 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
initialRuleset = Ruleset.Value;
|
||||
initialMods = Mods.Value.ToList();
|
||||
|
||||
FooterPanels.Add(freeModSelectOverlay);
|
||||
LoadComponent(freeModSelectOverlay);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@ -94,6 +97,8 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
|
||||
Mods.BindValueChanged(onModsChanged);
|
||||
Ruleset.BindValueChanged(onRulesetChanged);
|
||||
|
||||
freeModSelectOverlayRegistration = OverlayManager?.RegisterBlockingOverlay(freeModSelectOverlay);
|
||||
}
|
||||
|
||||
private void onModsChanged(ValueChangedEvent<IReadOnlyList<Mod>> mods)
|
||||
@ -150,10 +155,12 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
Mods.Value = initialMods;
|
||||
}
|
||||
|
||||
freeModSelectOverlay.Hide();
|
||||
|
||||
return base.OnExiting(e);
|
||||
}
|
||||
|
||||
protected override ModSelectOverlay CreateModSelectOverlay() => new UserModSelectOverlay
|
||||
protected override ModSelectScreen CreateModSelectOverlay() => new UserModSelectScreen(OverlayColourScheme.Plum)
|
||||
{
|
||||
IsValidMod = IsValidMod
|
||||
};
|
||||
@ -182,5 +189,12 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
private bool checkCompatibleFreeMod(Mod mod)
|
||||
=> Mods.Value.All(m => m.Acronym != mod.Acronym) // Mod must not be contained in the required mods.
|
||||
&& ModUtils.CheckCompatibleSet(Mods.Value.Append(mod).ToArray()); // Mod must be compatible with all the required mods.
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
freeModSelectOverlayRegistration?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
@ -101,7 +102,7 @@ namespace osu.Game.Screens.Select
|
||||
[Resolved(CanBeNull = true)]
|
||||
private LegacyImportManager legacyImportManager { get; set; }
|
||||
|
||||
protected ModSelectOverlay ModSelect { get; private set; }
|
||||
protected ModSelectScreen ModSelect { get; private set; }
|
||||
|
||||
protected Sample SampleConfirm { get; private set; }
|
||||
|
||||
@ -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)]
|
||||
internal IOverlayManager OverlayManager { get; private set; }
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(AudioManager audio, IDialogOverlay dialog, OsuColour colours, ManageCollectionsDialog manageCollectionsDialog, DifficultyRecommender recommender)
|
||||
{
|
||||
@ -252,38 +259,25 @@ namespace osu.Game.Screens.Select
|
||||
{
|
||||
AddRangeInternal(new Drawable[]
|
||||
{
|
||||
new GridContainer // used for max height implementation
|
||||
FooterPanels = new Container
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RowDimensions = new[]
|
||||
Padding = new MarginPadding { Bottom = Footer.HEIGHT },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Dimension(),
|
||||
new Dimension(GridSizeMode.Relative, 1f, maxSize: ModSelectOverlay.HEIGHT + Footer.HEIGHT),
|
||||
},
|
||||
Content = new[]
|
||||
{
|
||||
null,
|
||||
new Drawable[]
|
||||
{
|
||||
FooterPanels = new Container
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Bottom = Footer.HEIGHT },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
BeatmapOptions = new BeatmapOptionsOverlay(),
|
||||
ModSelect = CreateModSelectOverlay()
|
||||
}
|
||||
}
|
||||
}
|
||||
BeatmapOptions = new BeatmapOptionsOverlay(),
|
||||
}
|
||||
},
|
||||
Footer = new Footer()
|
||||
Footer = new Footer(),
|
||||
});
|
||||
}
|
||||
|
||||
// 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())
|
||||
@ -317,6 +311,13 @@ namespace osu.Game.Screens.Select
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
modSelectOverlayRegistration = OverlayManager?.RegisterBlockingOverlay(ModSelect);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the buttons to be displayed in the footer.
|
||||
/// </summary>
|
||||
@ -332,7 +333,7 @@ namespace osu.Game.Screens.Select
|
||||
(new FooterButtonOptions(), BeatmapOptions)
|
||||
};
|
||||
|
||||
protected virtual ModSelectOverlay CreateModSelectOverlay() => new UserModSelectOverlay();
|
||||
protected virtual ModSelectScreen CreateModSelectOverlay() => new UserModSelectScreen();
|
||||
|
||||
protected virtual void ApplyFilterToCarousel(FilterCriteria criteria)
|
||||
{
|
||||
@ -658,6 +659,7 @@ namespace osu.Game.Screens.Select
|
||||
return true;
|
||||
|
||||
beatmapInfoWedge.Hide();
|
||||
ModSelect.Hide();
|
||||
|
||||
this.FadeOut(100);
|
||||
|
||||
@ -716,6 +718,8 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
if (music != null)
|
||||
music.TrackChanged -= ensureTrackLooping;
|
||||
|
||||
modSelectOverlayRegistration?.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,12 +1,15 @@
|
||||
// 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.Development;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Screens;
|
||||
|
||||
@ -15,11 +18,12 @@ namespace osu.Game.Tests.Visual
|
||||
/// <summary>
|
||||
/// A test case which can be used to test a screen (that relies on OnEntering being called to execute startup instructions).
|
||||
/// </summary>
|
||||
public abstract class ScreenTestScene : OsuManualInputManagerTestScene
|
||||
public abstract class ScreenTestScene : OsuManualInputManagerTestScene, IOverlayManager
|
||||
{
|
||||
protected readonly OsuScreenStack Stack;
|
||||
|
||||
private readonly Container content;
|
||||
private readonly Container overlayContent;
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
|
||||
@ -36,7 +40,11 @@ namespace osu.Game.Tests.Visual
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
content = new Container { RelativeSizeAxes = Axes.Both },
|
||||
DialogOverlay = new DialogOverlay()
|
||||
overlayContent = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = DialogOverlay = new DialogOverlay()
|
||||
}
|
||||
});
|
||||
|
||||
Stack.ScreenPushed += (lastScreen, newScreen) => Logger.Log($"{nameof(ScreenTestScene)} screen changed → {newScreen}");
|
||||
@ -65,5 +73,26 @@ namespace osu.Game.Tests.Visual
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
#region IOverlayManager
|
||||
|
||||
IBindable<OverlayActivation> IOverlayManager.OverlayActivationMode { get; } = new Bindable<OverlayActivation>(OverlayActivation.All);
|
||||
|
||||
// in the blocking methods below it is important to be careful about threading (e.g. use `Expire()` rather than `Remove()`, and schedule transforms),
|
||||
// because in the worst case the clean-up methods could be called from async disposal.
|
||||
|
||||
IDisposable IOverlayManager.RegisterBlockingOverlay(OverlayContainer overlayContainer)
|
||||
{
|
||||
overlayContent.Add(overlayContainer);
|
||||
return new InvokeOnDisposal(() => overlayContainer.Expire());
|
||||
}
|
||||
|
||||
void IOverlayManager.ShowBlockingOverlay(OverlayContainer overlay)
|
||||
=> Schedule(() => Stack.FadeColour(OsuColour.Gray(0.5f), 500, Easing.OutQuint));
|
||||
|
||||
void IOverlayManager.HideBlockingOverlay(OverlayContainer overlay)
|
||||
=> Schedule(() => Stack.FadeColour(Colour4.White, 500, Easing.OutQuint));
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user