1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 11:20:04 +08:00

Move screen footer to OsuGame

This commit is contained in:
Salman Ahmed 2024-05-16 07:20:55 +03:00
parent 921be3ca01
commit 03220598b8
9 changed files with 96 additions and 31 deletions

View File

@ -5,6 +5,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Footer;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
@ -15,7 +16,7 @@ namespace osu.Game.Tests.Visual.UserInterface
public TestSceneBackButton() public TestSceneBackButton()
{ {
BackButton button; BackButton button;
BackButton.Receptor receptor = new BackButton.Receptor(); ScreenFooter.BackReceptor receptor = new ScreenFooter.BackReceptor();
Child = new Container Child = new Container
{ {

View File

@ -3,7 +3,6 @@
using System; using System;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Framework.Testing; using osu.Framework.Testing;
@ -19,9 +18,6 @@ namespace osu.Game.Tests.Visual.UserInterface
private ScreenFooter screenFooter = null!; private ScreenFooter screenFooter = null!;
private TestModSelectOverlay overlay = null!; private TestModSelectOverlay overlay = null!;
[Cached]
private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Aquamarine);
[SetUp] [SetUp]
public void SetUp() => Schedule(() => public void SetUp() => Schedule(() =>
{ {
@ -89,6 +85,11 @@ namespace osu.Game.Tests.Visual.UserInterface
private partial class TestModSelectOverlay : UserModSelectOverlay private partial class TestModSelectOverlay : UserModSelectOverlay
{ {
protected override bool ShowPresets => true; protected override bool ShowPresets => true;
public TestModSelectOverlay()
: base(OverlayColourScheme.Aquamarine)
{
}
} }
} }
} }

View File

@ -116,6 +116,11 @@ namespace osu.Game.Tests.Visual.UserInterface
private partial class TestModSelectOverlay : UserModSelectOverlay private partial class TestModSelectOverlay : UserModSelectOverlay
{ {
protected override bool ShowPresets => true; protected override bool ShowPresets => true;
public TestModSelectOverlay()
: base(OverlayColourScheme.Aquamarine)
{
}
} }
private partial class TestScreenFooterButtonMods : ScreenFooterButtonMods private partial class TestScreenFooterButtonMods : ScreenFooterButtonMods

View File

@ -22,6 +22,7 @@ using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Extensions.TypeExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
@ -58,6 +59,7 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Screens; using osu.Game.Screens;
using osu.Game.Screens.Edit; using osu.Game.Screens.Edit;
using osu.Game.Screens.Footer;
using osu.Game.Screens.Menu; using osu.Game.Screens.Menu;
using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Screens.OnlinePlay.Multiplayer;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
@ -153,6 +155,8 @@ namespace osu.Game
private float toolbarOffset => (Toolbar?.Position.Y ?? 0) + (Toolbar?.DrawHeight ?? 0); private float toolbarOffset => (Toolbar?.Position.Y ?? 0) + (Toolbar?.DrawHeight ?? 0);
private float screenFooterOffset => (ScreenFooter?.DrawHeight ?? 0) - (ScreenFooter?.Position.Y ?? 0);
private IdleTracker idleTracker; private IdleTracker idleTracker;
/// <summary> /// <summary>
@ -177,6 +181,7 @@ namespace osu.Game
protected OsuScreenStack ScreenStack; protected OsuScreenStack ScreenStack;
protected BackButton BackButton; protected BackButton BackButton;
protected ScreenFooter ScreenFooter;
protected SettingsOverlay Settings; protected SettingsOverlay Settings;
@ -917,7 +922,7 @@ namespace osu.Game
}; };
Container logoContainer; Container logoContainer;
BackButton.Receptor receptor; ScreenFooter.BackReceptor backReceptor;
dependencies.CacheAs(idleTracker = new GameIdleTracker(6000)); dependencies.CacheAs(idleTracker = new GameIdleTracker(6000));
@ -950,13 +955,20 @@ namespace osu.Game
Origin = Anchor.Centre, Origin = Anchor.Centre,
Children = new Drawable[] Children = new Drawable[]
{ {
receptor = new BackButton.Receptor(), backReceptor = new ScreenFooter.BackReceptor(),
ScreenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, ScreenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both },
BackButton = new BackButton(receptor) BackButton = new BackButton(backReceptor)
{ {
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
Action = () => Action = () => ScreenFooter.OnBack?.Invoke(),
},
new PopoverContainer
{
RelativeSizeAxes = Axes.Both,
Child = ScreenFooter = new ScreenFooter(backReceptor)
{
OnBack = () =>
{ {
if (!(ScreenStack.CurrentScreen is IOsuScreen currentScreen)) if (!(ScreenStack.CurrentScreen is IOsuScreen currentScreen))
return; return;
@ -965,6 +977,7 @@ namespace osu.Game
ScreenStack.Exit(); ScreenStack.Exit();
} }
}, },
},
logoContainer = new Container { RelativeSizeAxes = Axes.Both }, logoContainer = new Container { RelativeSizeAxes = Axes.Both },
} }
}, },
@ -985,6 +998,8 @@ namespace osu.Game
new ConfineMouseTracker() new ConfineMouseTracker()
}); });
dependencies.Cache(ScreenFooter);
ScreenStack.ScreenPushed += screenPushed; ScreenStack.ScreenPushed += screenPushed;
ScreenStack.ScreenExited += screenExited; ScreenStack.ScreenExited += screenExited;
@ -1457,6 +1472,7 @@ namespace osu.Game
ScreenOffsetContainer.Padding = new MarginPadding { Top = toolbarOffset }; ScreenOffsetContainer.Padding = new MarginPadding { Top = toolbarOffset };
overlayOffsetContainer.Padding = new MarginPadding { Top = toolbarOffset }; overlayOffsetContainer.Padding = new MarginPadding { Top = toolbarOffset };
ScreenStack.Padding = new MarginPadding { Bottom = screenFooterOffset };
float horizontalOffset = 0f; float horizontalOffset = 0f;
@ -1529,6 +1545,18 @@ namespace osu.Game
BackButton.Show(); BackButton.Show();
else else
BackButton.Hide(); 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); skinEditor.SetTarget((OsuScreen)newScreen);

View File

@ -1,11 +1,13 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Screens.Footer;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Screens namespace osu.Game.Screens
@ -19,10 +21,18 @@ namespace osu.Game.Screens
bool DisallowExternalBeatmapRulesetChanges { get; } bool DisallowExternalBeatmapRulesetChanges { get; }
/// <summary> /// <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> /// </summary>
bool AllowBackButton { get; } 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> /// <summary>
/// Whether a top-level component should be allowed to exit the current screen to, for example, /// 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. /// 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; } 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> /// <summary>
/// Whether mod track adjustments should be applied on entering this screen. /// 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. /// A <see langword="null"/> value means that the parent screen's value of this setting will be used.

View File

@ -173,9 +173,9 @@ namespace osu.Game.Screens.OnlinePlay
IsValidMod = IsValidMod 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 }; var freeModsButton = new FooterButtonFreeMods(freeModSelectOverlay) { Current = FreeMods };
baseButtons.Insert(baseButtons.FindIndex(b => b.Item1 is FooterButtonMods) + 1, (freeModsButton, freeModSelectOverlay)); baseButtons.Insert(baseButtons.FindIndex(b => b.Item1 is FooterButtonMods) + 1, (freeModsButton, freeModSelectOverlay));

View File

@ -16,6 +16,7 @@ using osu.Game.Beatmaps;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Footer;
using osu.Game.Screens.Menu; using osu.Game.Screens.Menu;
using osu.Game.Users; using osu.Game.Users;
@ -38,6 +39,8 @@ namespace osu.Game.Screens
public virtual bool AllowBackButton => true; public virtual bool AllowBackButton => true;
public virtual bool ShowFooter => false;
public virtual bool AllowExternalScreenChange => false; public virtual bool AllowExternalScreenChange => false;
public virtual bool HideOverlaysOnEnter => false; public virtual bool HideOverlaysOnEnter => false;
@ -141,6 +144,10 @@ namespace osu.Game.Screens
[Resolved(canBeNull: true)] [Resolved(canBeNull: true)]
private OsuLogo logo { get; set; } private OsuLogo logo { get; set; }
[Resolved(canBeNull: true)]
[CanBeNull]
protected ScreenFooter Footer { get; private set; }
protected OsuScreen() protected OsuScreen()
{ {
Anchor = Anchor.Centre; Anchor = Anchor.Centre;
@ -298,6 +305,8 @@ namespace osu.Game.Screens
/// </summary> /// </summary>
protected virtual BackgroundScreen CreateBackground() => null; protected virtual BackgroundScreen CreateBackground() => null;
public virtual IReadOnlyList<ScreenFooterButton> CreateFooterButtons() => Array.Empty<ScreenFooterButton>();
public virtual bool OnBackButton() => false; public virtual bool OnBackButton() => false;
} }
} }

View File

@ -17,6 +17,12 @@ namespace osu.Game.Screens
protected float ParallaxAmount => parallaxContainer.ParallaxAmount; protected float ParallaxAmount => parallaxContainer.ParallaxAmount;
public new MarginPadding Padding
{
get => base.Padding;
set => base.Padding = value;
}
public OsuScreenStack() public OsuScreenStack()
{ {
InternalChild = parallaxContainer = new ParallaxContainer InternalChild = parallaxContainer = new ParallaxContainer

View File

@ -60,19 +60,19 @@ namespace osu.Game.Screens.Select
/// </summary> /// </summary>
protected virtual bool ControlGlobalMusic => true; protected virtual bool ControlGlobalMusic => true;
protected virtual bool ShowFooter => true; protected virtual bool ShowSongSelectFooter => true;
public override bool? ApplyModTrackAdjustments => true; public override bool? ApplyModTrackAdjustments => true;
/// <summary> /// <summary>
/// Can be null if <see cref="ShowFooter"/> is false. /// Can be null if <see cref="ShowSongSelectFooter"/> is false.
/// </summary> /// </summary>
protected BeatmapOptionsOverlay BeatmapOptions { get; private set; } = null!; protected BeatmapOptionsOverlay BeatmapOptions { get; private set; } = null!;
/// <summary> /// <summary>
/// Can be null if <see cref="ShowFooter"/> is false. /// Can be null if <see cref="ShowSongSelectFooter"/> is false.
/// </summary> /// </summary>
protected Footer? Footer { get; private set; } protected Footer? SongSelectFooter { get; private set; }
/// <summary> /// <summary>
/// Contains any panel which is triggered by a footer button. /// Contains any panel which is triggered by a footer button.
@ -163,7 +163,7 @@ namespace osu.Game.Screens.Select
Origin = Anchor.CentreRight, Origin = Anchor.CentreRight,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
BleedTop = FilterControl.HEIGHT, BleedTop = FilterControl.HEIGHT,
BleedBottom = Footer.HEIGHT, BleedBottom = Select.Footer.HEIGHT,
SelectionChanged = updateSelectedBeatmap, SelectionChanged = updateSelectedBeatmap,
BeatmapSetsChanged = carouselBeatmapsLoaded, BeatmapSetsChanged = carouselBeatmapsLoaded,
FilterApplied = () => Scheduler.AddOnce(updateVisibleBeatmapCount), FilterApplied = () => Scheduler.AddOnce(updateVisibleBeatmapCount),
@ -210,7 +210,7 @@ namespace osu.Game.Screens.Select
Padding = new MarginPadding Padding = new MarginPadding
{ {
Top = FilterControl.HEIGHT, Top = FilterControl.HEIGHT,
Bottom = Footer.HEIGHT Bottom = Select.Footer.HEIGHT
}, },
Child = new LoadingSpinner(true) { State = { Value = Visibility.Visible } } Child = new LoadingSpinner(true) { State = { Value = Visibility.Visible } }
} }
@ -297,7 +297,7 @@ namespace osu.Game.Screens.Select
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding Padding = new MarginPadding
{ {
Bottom = Footer.HEIGHT, Bottom = Select.Footer.HEIGHT,
Top = WEDGE_HEIGHT + 70, Top = WEDGE_HEIGHT + 70,
Left = left_area_padding, Left = left_area_padding,
Right = left_area_padding * 2, Right = left_area_padding * 2,
@ -321,7 +321,7 @@ namespace osu.Game.Screens.Select
}, },
}); });
if (ShowFooter) if (ShowSongSelectFooter)
{ {
AddRangeInternal(new Drawable[] AddRangeInternal(new Drawable[]
{ {
@ -330,13 +330,13 @@ namespace osu.Game.Screens.Select
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Bottom = Footer.HEIGHT }, Padding = new MarginPadding { Bottom = Select.Footer.HEIGHT },
Children = new Drawable[] Children = new Drawable[]
{ {
BeatmapOptions = new BeatmapOptionsOverlay(), BeatmapOptions = new BeatmapOptionsOverlay(),
} }
}, },
Footer = new Footer() SongSelectFooter = new Footer()
}); });
} }
@ -344,10 +344,10 @@ namespace osu.Game.Screens.Select
// therein it will be registered at the `OsuGame` level to properly function as a blocking overlay. // therein it will be registered at the `OsuGame` level to properly function as a blocking overlay.
LoadComponent(ModSelect = CreateModSelectOverlay()); LoadComponent(ModSelect = CreateModSelectOverlay());
if (Footer != null) if (SongSelectFooter != null)
{ {
foreach (var (button, overlay) in CreateFooterButtons()) foreach (var (button, overlay) in CreateSongSelectFooterButtons())
Footer.AddButton(button, overlay); SongSelectFooter.AddButton(button, overlay);
BeatmapOptions.AddButton(@"Manage", @"collections", FontAwesome.Solid.Book, colours.Green, () => manageCollectionsDialog?.Show()); 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)); BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => DeleteBeatmap(Beatmap.Value.BeatmapSetInfo));
@ -381,7 +381,7 @@ namespace osu.Game.Screens.Select
/// Creates the buttons to be displayed in the footer. /// Creates the buttons to be displayed in the footer.
/// </summary> /// </summary>
/// <returns>A set of <see cref="FooterButton"/> and an optional <see cref="OverlayContainer"/> which the button opens when pressed.</returns> /// <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 FooterButtonMods { Current = Mods }, ModSelect),
(new FooterButtonRandom (new FooterButtonRandom