mirror of
https://github.com/ppy/osu.git
synced 2026-05-16 17:03:01 +08:00
b76a7e1bb6
This commit rearranges the contents of `ShearedButtons` to be more independent of each other in regards to sizing. Thanks to that, the custom logic related to enabling autosizing is no longer necessary. Witdh and height are no longer set via the constructor, and can be freely configured using the initializer syntax. Additionally, this allows the button to use relative sizing without having to resort to any hackery with `Size` (this will come in handy for me when implementing the new footer on multiplayer screens). Given that most of the `ShearedButton`s currently in use set their width explicitly, I did not set `AutoSizeAxes = Axes.X` like it would be by default previously. Instead it is set on the only two such buttons (show converts/selected mods on ssv2). I suppose it might be a good idea to have it set that by default if no `Width` is specified, as right now it'll just not show anything. Also I've set the margin on the text field by default in all cases instead of only when autosizing like how it was previously, since otherwise it would be a pain to set that on each button instance when needed. I've checked all affected components and could not find any text overflowing issues that this could cause. --------- Co-authored-by: Dean Herbert <pe@ppy.sh>
373 lines
16 KiB
C#
373 lines
16 KiB
C#
// 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.Sprites;
|
|
using osu.Framework.Screens;
|
|
using osu.Framework.Testing;
|
|
using osu.Game.Graphics;
|
|
using osu.Game.Graphics.UserInterface;
|
|
using osu.Game.Overlays;
|
|
using osu.Game.Overlays.Mods;
|
|
using osu.Game.Screens;
|
|
using osu.Game.Screens.Footer;
|
|
|
|
namespace osu.Game.Tests.Visual.Navigation
|
|
{
|
|
public partial class TestSceneScreenFooterNavigation : OsuGameTestScene
|
|
{
|
|
private ScreenFooter screenFooter => this.ChildrenOfType<ScreenFooter>().Single();
|
|
|
|
[Test]
|
|
public void TestFooterButtonsOnScreenTransitions()
|
|
{
|
|
PushAndConfirm(() => new TestScreen
|
|
{
|
|
CreateButtons = () => [new ScreenFooterButton { Text = "Button One" }]
|
|
});
|
|
AddUntilStep("button one shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
|
|
|
PushAndConfirm(() => new TestScreen { CreateButtons = () => [new ScreenFooterButton { Text = "Button Two" }] });
|
|
AddUntilStep("button two shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button Two"));
|
|
|
|
AddStep("exit screen", () => Game.ScreenStack.Exit());
|
|
AddUntilStep("button one shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
|
}
|
|
|
|
[Test]
|
|
public void TestFooterHidesOldBackButton()
|
|
{
|
|
PushAndConfirm(() => new TestScreen(false));
|
|
AddAssert("footer hidden", () => screenFooter.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
|
AddAssert("old back button shown", () => Game.BackButton.State.Value, () => Is.EqualTo(Visibility.Visible));
|
|
|
|
PushAndConfirm(() => new TestScreen());
|
|
AddAssert("footer shown", () => screenFooter.State.Value, () => Is.EqualTo(Visibility.Visible));
|
|
AddAssert("old back button hidden", () => Game.BackButton.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
|
|
|
PushAndConfirm(() => new TestScreen(false));
|
|
AddAssert("footer hidden", () => screenFooter.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
|
AddAssert("back button shown", () => Game.BackButton.State.Value, () => Is.EqualTo(Visibility.Visible));
|
|
|
|
AddStep("exit screen", () => Game.ScreenStack.Exit());
|
|
AddAssert("footer shown", () => screenFooter.State.Value, () => Is.EqualTo(Visibility.Visible));
|
|
AddAssert("old back button hidden", () => Game.BackButton.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
|
|
|
AddStep("exit screen", () => Game.ScreenStack.Exit());
|
|
AddAssert("footer hidden", () => screenFooter.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
|
AddAssert("old back button shown", () => Game.BackButton.State.Value, () => Is.EqualTo(Visibility.Visible));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests pushing and exiting subscreens that have footers.
|
|
/// </summary>
|
|
[Test]
|
|
public void TestPushAndExitSubScreens()
|
|
{
|
|
TestScreenWithSubScreen screen = null!;
|
|
|
|
PushAndConfirm(() => screen = new TestScreenWithSubScreen());
|
|
AddAssert("footer hidden", () => screenFooter.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
|
AddAssert("old back button shown", () => Game.BackButton.State.Value, () => Is.EqualTo(Visibility.Visible));
|
|
|
|
pushSubScreenAndConfirm(() => screen, () => new TestScreen
|
|
{
|
|
CreateButtons = () => [new ScreenFooterButton { Text = "Button One" }]
|
|
});
|
|
AddUntilStep("button one shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
|
|
|
pushSubScreenAndConfirm(() => screen, () => new TestScreen
|
|
{
|
|
CreateButtons = () => [new ScreenFooterButton { Text = "Button Two" }]
|
|
});
|
|
AddUntilStep("button two shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button Two"));
|
|
|
|
AddStep("exit sub screen", () => screen.ExitSubScreen());
|
|
AddUntilStep("button one shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
|
|
|
AddStep("exit sub screen", () => screen.ExitSubScreen());
|
|
AddAssert("footer hidden", () => screenFooter.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
|
AddAssert("old back button shown", () => Game.BackButton.State.Value, () => Is.EqualTo(Visibility.Visible));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests pushing a new parenting screen while the footer is displayed from a subscreen.
|
|
/// </summary>
|
|
[Test]
|
|
public void TestPushParentScreenDuringSubScreen()
|
|
{
|
|
TestScreenWithSubScreen screen = null!;
|
|
|
|
PushAndConfirm(() => screen = new TestScreenWithSubScreen());
|
|
pushSubScreenAndConfirm(() => screen, () => new TestScreen
|
|
{
|
|
CreateButtons = () => [new ScreenFooterButton { Text = "Button One" }]
|
|
});
|
|
AddUntilStep("button one shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
|
|
|
PushAndConfirm(() => new TestScreen
|
|
{
|
|
CreateButtons = () => [new ScreenFooterButton { Text = "Button Two" }]
|
|
});
|
|
AddUntilStep("button two shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button Two"));
|
|
|
|
AddStep("exit parent screen", () => Game.ScreenStack.Exit());
|
|
AddUntilStep("button one shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests pushing a new subscreen after a new parenting screen has been pushed.
|
|
/// </summary>
|
|
[Test]
|
|
public void TestPushSubScreenWhileNotCurrent()
|
|
{
|
|
TestScreenWithSubScreen screen = null!;
|
|
|
|
PushAndConfirm(() => screen = new TestScreenWithSubScreen());
|
|
pushSubScreenAndConfirm(() => screen, () => new TestScreen
|
|
{
|
|
CreateButtons = () => [new ScreenFooterButton { Text = "Button One" }]
|
|
});
|
|
AddUntilStep("button one shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
|
|
|
PushAndConfirm(() => new TestScreen
|
|
{
|
|
CreateButtons = () => [new ScreenFooterButton { Text = "Button One" }]
|
|
});
|
|
AddUntilStep("button one shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
|
|
|
// Can't use the helper method because the screen never loads
|
|
AddStep("Push new sub screen", () => screen.PushSubScreen(new TestScreen
|
|
{
|
|
CreateButtons = () => [new ScreenFooterButton { Text = "Button Two" }]
|
|
}));
|
|
AddWaitStep("wait for potential screen load", 5);
|
|
AddUntilStep("button one still shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
|
|
|
AddStep("exit parent screen", () => Game.ScreenStack.Exit());
|
|
AddUntilStep("button two shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button Two"));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests clicking the back button while an overlay is open.
|
|
/// </summary>
|
|
[Test]
|
|
public void TestBackButtonWhenOverlayOpen()
|
|
{
|
|
TestScreen screen = null!;
|
|
|
|
PushAndConfirm(() =>
|
|
{
|
|
ShearedOverlayContainer overlay = new TestShearedOverlayContainer();
|
|
|
|
return screen = new TestScreen
|
|
{
|
|
Overlay = overlay,
|
|
CreateButtons = () =>
|
|
[
|
|
new ScreenFooterButton(overlay)
|
|
{
|
|
AccentColour = Dependencies.Get<OsuColour>().Orange1,
|
|
Icon = FontAwesome.Solid.Toolbox,
|
|
Text = "One",
|
|
},
|
|
new ScreenFooterButton { Text = "Two", Action = () => { } },
|
|
new ScreenFooterButton { Text = "Three", Action = () => { } },
|
|
],
|
|
};
|
|
});
|
|
|
|
AddStep("show overlay", () => screen.Overlay.Show());
|
|
AddAssert("overlay shown", () => screen.Overlay.State.Value, () => Is.EqualTo(Visibility.Visible));
|
|
|
|
AddStep("press back", () => screenFooter.ChildrenOfType<ScreenBackButton>().Single().TriggerClick());
|
|
AddAssert("overlay hidden", () => screen.Overlay.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
|
AddAssert("screen still shown", () => screen.IsCurrentScreen(), () => Is.True);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests clicking the back button on an overlay with `BackButtonPressed` being overridden.
|
|
/// </summary>
|
|
[Test]
|
|
public void TestBackButtonWithCustomBackButtonPressed()
|
|
{
|
|
TestScreen screen = null!;
|
|
TestShearedOverlayContainer overlay = null!;
|
|
|
|
PushAndConfirm(() =>
|
|
{
|
|
return screen = new TestScreen
|
|
{
|
|
Overlay = overlay = new TestShearedOverlayContainer(),
|
|
CreateButtons = () =>
|
|
[
|
|
new ScreenFooterButton(overlay)
|
|
{
|
|
AccentColour = Dependencies.Get<OsuColour>().Orange1,
|
|
Icon = FontAwesome.Solid.Toolbox,
|
|
Text = "One",
|
|
},
|
|
new ScreenFooterButton { Text = "Two", Action = () => { } },
|
|
new ScreenFooterButton { Text = "Three", Action = () => { } },
|
|
],
|
|
};
|
|
});
|
|
|
|
AddStep("show overlay", () => screen.Overlay.Show());
|
|
AddAssert("overlay shown", () => screen.Overlay.State.Value, () => Is.EqualTo(Visibility.Visible));
|
|
AddStep("set block count", () => overlay.BackButtonCount = 1);
|
|
|
|
AddStep("press back", () => screenFooter.ChildrenOfType<ScreenBackButton>().Single().TriggerClick());
|
|
AddAssert("overlay still shown", () => screen.Overlay.State.Value, () => Is.EqualTo(Visibility.Visible));
|
|
|
|
AddStep("press back again", () => screenFooter.ChildrenOfType<ScreenBackButton>().Single().TriggerClick());
|
|
AddAssert("overlay hidden", () => screen.Overlay.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
|
AddAssert("screen still shown", () => screen.IsCurrentScreen(), () => Is.True);
|
|
}
|
|
|
|
private void pushSubScreenAndConfirm(Func<TestScreenWithSubScreen> target, Func<Screen> newScreen)
|
|
{
|
|
Screen screen = null!;
|
|
IScreen? previousScreen = null;
|
|
|
|
AddStep("Push new sub screen", () =>
|
|
{
|
|
previousScreen = target().CurrentSubScreen;
|
|
target().PushSubScreen(screen = newScreen());
|
|
});
|
|
|
|
AddUntilStep("Wait for new screen", () => screen.IsLoaded
|
|
&& target().CurrentSubScreen != previousScreen
|
|
&& (previousScreen == null || previousScreen.GetChildScreen() == screen));
|
|
}
|
|
|
|
private partial class TestScreen : OsuScreen
|
|
{
|
|
public override bool ShowFooter { get; }
|
|
|
|
public Func<IReadOnlyList<ScreenFooterButton>> CreateButtons = Array.Empty<ScreenFooterButton>;
|
|
|
|
public ShearedOverlayContainer Overlay = new TestShearedOverlayContainer();
|
|
|
|
private IDisposable? overlayRegistration;
|
|
|
|
[Cached]
|
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
|
|
|
[Resolved]
|
|
private IOverlayManager? overlayManager { get; set; }
|
|
|
|
public TestScreen(bool showFooter = true)
|
|
{
|
|
ShowFooter = showFooter;
|
|
}
|
|
|
|
[BackgroundDependencyLoader]
|
|
private void load()
|
|
{
|
|
LoadComponent(Overlay);
|
|
}
|
|
|
|
protected override void LoadComplete()
|
|
{
|
|
base.LoadComplete();
|
|
overlayRegistration = overlayManager?.RegisterBlockingOverlay(Overlay);
|
|
}
|
|
|
|
public override IReadOnlyList<ScreenFooterButton> CreateFooterButtons() => CreateButtons.Invoke();
|
|
|
|
protected override void Dispose(bool isDisposing)
|
|
{
|
|
base.Dispose(isDisposing);
|
|
overlayRegistration?.Dispose();
|
|
}
|
|
}
|
|
|
|
private partial class TestScreenWithSubScreen : OsuScreen, IHasSubScreenStack
|
|
{
|
|
public ScreenStack SubScreenStack { get; }
|
|
|
|
public TestScreenWithSubScreen()
|
|
{
|
|
InternalChild = SubScreenStack = new ScreenStack
|
|
{
|
|
RelativeSizeAxes = Axes.Both
|
|
};
|
|
}
|
|
|
|
public IScreen? CurrentSubScreen => SubScreenStack.CurrentScreen;
|
|
|
|
public void PushSubScreen(IScreen screen) => SubScreenStack.Push(screen);
|
|
|
|
public void ExitSubScreen() => SubScreenStack.Exit();
|
|
}
|
|
|
|
private partial class TestShearedOverlayContainer : ShearedOverlayContainer
|
|
{
|
|
public TestShearedOverlayContainer()
|
|
: base(OverlayColourScheme.Orange)
|
|
{
|
|
}
|
|
|
|
[BackgroundDependencyLoader]
|
|
private void load()
|
|
{
|
|
Header.Title = "Test overlay";
|
|
Header.Description = "An overlay that is made purely for testing purposes.";
|
|
}
|
|
|
|
public int BackButtonCount;
|
|
|
|
public override bool OnBackButton()
|
|
{
|
|
if (BackButtonCount > 0)
|
|
{
|
|
BackButtonCount--;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public override VisibilityContainer CreateFooterContent() => new TestFooterContent();
|
|
|
|
public partial class TestFooterContent : VisibilityContainer
|
|
{
|
|
[BackgroundDependencyLoader]
|
|
private void load()
|
|
{
|
|
AutoSizeAxes = Axes.Both;
|
|
|
|
InternalChild = new FillFlowContainer
|
|
{
|
|
AutoSizeAxes = Axes.Both,
|
|
Children = new[]
|
|
{
|
|
new ShearedButton { Width = 200, Text = "Action #1", Action = () => { } },
|
|
new ShearedButton { Width = 140, Text = "Action #2", Action = () => { } },
|
|
}
|
|
};
|
|
}
|
|
|
|
protected override void PopIn()
|
|
{
|
|
this.MoveToY(0, 400, Easing.OutQuint)
|
|
.FadeIn(400, Easing.OutQuint);
|
|
}
|
|
|
|
protected override void PopOut()
|
|
{
|
|
this.MoveToY(-20f, 200, Easing.OutQuint)
|
|
.FadeOut(200, Easing.OutQuint);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|