diff --git a/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs b/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs index 1686436924..df12e14891 100644 --- a/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs +++ b/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Threading; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -22,55 +23,76 @@ public class TestCaseLoaderAnimation : ScreenTestCase public TestCaseLoaderAnimation() { - Add(logo = new OsuLogo { Depth = float.MinValue }); + Child = logo = new OsuLogo { Depth = float.MinValue }; } - protected override void LoadComplete() + [Test] + public void TestInstantLoad() { - base.LoadComplete(); - bool logoVisible = false; - AddStep("almost instant display", () => LoadScreen(loader = new TestLoader(250))); - AddUntilStep("loaded", () => - { - logoVisible = loader.Logo?.Alpha > 0; - return loader.Logo != null && loader.ScreenLoaded; - }); - AddAssert("logo not visible", () => !logoVisible); - AddStep("short load", () => LoadScreen(loader = new TestLoader(800))); - AddUntilStep("loaded", () => + AddStep("begin loading", () => + { + loader = new TestLoader(); + loader.AllowLoad.Set(); + + LoadScreen(loader); + }); + + AddAssert("loaded", () => { logoVisible = loader.Logo?.Alpha > 0; return loader.Logo != null && loader.ScreenLoaded; }); - AddAssert("logo visible", () => logoVisible); + + AddAssert("logo was not visible", () => !logoVisible); + } + + [Test] + public void TestShortLoad() + { + bool logoVisible = false; + + AddStep("begin loading", () => LoadScreen(loader = new TestLoader())); + AddWaitStep("wait", 2); + AddStep("finish loading", () => + { + logoVisible = loader.Logo?.Alpha > 0; + loader.AllowLoad.Set(); + }); + + AddAssert("loaded", () => loader.Logo != null && loader.ScreenLoaded); + AddAssert("logo was visible", () => logoVisible); AddUntilStep("logo gone", () => loader.Logo?.Alpha == 0); + } - AddStep("longer load", () => LoadScreen(loader = new TestLoader(1400))); - AddUntilStep("loaded", () => + [Test] + public void TestLongLoad() + { + bool logoVisible = false; + + AddStep("begin loading", () => LoadScreen(loader = new TestLoader())); + AddWaitStep("wait", 10); + AddStep("finish loading", () => { logoVisible = loader.Logo?.Alpha > 0; - return loader.Logo != null && loader.ScreenLoaded; + loader.AllowLoad.Set(); }); - AddAssert("logo visible", () => logoVisible); + + AddAssert("loaded", () => loader.Logo != null && loader.ScreenLoaded); + AddAssert("logo was visible", () => logoVisible); AddUntilStep("logo gone", () => loader.Logo?.Alpha == 0); } private class TestLoader : Loader { - private readonly double delay; + public readonly ManualResetEventSlim AllowLoad = new ManualResetEventSlim(); public OsuLogo Logo; private TestScreen screen; public bool ScreenLoaded => screen.IsCurrentScreen(); - public TestLoader(double delay) - { - this.delay = delay; - } - protected override void LogoArriving(OsuLogo logo, bool resuming) { Logo = logo; @@ -78,25 +100,18 @@ protected override void LogoArriving(OsuLogo logo, bool resuming) } protected override OsuScreen CreateLoadableScreen() => screen = new TestScreen(); - protected override ShaderPrecompiler CreateShaderPrecompiler() => new TestShaderPrecompiler(delay); + protected override ShaderPrecompiler CreateShaderPrecompiler() => new TestShaderPrecompiler(AllowLoad); private class TestShaderPrecompiler : ShaderPrecompiler { - private readonly double delay; - private double startTime; + private readonly ManualResetEventSlim allowLoad; - public TestShaderPrecompiler(double delay) + public TestShaderPrecompiler(ManualResetEventSlim allowLoad) { - this.delay = delay; + this.allowLoad = allowLoad; } - protected override void LoadComplete() - { - base.LoadComplete(); - startTime = Time.Current; - } - - protected override bool AllLoaded => Time.Current > startTime + delay; + protected override bool AllLoaded => allowLoad.IsSet; } private class TestScreen : OsuScreen diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs new file mode 100644 index 0000000000..1574023068 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.cs @@ -0,0 +1,80 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Graphics.UserInterface +{ + public abstract class ScreenTitle : CompositeDrawable, IHasAccentColour + { + private readonly SpriteIcon iconSprite; + private readonly OsuSpriteText titleText, pageText; + + protected IconUsage Icon + { + get => iconSprite.Icon; + set => iconSprite.Icon = value; + } + + protected string Title + { + get => titleText.Text; + set => titleText.Text = value; + } + + protected string Section + { + get => pageText.Text; + set => pageText.Text = value; + } + + public Color4 AccentColour + { + get => pageText.Colour; + set => pageText.Colour = value; + } + + protected ScreenTitle() + { + AutoSizeAxes = Axes.Both; + + InternalChildren = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + iconSprite = new SpriteIcon + { + Size = new Vector2(25), + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(6, 0), + Children = new[] + { + titleText = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 25), + }, + pageText = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 25), + } + } + } + } + }, + }; + } + } +} diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index d33762374f..e470d554c9 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -62,6 +62,8 @@ public class OsuGame : OsuGameBase, IKeyBindingHandler private NotificationOverlay notifications; + private LoginOverlay loginOverlay; + private DialogOverlay dialogOverlay; private AccountCreationOverlay accountCreation; @@ -422,6 +424,13 @@ protected override void LoadComplete() loadComponentSingleFile(volume = new VolumeOverlay(), floatingOverlayContent.Add); loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add); + loadComponentSingleFile(loginOverlay = new LoginOverlay + { + GetToolbarHeight = () => ToolbarOffset, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }, floatingOverlayContent.Add); + loadComponentSingleFile(screenshotManager, Add); //overlay elements @@ -432,6 +441,7 @@ protected override void LoadComplete() loadComponentSingleFile(settings = new MainSettings { GetToolbarHeight = () => ToolbarOffset }, floatingOverlayContent.Add); loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add); + loadComponentSingleFile(notifications = new NotificationOverlay { GetToolbarHeight = () => ToolbarOffset, @@ -463,6 +473,7 @@ protected override void LoadComplete() dependencies.Cache(musicController); dependencies.Cache(beatmapSetOverlay); dependencies.Cache(notifications); + dependencies.Cache(loginOverlay); dependencies.Cache(dialogOverlay); dependencies.Cache(accountCreation); diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index e7caaa3aca..d0411ba9e7 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; +using System; namespace osu.Game.Overlays { @@ -19,6 +20,11 @@ public class LoginOverlay : OsuFocusedOverlayContainer private const float transition_time = 400; + /// + /// Provide a source for the toolbar height. + /// + public Func GetToolbarHeight; + public LoginOverlay() { AutoSizeAxes = Axes.Both; @@ -88,5 +94,12 @@ protected override void PopOut() settingsSection.Bounding = false; this.FadeOut(transition_time); } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + Padding = new MarginPadding { Top = GetToolbarHeight?.Invoke() ?? 0 }; + } } } diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 241c3dfd51..59d7a18a34 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -22,7 +22,7 @@ public class Toolbar : OverlayContainer public Action OnHome; - private ToolbarUserArea userArea; + private ToolbarUserButton userButton; protected override bool BlockPositionalInput => false; @@ -77,7 +77,7 @@ private void load(OsuGame osuGame) //{ // Icon = FontAwesome.search //}, - userArea = new ToolbarUserArea(), + userButton = new ToolbarUserButton(), new ToolbarNotificationButton(), } } @@ -143,7 +143,7 @@ protected override void PopIn() protected override void PopOut() { - userArea?.LoginOverlay.Hide(); + userButton?.StateContainer.Hide(); this.MoveToY(-DrawSize.Y, transition_time, Easing.OutQuint); this.FadeOut(transition_time); diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs b/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs deleted file mode 100644 index f9cf5d4350..0000000000 --- a/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osuTK; -using RectangleF = osu.Framework.Graphics.Primitives.RectangleF; - -namespace osu.Game.Overlays.Toolbar -{ - public class ToolbarUserArea : Container - { - public LoginOverlay LoginOverlay; - private ToolbarUserButton button; - - public override RectangleF BoundingBox => button.BoundingBox; - - [BackgroundDependencyLoader] - private void load() - { - RelativeSizeAxes = Axes.Y; - AutoSizeAxes = Axes.X; - - Children = new Drawable[] - { - button = new ToolbarUserButton - { - Action = () => LoginOverlay.ToggleVisibility(), - }, - LoginOverlay = new LoginOverlay - { - BypassAutoSizeAxes = Axes.Both, - Position = new Vector2(0, 1), - RelativePositionAxes = Axes.Y, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - } - }; - } - } -} diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 8d1910fc19..356ffa5180 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Toolbar { - public class ToolbarUserButton : ToolbarButton, IOnlineComponent + public class ToolbarUserButton : ToolbarOverlayToggleButton, IOnlineComponent { private readonly UpdateableAvatar avatar; @@ -42,10 +42,12 @@ public ToolbarUserButton() }); } - [BackgroundDependencyLoader] - private void load(IAPIProvider api) + [BackgroundDependencyLoader(true)] + private void load(IAPIProvider api, LoginOverlay login) { api.Register(this); + + StateContainer = login; } public void APIStateChanged(IAPIProvider api, APIState state) diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index dbfdc86571..7924086389 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -5,13 +5,10 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Screens; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.SearchableList; -using osuTK; using osuTK.Graphics; namespace osu.Game.Screens.Multi @@ -20,11 +17,11 @@ public class Header : Container { public const float HEIGHT = 121; - private readonly OsuSpriteText screenType; private readonly HeaderBreadcrumbControl breadcrumbs; public Header(ScreenStack stack) { + MultiHeaderTitle title; RelativeSizeAxes = Axes.X; Height = HEIGHT; @@ -41,39 +38,11 @@ public Header(ScreenStack stack) Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING + OsuScreen.HORIZONTAL_OVERFLOW_PADDING }, Children = new Drawable[] { - new FillFlowContainer + title = new MultiHeaderTitle { Anchor = Anchor.CentreLeft, Origin = Anchor.BottomLeft, - Position = new Vector2(-35f, 5f), - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10f, 0f), - Children = new Drawable[] - { - new SpriteIcon - { - Size = new Vector2(25), - Icon = OsuIcon.Multi, - }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new[] - { - new OsuSpriteText - { - Text = "multiplayer ", - Font = OsuFont.GetFont(size: 25) - }, - screenType = new OsuSpriteText - { - Font = OsuFont.GetFont(weight: FontWeight.Light, size: 25) - }, - }, - }, - }, + X = -35, }, breadcrumbs = new HeaderBreadcrumbControl(stack) { @@ -85,10 +54,10 @@ public Header(ScreenStack stack) }, }; - breadcrumbs.Current.ValueChanged += scren => + breadcrumbs.Current.ValueChanged += screen => { - if (scren.NewValue is IMultiplayerSubScreen multiScreen) - screenType.Text = multiScreen.ShortTitle.ToLowerInvariant(); + if (screen.NewValue is IMultiplayerSubScreen multiScreen) + title.Screen = multiScreen; }; breadcrumbs.Current.TriggerChange(); @@ -97,10 +66,25 @@ public Header(ScreenStack stack) [BackgroundDependencyLoader] private void load(OsuColour colours) { - screenType.Colour = colours.Yellow; breadcrumbs.StripColour = colours.Green; } + private class MultiHeaderTitle : ScreenTitle + { + public IMultiplayerSubScreen Screen + { + set => Section = value.ShortTitle.ToLowerInvariant(); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Title = "multiplayer"; + Icon = OsuIcon.Multi; + AccentColour = colours.Yellow; + } + } + private class HeaderBreadcrumbControl : ScreenBreadcrumbControl { public HeaderBreadcrumbControl(ScreenStack stack) diff --git a/osu.Game/Tests/Visual/ScreenTestCase.cs b/osu.Game/Tests/Visual/ScreenTestCase.cs index d10779349b..4fd4c7c207 100644 --- a/osu.Game/Tests/Visual/ScreenTestCase.cs +++ b/osu.Game/Tests/Visual/ScreenTestCase.cs @@ -1,8 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Screens; namespace osu.Game.Tests.Visual @@ -12,12 +12,19 @@ namespace osu.Game.Tests.Visual /// public abstract class ScreenTestCase : ManualInputManagerTestCase { - private OsuScreenStack stack; + private readonly OsuScreenStack stack; - [BackgroundDependencyLoader] - private void load() + private readonly Container content; + + protected override Container Content => content; + + protected ScreenTestCase() { - Add(stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }); + base.Content.AddRange(new Drawable[] + { + stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, + content = new Container { RelativeSizeAxes = Axes.Both } + }); } protected void LoadScreen(OsuScreen screen)