mirror of
https://github.com/ppy/osu.git
synced 2024-11-13 16:13:34 +08:00
Merge pull request #28185 from frenzibyte/footer-v2-become-global
Move new screen footer to `OsuGame` and add temporary `SongSelectV2` screen
This commit is contained in:
commit
be48377c4c
204
osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectV2.cs
Normal file
204
osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectV2.cs
Normal file
@ -0,0 +1,204 @@
|
||||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Footer;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Screens.SelectV2.Footer;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.SongSelect
|
||||
{
|
||||
public partial class TestSceneSongSelectV2 : ScreenTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly ScreenFooter screenScreenFooter;
|
||||
|
||||
[Cached]
|
||||
private readonly OsuLogo logo;
|
||||
|
||||
public TestSceneSongSelectV2()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new PopoverContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = screenScreenFooter = new ScreenFooter
|
||||
{
|
||||
OnBack = () => Stack.CurrentScreen.Exit(),
|
||||
},
|
||||
},
|
||||
logo = new OsuLogo
|
||||
{
|
||||
Alpha = 0f,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Stack.ScreenPushed += updateFooter;
|
||||
Stack.ScreenExited += updateFooter;
|
||||
}
|
||||
|
||||
[SetUpSteps]
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("load screen", () => Stack.Push(new SongSelectV2()));
|
||||
AddUntilStep("wait for load", () => Stack.CurrentScreen is SongSelectV2 songSelect && songSelect.IsLoaded);
|
||||
}
|
||||
|
||||
#region Footer
|
||||
|
||||
[Test]
|
||||
public void TestMods()
|
||||
{
|
||||
AddStep("one mod", () => SelectedMods.Value = new List<Mod> { new OsuModHidden() });
|
||||
AddStep("two mods", () => SelectedMods.Value = new List<Mod> { new OsuModHidden(), new OsuModHardRock() });
|
||||
AddStep("three mods", () => SelectedMods.Value = new List<Mod> { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime() });
|
||||
AddStep("four mods", () => SelectedMods.Value = new List<Mod> { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime(), new OsuModClassic() });
|
||||
AddStep("five mods", () => SelectedMods.Value = new List<Mod> { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime(), new OsuModClassic(), new OsuModDifficultyAdjust() });
|
||||
|
||||
AddStep("modified", () => SelectedMods.Value = new List<Mod> { new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } });
|
||||
AddStep("modified + one", () => SelectedMods.Value = new List<Mod> { new OsuModHidden(), new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } });
|
||||
AddStep("modified + two", () => SelectedMods.Value = new List<Mod> { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } });
|
||||
AddStep("modified + three", () => SelectedMods.Value = new List<Mod> { new OsuModHidden(), new OsuModHardRock(), new OsuModClassic(), new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } });
|
||||
AddStep("modified + four", () => SelectedMods.Value = new List<Mod> { new OsuModHidden(), new OsuModHardRock(), new OsuModClassic(), new OsuModDifficultyAdjust(), new OsuModDoubleTime { SpeedChange = { Value = 1.2 } } });
|
||||
|
||||
AddStep("clear mods", () => SelectedMods.Value = Array.Empty<Mod>());
|
||||
AddWaitStep("wait", 3);
|
||||
AddStep("one mod", () => SelectedMods.Value = new List<Mod> { new OsuModHidden() });
|
||||
|
||||
AddStep("clear mods", () => SelectedMods.Value = Array.Empty<Mod>());
|
||||
AddWaitStep("wait", 3);
|
||||
AddStep("five mods", () => SelectedMods.Value = new List<Mod> { new OsuModHidden(), new OsuModHardRock(), new OsuModDoubleTime(), new OsuModClassic(), new OsuModDifficultyAdjust() });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestShowOptions()
|
||||
{
|
||||
AddStep("enable options", () =>
|
||||
{
|
||||
var optionsButton = this.ChildrenOfType<ScreenFooterButton>().Last();
|
||||
|
||||
optionsButton.Enabled.Value = true;
|
||||
optionsButton.TriggerClick();
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestState()
|
||||
{
|
||||
AddToggleStep("set options enabled state", state => this.ChildrenOfType<ScreenFooterButton>().Last().Enabled.Value = state);
|
||||
}
|
||||
|
||||
// add these test cases when functionality is implemented.
|
||||
// [Test]
|
||||
// public void TestFooterRandom()
|
||||
// {
|
||||
// AddStep("press F2", () => InputManager.Key(Key.F2));
|
||||
// AddAssert("next random invoked", () => nextRandomCalled && !previousRandomCalled);
|
||||
// }
|
||||
//
|
||||
// [Test]
|
||||
// public void TestFooterRandomViaMouse()
|
||||
// {
|
||||
// AddStep("click button", () =>
|
||||
// {
|
||||
// InputManager.MoveMouseTo(randomButton);
|
||||
// InputManager.Click(MouseButton.Left);
|
||||
// });
|
||||
// AddAssert("next random invoked", () => nextRandomCalled && !previousRandomCalled);
|
||||
// }
|
||||
//
|
||||
// [Test]
|
||||
// public void TestFooterRewind()
|
||||
// {
|
||||
// AddStep("press Shift+F2", () =>
|
||||
// {
|
||||
// InputManager.PressKey(Key.LShift);
|
||||
// InputManager.PressKey(Key.F2);
|
||||
// InputManager.ReleaseKey(Key.F2);
|
||||
// InputManager.ReleaseKey(Key.LShift);
|
||||
// });
|
||||
// AddAssert("previous random invoked", () => previousRandomCalled && !nextRandomCalled);
|
||||
// }
|
||||
//
|
||||
// [Test]
|
||||
// public void TestFooterRewindViaShiftMouseLeft()
|
||||
// {
|
||||
// AddStep("shift + click button", () =>
|
||||
// {
|
||||
// InputManager.PressKey(Key.LShift);
|
||||
// InputManager.MoveMouseTo(randomButton);
|
||||
// InputManager.Click(MouseButton.Left);
|
||||
// InputManager.ReleaseKey(Key.LShift);
|
||||
// });
|
||||
// AddAssert("previous random invoked", () => previousRandomCalled && !nextRandomCalled);
|
||||
// }
|
||||
//
|
||||
// [Test]
|
||||
// public void TestFooterRewindViaMouseRight()
|
||||
// {
|
||||
// AddStep("right click button", () =>
|
||||
// {
|
||||
// InputManager.MoveMouseTo(randomButton);
|
||||
// InputManager.Click(MouseButton.Right);
|
||||
// });
|
||||
// AddAssert("previous random invoked", () => previousRandomCalled && !nextRandomCalled);
|
||||
// }
|
||||
|
||||
[Test]
|
||||
public void TestOverlayPresent()
|
||||
{
|
||||
AddStep("Press F1", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<ScreenFooterButtonMods>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddAssert("Overlay visible", () => this.ChildrenOfType<ModSelectOverlay>().Single().State.Value == Visibility.Visible);
|
||||
AddStep("Hide", () => this.ChildrenOfType<ModSelectOverlay>().Single().Hide());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
Stack.Padding = new MarginPadding { Bottom = screenScreenFooter.DrawHeight - screenScreenFooter.Y };
|
||||
}
|
||||
|
||||
private void updateFooter(IScreen? _, IScreen? newScreen)
|
||||
{
|
||||
if (newScreen is IOsuScreen osuScreen && osuScreen.ShowFooter)
|
||||
{
|
||||
screenScreenFooter.Show();
|
||||
screenScreenFooter.SetButtons(osuScreen.CreateFooterButtons());
|
||||
}
|
||||
else
|
||||
{
|
||||
screenScreenFooter.Hide();
|
||||
screenScreenFooter.SetButtons(Array.Empty<ScreenFooterButton>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.SongSelect
|
||||
{
|
||||
public partial class TestSceneSongSelectV2Navigation : OsuGameTestScene
|
||||
{
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
AddStep("press enter", () => InputManager.Key(Key.Enter));
|
||||
AddWaitStep("wait", 5);
|
||||
PushAndConfirm(() => new SongSelectV2());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestClickLogo()
|
||||
{
|
||||
AddStep("click", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(Game.ChildrenOfType<OsuLogo>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Screens.Footer;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -15,7 +16,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
public TestSceneBackButton()
|
||||
{
|
||||
BackButton button;
|
||||
BackButton.Receptor receptor = new BackButton.Receptor();
|
||||
ScreenFooter.BackReceptor receptor = new ScreenFooter.BackReceptor();
|
||||
|
||||
Child = new Container
|
||||
{
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Testing;
|
||||
@ -19,9 +18,6 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
private ScreenFooter screenFooter = null!;
|
||||
private TestModSelectOverlay overlay = null!;
|
||||
|
||||
[Cached]
|
||||
private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Aquamarine);
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
@ -89,6 +85,11 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
private partial class TestModSelectOverlay : UserModSelectOverlay
|
||||
{
|
||||
protected override bool ShowPresets => true;
|
||||
|
||||
public TestModSelectOverlay()
|
||||
: base(OverlayColourScheme.Aquamarine)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,6 +116,11 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
private partial class TestModSelectOverlay : UserModSelectOverlay
|
||||
{
|
||||
protected override bool ShowPresets => true;
|
||||
|
||||
public TestModSelectOverlay()
|
||||
: base(OverlayColourScheme.Aquamarine)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private partial class TestScreenFooterButtonMods : ScreenFooterButtonMods
|
||||
|
@ -7,19 +7,18 @@ using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Screens.Footer;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
// todo: remove this once all screens migrate to display the new game footer and back button.
|
||||
public partial class BackButton : VisibilityContainer
|
||||
{
|
||||
public Action Action;
|
||||
|
||||
private readonly TwoLayerButton button;
|
||||
|
||||
public BackButton(Receptor receptor = null)
|
||||
public BackButton(ScreenFooter.BackReceptor receptor = null)
|
||||
{
|
||||
Size = TwoLayerButton.SIZE_EXTENDED;
|
||||
|
||||
@ -35,7 +34,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
if (receptor == null)
|
||||
{
|
||||
// if a receptor wasn't provided, create our own locally.
|
||||
Add(receptor = new Receptor());
|
||||
Add(receptor = new ScreenFooter.BackReceptor());
|
||||
}
|
||||
|
||||
receptor.OnBackPressed = () => button.TriggerClick();
|
||||
@ -59,29 +58,5 @@ namespace osu.Game.Graphics.UserInterface
|
||||
button.MoveToX(-TwoLayerButton.SIZE_EXTENDED.X / 2, 400, Easing.OutQuint);
|
||||
button.FadeOut(400, Easing.OutQuint);
|
||||
}
|
||||
|
||||
public partial class Receptor : Drawable, IKeyBindingHandler<GlobalAction>
|
||||
{
|
||||
public Action OnBackPressed;
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||
{
|
||||
if (e.Repeat)
|
||||
return false;
|
||||
|
||||
switch (e.Action)
|
||||
{
|
||||
case GlobalAction.Back:
|
||||
OnBackPressed?.Invoke();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Extensions.TypeExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Bindings;
|
||||
@ -58,6 +59,7 @@ using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Footer;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||
using osu.Game.Screens.Play;
|
||||
@ -153,6 +155,8 @@ namespace osu.Game
|
||||
|
||||
private float toolbarOffset => (Toolbar?.Position.Y ?? 0) + (Toolbar?.DrawHeight ?? 0);
|
||||
|
||||
private float screenFooterOffset => (ScreenFooter?.DrawHeight ?? 0) - (ScreenFooter?.Position.Y ?? 0);
|
||||
|
||||
private IdleTracker idleTracker;
|
||||
|
||||
/// <summary>
|
||||
@ -177,6 +181,7 @@ namespace osu.Game
|
||||
protected OsuScreenStack ScreenStack;
|
||||
|
||||
protected BackButton BackButton;
|
||||
protected ScreenFooter ScreenFooter;
|
||||
|
||||
protected SettingsOverlay Settings;
|
||||
|
||||
@ -926,7 +931,7 @@ namespace osu.Game
|
||||
};
|
||||
|
||||
Container logoContainer;
|
||||
BackButton.Receptor receptor;
|
||||
ScreenFooter.BackReceptor backReceptor;
|
||||
|
||||
dependencies.CacheAs(idleTracker = new GameIdleTracker(6000));
|
||||
|
||||
@ -959,20 +964,28 @@ namespace osu.Game
|
||||
Origin = Anchor.Centre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
receptor = new BackButton.Receptor(),
|
||||
backReceptor = new ScreenFooter.BackReceptor(),
|
||||
ScreenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both },
|
||||
BackButton = new BackButton(receptor)
|
||||
BackButton = new BackButton(backReceptor)
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Action = () =>
|
||||
Action = () => ScreenFooter.OnBack?.Invoke(),
|
||||
},
|
||||
new PopoverContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = ScreenFooter = new ScreenFooter(backReceptor)
|
||||
{
|
||||
if (!(ScreenStack.CurrentScreen is IOsuScreen currentScreen))
|
||||
return;
|
||||
OnBack = () =>
|
||||
{
|
||||
if (!(ScreenStack.CurrentScreen is IOsuScreen currentScreen))
|
||||
return;
|
||||
|
||||
if (!((Drawable)currentScreen).IsLoaded || (currentScreen.AllowBackButton && !currentScreen.OnBackButton()))
|
||||
ScreenStack.Exit();
|
||||
}
|
||||
if (!((Drawable)currentScreen).IsLoaded || (currentScreen.AllowBackButton && !currentScreen.OnBackButton()))
|
||||
ScreenStack.Exit();
|
||||
}
|
||||
},
|
||||
},
|
||||
logoContainer = new Container { RelativeSizeAxes = Axes.Both },
|
||||
}
|
||||
@ -994,6 +1007,8 @@ namespace osu.Game
|
||||
new ConfineMouseTracker()
|
||||
});
|
||||
|
||||
dependencies.Cache(ScreenFooter);
|
||||
|
||||
ScreenStack.ScreenPushed += screenPushed;
|
||||
ScreenStack.ScreenExited += screenExited;
|
||||
|
||||
@ -1466,6 +1481,7 @@ namespace osu.Game
|
||||
|
||||
ScreenOffsetContainer.Padding = new MarginPadding { Top = toolbarOffset };
|
||||
overlayOffsetContainer.Padding = new MarginPadding { Top = toolbarOffset };
|
||||
ScreenStack.Padding = new MarginPadding { Bottom = screenFooterOffset };
|
||||
|
||||
float horizontalOffset = 0f;
|
||||
|
||||
@ -1538,6 +1554,18 @@ namespace osu.Game
|
||||
BackButton.Show();
|
||||
else
|
||||
BackButton.Hide();
|
||||
|
||||
if (newOsuScreen.ShowFooter)
|
||||
{
|
||||
BackButton.Hide();
|
||||
ScreenFooter.SetButtons(newOsuScreen.CreateFooterButtons());
|
||||
ScreenFooter.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
ScreenFooter.SetButtons(Array.Empty<ScreenFooterButton>());
|
||||
ScreenFooter.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
skinEditor.SetTarget((OsuScreen)newScreen);
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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 System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
@ -8,7 +9,12 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Footer
|
||||
@ -22,19 +28,31 @@ namespace osu.Game.Screens.Footer
|
||||
|
||||
private readonly List<OverlayContainer> overlays = new List<OverlayContainer>();
|
||||
|
||||
private ScreenBackButton backButton = null!;
|
||||
private FillFlowContainer<ScreenFooterButton> buttonsFlow = null!;
|
||||
private Container<ScreenFooterButton> removedButtonsContainer = null!;
|
||||
private LogoTrackingContainer logoTrackingContainer = null!;
|
||||
|
||||
public ScreenFooter()
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine);
|
||||
|
||||
public Action? OnBack;
|
||||
|
||||
public ScreenFooter(BackReceptor? receptor = null)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = HEIGHT;
|
||||
Anchor = Anchor.BottomLeft;
|
||||
Origin = Anchor.BottomLeft;
|
||||
|
||||
if (receptor == null)
|
||||
Add(receptor = new BackReceptor());
|
||||
|
||||
receptor.OnBackPressed = () => backButton.TriggerClick();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colourProvider)
|
||||
private void load()
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
@ -53,12 +71,12 @@ namespace osu.Game.Screens.Footer
|
||||
Spacing = new Vector2(7, 0),
|
||||
AutoSizeAxes = Axes.Both
|
||||
},
|
||||
new ScreenBackButton
|
||||
backButton = new ScreenBackButton
|
||||
{
|
||||
Margin = new MarginPadding { Bottom = 10f, Left = 12f },
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Action = () => { },
|
||||
Action = () => OnBack?.Invoke(),
|
||||
},
|
||||
removedButtonsContainer = new Container<ScreenFooterButton>
|
||||
{
|
||||
@ -68,9 +86,21 @@ namespace osu.Game.Screens.Footer
|
||||
Origin = Anchor.BottomLeft,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
},
|
||||
(logoTrackingContainer = new LogoTrackingContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}).WithChild(logoTrackingContainer.LogoFacade.With(f =>
|
||||
{
|
||||
f.Anchor = Anchor.BottomRight;
|
||||
f.Origin = Anchor.Centre;
|
||||
f.Position = new Vector2(-76, -36);
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
public void StartTrackingLogo(OsuLogo logo, float duration = 0, Easing easing = Easing.None) => logoTrackingContainer.StartTracking(logo, duration, easing);
|
||||
public void StopTrackingLogo() => logoTrackingContainer.StopTracking();
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
this.MoveToY(0, 400, Easing.OutQuint)
|
||||
@ -150,5 +180,29 @@ namespace osu.Game.Screens.Footer
|
||||
o.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
public partial class BackReceptor : Drawable, IKeyBindingHandler<GlobalAction>
|
||||
{
|
||||
public Action? OnBackPressed;
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||
{
|
||||
if (e.Repeat)
|
||||
return false;
|
||||
|
||||
switch (e.Action)
|
||||
{
|
||||
case GlobalAction.Back:
|
||||
OnBackPressed?.Invoke();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
// 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.Collections.Generic;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Footer;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Screens
|
||||
@ -19,10 +21,18 @@ namespace osu.Game.Screens
|
||||
bool DisallowExternalBeatmapRulesetChanges { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the user can exit this this <see cref="IOsuScreen"/> by pressing the back button.
|
||||
/// Whether the user can exit this <see cref="IOsuScreen"/> by pressing the back button.
|
||||
/// </summary>
|
||||
bool AllowBackButton { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether a footer (and a back button) should be displayed underneath the screen.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Temporarily, the back button is shown regardless of whether <see cref="AllowBackButton"/> is true.
|
||||
/// </remarks>
|
||||
bool ShowFooter { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether a top-level component should be allowed to exit the current screen to, for example,
|
||||
/// complete an import. Note that this can be overridden by a user if they specifically request.
|
||||
@ -63,6 +73,11 @@ namespace osu.Game.Screens
|
||||
|
||||
Bindable<RulesetInfo> Ruleset { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of footer buttons to be added to the game footer, or empty to display no buttons.
|
||||
/// </summary>
|
||||
IReadOnlyList<ScreenFooterButton> CreateFooterButtons();
|
||||
|
||||
/// <summary>
|
||||
/// Whether mod track adjustments should be applied on entering this screen.
|
||||
/// A <see langword="null"/> value means that the parent screen's value of this setting will be used.
|
||||
|
@ -173,9 +173,9 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
IsValidMod = IsValidMod
|
||||
};
|
||||
|
||||
protected override IEnumerable<(FooterButton, OverlayContainer?)> CreateFooterButtons()
|
||||
protected override IEnumerable<(FooterButton, OverlayContainer?)> CreateSongSelectFooterButtons()
|
||||
{
|
||||
var baseButtons = base.CreateFooterButtons().ToList();
|
||||
var baseButtons = base.CreateSongSelectFooterButtons().ToList();
|
||||
var freeModsButton = new FooterButtonFreeMods(freeModSelectOverlay) { Current = FreeMods };
|
||||
|
||||
baseButtons.Insert(baseButtons.FindIndex(b => b.Item1 is FooterButtonMods) + 1, (freeModsButton, freeModSelectOverlay));
|
||||
|
@ -16,6 +16,7 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Footer;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Users;
|
||||
|
||||
@ -38,6 +39,8 @@ namespace osu.Game.Screens
|
||||
|
||||
public virtual bool AllowBackButton => true;
|
||||
|
||||
public virtual bool ShowFooter => false;
|
||||
|
||||
public virtual bool AllowExternalScreenChange => false;
|
||||
|
||||
public virtual bool HideOverlaysOnEnter => false;
|
||||
@ -141,6 +144,10 @@ namespace osu.Game.Screens
|
||||
[Resolved(canBeNull: true)]
|
||||
private OsuLogo logo { get; set; }
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
[CanBeNull]
|
||||
protected ScreenFooter Footer { get; private set; }
|
||||
|
||||
protected OsuScreen()
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
@ -298,6 +305,8 @@ namespace osu.Game.Screens
|
||||
/// </summary>
|
||||
protected virtual BackgroundScreen CreateBackground() => null;
|
||||
|
||||
public virtual IReadOnlyList<ScreenFooterButton> CreateFooterButtons() => Array.Empty<ScreenFooterButton>();
|
||||
|
||||
public virtual bool OnBackButton() => false;
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,12 @@ namespace osu.Game.Screens
|
||||
|
||||
protected float ParallaxAmount => parallaxContainer.ParallaxAmount;
|
||||
|
||||
public new MarginPadding Padding
|
||||
{
|
||||
get => base.Padding;
|
||||
set => base.Padding = value;
|
||||
}
|
||||
|
||||
public OsuScreenStack()
|
||||
{
|
||||
InternalChild = parallaxContainer = new ParallaxContainer
|
||||
|
@ -61,19 +61,19 @@ namespace osu.Game.Screens.Select
|
||||
/// </summary>
|
||||
protected virtual bool ControlGlobalMusic => true;
|
||||
|
||||
protected virtual bool ShowFooter => true;
|
||||
protected virtual bool ShowSongSelectFooter => true;
|
||||
|
||||
public override bool? ApplyModTrackAdjustments => true;
|
||||
|
||||
/// <summary>
|
||||
/// Can be null if <see cref="ShowFooter"/> is false.
|
||||
/// Can be null if <see cref="ShowSongSelectFooter"/> is false.
|
||||
/// </summary>
|
||||
protected BeatmapOptionsOverlay BeatmapOptions { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Can be null if <see cref="ShowFooter"/> is false.
|
||||
/// Can be null if <see cref="ShowSongSelectFooter"/> is false.
|
||||
/// </summary>
|
||||
protected Footer? Footer { get; private set; }
|
||||
protected Footer? SongSelectFooter { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Contains any panel which is triggered by a footer button.
|
||||
@ -168,7 +168,7 @@ namespace osu.Game.Screens.Select
|
||||
Origin = Anchor.CentreRight,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BleedTop = FilterControl.HEIGHT,
|
||||
BleedBottom = Footer.HEIGHT,
|
||||
BleedBottom = Select.Footer.HEIGHT,
|
||||
SelectionChanged = updateSelectedBeatmap,
|
||||
BeatmapSetsChanged = carouselBeatmapsLoaded,
|
||||
FilterApplied = () => Scheduler.AddOnce(updateVisibleBeatmapCount),
|
||||
@ -215,7 +215,7 @@ namespace osu.Game.Screens.Select
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Top = FilterControl.HEIGHT,
|
||||
Bottom = Footer.HEIGHT
|
||||
Bottom = Select.Footer.HEIGHT
|
||||
},
|
||||
Child = new LoadingSpinner(true) { State = { Value = Visibility.Visible } }
|
||||
}
|
||||
@ -302,7 +302,7 @@ namespace osu.Game.Screens.Select
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Bottom = Footer.HEIGHT,
|
||||
Bottom = Select.Footer.HEIGHT,
|
||||
Top = WEDGE_HEIGHT + 70,
|
||||
Left = left_area_padding,
|
||||
Right = left_area_padding * 2,
|
||||
@ -327,7 +327,7 @@ namespace osu.Game.Screens.Select
|
||||
modSpeedHotkeyHandler = new ModSpeedHotkeyHandler(),
|
||||
});
|
||||
|
||||
if (ShowFooter)
|
||||
if (ShowSongSelectFooter)
|
||||
{
|
||||
AddRangeInternal(new Drawable[]
|
||||
{
|
||||
@ -336,13 +336,13 @@ namespace osu.Game.Screens.Select
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Bottom = Footer.HEIGHT },
|
||||
Padding = new MarginPadding { Bottom = Select.Footer.HEIGHT },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
BeatmapOptions = new BeatmapOptionsOverlay(),
|
||||
}
|
||||
},
|
||||
Footer = new Footer()
|
||||
SongSelectFooter = new Footer()
|
||||
});
|
||||
}
|
||||
|
||||
@ -350,10 +350,10 @@ namespace osu.Game.Screens.Select
|
||||
// therein it will be registered at the `OsuGame` level to properly function as a blocking overlay.
|
||||
LoadComponent(ModSelect = CreateModSelectOverlay());
|
||||
|
||||
if (Footer != null)
|
||||
if (SongSelectFooter != null)
|
||||
{
|
||||
foreach (var (button, overlay) in CreateFooterButtons())
|
||||
Footer.AddButton(button, overlay);
|
||||
foreach (var (button, overlay) in CreateSongSelectFooterButtons())
|
||||
SongSelectFooter.AddButton(button, overlay);
|
||||
|
||||
BeatmapOptions.AddButton(@"Manage", @"collections", FontAwesome.Solid.Book, colours.Green, () => manageCollectionsDialog?.Show());
|
||||
BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => DeleteBeatmap(Beatmap.Value.BeatmapSetInfo));
|
||||
@ -387,7 +387,7 @@ namespace osu.Game.Screens.Select
|
||||
/// Creates the buttons to be displayed in the footer.
|
||||
/// </summary>
|
||||
/// <returns>A set of <see cref="FooterButton"/> and an optional <see cref="OverlayContainer"/> which the button opens when pressed.</returns>
|
||||
protected virtual IEnumerable<(FooterButton, OverlayContainer?)> CreateFooterButtons() => new (FooterButton, OverlayContainer?)[]
|
||||
protected virtual IEnumerable<(FooterButton, OverlayContainer?)> CreateSongSelectFooterButtons() => new (FooterButton, OverlayContainer?)[]
|
||||
{
|
||||
(new FooterButtonMods { Current = Mods }, ModSelect),
|
||||
(new FooterButtonRandom
|
||||
|
@ -20,7 +20,6 @@ using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Screens.Select;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
@ -33,18 +32,22 @@ namespace osu.Game.Screens.SelectV2.Footer
|
||||
private FillFlowContainer buttonFlow = null!;
|
||||
private readonly ScreenFooterButtonOptions footerButton;
|
||||
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider;
|
||||
|
||||
private WorkingBeatmap beatmapWhenOpening = null!;
|
||||
|
||||
[Resolved]
|
||||
private IBindable<WorkingBeatmap> beatmap { get; set; } = null!;
|
||||
|
||||
public BeatmapOptionsPopover(ScreenFooterButtonOptions footerButton)
|
||||
public BeatmapOptionsPopover(ScreenFooterButtonOptions footerButton, OverlayColourProvider colourProvider)
|
||||
{
|
||||
this.footerButton = footerButton;
|
||||
this.colourProvider = colourProvider;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ManageCollectionsDialog? manageCollectionsDialog, SongSelect? songSelect, OsuColour colours, BeatmapManager? beatmapManager)
|
||||
private void load(ManageCollectionsDialog? manageCollectionsDialog, OsuColour colours, BeatmapManager? beatmapManager)
|
||||
{
|
||||
Content.Padding = new MarginPadding(5);
|
||||
|
||||
@ -61,15 +64,15 @@ namespace osu.Game.Screens.SelectV2.Footer
|
||||
addButton(SongSelectStrings.ManageCollections, FontAwesome.Solid.Book, () => manageCollectionsDialog?.Show());
|
||||
|
||||
addHeader(SongSelectStrings.ForAllDifficulties, beatmapWhenOpening.BeatmapSetInfo.ToString());
|
||||
addButton(SongSelectStrings.DeleteBeatmap, FontAwesome.Solid.Trash, () => songSelect?.DeleteBeatmap(beatmapWhenOpening.BeatmapSetInfo), colours.Red1);
|
||||
addButton(SongSelectStrings.DeleteBeatmap, FontAwesome.Solid.Trash, () => { }, colours.Red1); // songSelect?.DeleteBeatmap(beatmapWhenOpening.BeatmapSetInfo);
|
||||
|
||||
addHeader(SongSelectStrings.ForSelectedDifficulty, beatmapWhenOpening.BeatmapInfo.DifficultyName);
|
||||
// TODO: make work, and make show "unplayed" or "played" based on status.
|
||||
addButton(SongSelectStrings.MarkAsPlayed, FontAwesome.Regular.TimesCircle, null);
|
||||
addButton(SongSelectStrings.ClearAllLocalScores, FontAwesome.Solid.Eraser, () => songSelect?.ClearScores(beatmapWhenOpening.BeatmapInfo), colours.Red1);
|
||||
addButton(SongSelectStrings.ClearAllLocalScores, FontAwesome.Solid.Eraser, () => { }, colours.Red1); // songSelect?.ClearScores(beatmapWhenOpening.BeatmapInfo);
|
||||
|
||||
if (songSelect != null && songSelect.AllowEditing)
|
||||
addButton(SongSelectStrings.EditBeatmap, FontAwesome.Solid.PencilAlt, () => songSelect.Edit(beatmapWhenOpening.BeatmapInfo));
|
||||
// if (songSelect != null && songSelect.AllowEditing)
|
||||
addButton(SongSelectStrings.EditBeatmap, FontAwesome.Solid.PencilAlt, () => { }); // songSelect.Edit(beatmapWhenOpening.BeatmapInfo);
|
||||
|
||||
addButton(WebCommonStrings.ButtonsHide.ToSentence(), FontAwesome.Solid.Magic, () => beatmapManager?.Hide(beatmapWhenOpening.BeatmapInfo));
|
||||
}
|
||||
@ -83,9 +86,6 @@ namespace osu.Game.Screens.SelectV2.Footer
|
||||
beatmap.BindValueChanged(_ => Hide());
|
||||
}
|
||||
|
||||
[Resolved]
|
||||
private OverlayColourProvider overlayColourProvider { get; set; } = null!;
|
||||
|
||||
private void addHeader(LocalisableString text, string? context = null)
|
||||
{
|
||||
var textFlow = new OsuTextFlowContainer
|
||||
@ -102,7 +102,7 @@ namespace osu.Game.Screens.SelectV2.Footer
|
||||
textFlow.NewLine();
|
||||
textFlow.AddText(context, t =>
|
||||
{
|
||||
t.Colour = overlayColourProvider.Content2;
|
||||
t.Colour = colourProvider.Content2;
|
||||
t.Font = t.Font.With(size: 13);
|
||||
});
|
||||
}
|
||||
|
@ -8,12 +8,16 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Screens.Footer;
|
||||
|
||||
namespace osu.Game.Screens.SelectV2.Footer
|
||||
{
|
||||
public partial class ScreenFooterButtonOptions : ScreenFooterButton, IHasPopover
|
||||
{
|
||||
[Resolved]
|
||||
private OverlayColourProvider colourProvider { get; set; } = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colour)
|
||||
{
|
||||
@ -25,6 +29,6 @@ namespace osu.Game.Screens.SelectV2.Footer
|
||||
Action = this.ShowPopover;
|
||||
}
|
||||
|
||||
public Popover GetPopover() => new BeatmapOptionsPopover(this);
|
||||
public Popover GetPopover() => new BeatmapOptionsPopover(this, colourProvider);
|
||||
}
|
||||
}
|
||||
|
145
osu.Game/Screens/SelectV2/SongSelectV2.cs
Normal file
145
osu.Game/Screens/SelectV2/SongSelectV2.cs
Normal file
@ -0,0 +1,145 @@
|
||||
// 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 System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Screens.Footer;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.SelectV2.Footer;
|
||||
|
||||
namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
/// <summary>
|
||||
/// This screen is intended to house all components introduced in the new song select design to add transitions and examine the overall look.
|
||||
/// This will be gradually built upon and ultimately replace <see cref="Select.SongSelect"/> once everything is in place.
|
||||
/// </summary>
|
||||
public partial class SongSelectV2 : OsuScreen
|
||||
{
|
||||
private readonly ModSelectOverlay modSelectOverlay = new SoloModSelectOverlay();
|
||||
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine);
|
||||
|
||||
public override bool ShowFooter => true;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AddRangeInternal(new Drawable[]
|
||||
{
|
||||
new PopoverContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
modSelectOverlay,
|
||||
});
|
||||
}
|
||||
|
||||
public override IReadOnlyList<ScreenFooterButton> CreateFooterButtons() => new ScreenFooterButton[]
|
||||
{
|
||||
new ScreenFooterButtonMods(modSelectOverlay) { Current = Mods },
|
||||
new ScreenFooterButtonRandom(),
|
||||
new ScreenFooterButtonOptions(),
|
||||
};
|
||||
|
||||
public override void OnEntering(ScreenTransitionEvent e)
|
||||
{
|
||||
this.FadeIn();
|
||||
base.OnEntering(e);
|
||||
}
|
||||
|
||||
public override void OnResuming(ScreenTransitionEvent e)
|
||||
{
|
||||
this.FadeIn();
|
||||
base.OnResuming(e);
|
||||
}
|
||||
|
||||
public override void OnSuspending(ScreenTransitionEvent e)
|
||||
{
|
||||
this.Delay(400).FadeOut();
|
||||
base.OnSuspending(e);
|
||||
}
|
||||
|
||||
public override bool OnExiting(ScreenExitEvent e)
|
||||
{
|
||||
this.Delay(400).FadeOut();
|
||||
return base.OnExiting(e);
|
||||
}
|
||||
|
||||
public override bool OnBackButton()
|
||||
{
|
||||
if (modSelectOverlay.State.Value == Visibility.Visible)
|
||||
{
|
||||
modSelectOverlay.Hide();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
||||
{
|
||||
base.LogoArriving(logo, resuming);
|
||||
|
||||
if (logo.Alpha > 0.8f)
|
||||
Footer?.StartTrackingLogo(logo, 400, Easing.OutQuint);
|
||||
else
|
||||
{
|
||||
logo.Hide();
|
||||
logo.ScaleTo(0.2f);
|
||||
Footer?.StartTrackingLogo(logo);
|
||||
}
|
||||
|
||||
logo.FadeIn(240, Easing.OutQuint);
|
||||
logo.ScaleTo(0.4f, 240, Easing.OutQuint);
|
||||
|
||||
logo.Action = () =>
|
||||
{
|
||||
this.Push(new PlayerLoaderV2(() => new SoloPlayer()));
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LogoSuspending(OsuLogo logo)
|
||||
{
|
||||
base.LogoSuspending(logo);
|
||||
Footer?.StopTrackingLogo();
|
||||
}
|
||||
|
||||
protected override void LogoExiting(OsuLogo logo)
|
||||
{
|
||||
base.LogoExiting(logo);
|
||||
Scheduler.AddDelayed(() => Footer?.StopTrackingLogo(), 120);
|
||||
logo.ScaleTo(0.2f, 120, Easing.Out);
|
||||
logo.FadeOut(120, Easing.Out);
|
||||
}
|
||||
|
||||
private partial class SoloModSelectOverlay : ModSelectOverlay
|
||||
{
|
||||
protected override bool ShowPresets => true;
|
||||
|
||||
public SoloModSelectOverlay()
|
||||
: base(OverlayColourScheme.Aquamarine)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private partial class PlayerLoaderV2 : PlayerLoader
|
||||
{
|
||||
public override bool ShowFooter => true;
|
||||
|
||||
public PlayerLoaderV2(Func<Player> createPlayer)
|
||||
: base(createPlayer)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user