From e1eda89ea69234164ae055d1f129626d8fc970f7 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 8 Jan 2020 17:41:44 +0100 Subject: [PATCH 001/216] Implement OnlineContainer --- osu.Game/Online/OnlineContainer.cs | 76 ++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 osu.Game/Online/OnlineContainer.cs diff --git a/osu.Game/Online/OnlineContainer.cs b/osu.Game/Online/OnlineContainer.cs new file mode 100644 index 0000000000..6ab5203fe6 --- /dev/null +++ b/osu.Game/Online/OnlineContainer.cs @@ -0,0 +1,76 @@ +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Online.API; +using osu.Game.Online.Placeholders; + +namespace osu.Game.Online +{ + /// + /// A for dislaying online content who require a local user to be logged in. + /// Shows its children only when the local user is logged in and supports displaying a placeholder if not. + /// + public class OnlineViewContainer : Container, IOnlineComponent + { + private readonly Container content; + private readonly Container placeholderContainer; + private readonly Placeholder placeholder; + + private const int transform_time = 300; + + protected override Container Content => content; + + public OnlineViewContainer(string placeholder_message) + { + InternalChildren = new Drawable[] + { + content = new Container + { + RelativeSizeAxes = Axes.Both, + }, + placeholderContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + Child = placeholder = new LoginPlaceholder() + }, + }; + } + + public void APIStateChanged(IAPIProvider api, APIState state) + { + switch (state) + { + case APIState.Offline: + case APIState.Connecting: + Schedule(() =>updatePlaceholderVisibility(true)); + break; + + default: + Schedule(() => updatePlaceholderVisibility(false)); + break; + } + } + + private void updatePlaceholderVisibility(bool show_placeholder) + { + if (show_placeholder) + { + content.FadeOut(transform_time / 2, Easing.OutQuint); + placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 3 * transform_time, Easing.OutQuint); + placeholderContainer.FadeInFromZero(2 * transform_time, Easing.OutQuint); + } + else + { + placeholderContainer.FadeOut(transform_time / 2, Easing.OutQuint); + content.FadeIn(transform_time, Easing.OutQuint); + } + } + + [BackgroundDependencyLoader] + private void load(IAPIProvider api) + { + api.Register(this); + } + } +} From e9a52984845e9a39cab5a5dd09081aa7045d6436 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 12 Jan 2020 15:50:35 +0100 Subject: [PATCH 002/216] Allow setting the displayed text on LoginPlaceholder --- osu.Game/Online/Leaderboards/Leaderboard.cs | 2 +- osu.Game/Online/OnlineContainer.cs | 2 +- osu.Game/Online/Placeholders/LoginPlaceholder.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 55233bef6e..095e552ddd 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -151,7 +151,7 @@ namespace osu.Game.Online.Leaderboards break; case PlaceholderState.NotLoggedIn: - replacePlaceholder(new LoginPlaceholder()); + replacePlaceholder(new LoginPlaceholder(@"Please sign in to view online leaderboards!")); break; case PlaceholderState.NotSupporter: diff --git a/osu.Game/Online/OnlineContainer.cs b/osu.Game/Online/OnlineContainer.cs index 6ab5203fe6..6a8963599f 100644 --- a/osu.Game/Online/OnlineContainer.cs +++ b/osu.Game/Online/OnlineContainer.cs @@ -32,7 +32,7 @@ namespace osu.Game.Online { RelativeSizeAxes = Axes.Both, Alpha = 0, - Child = placeholder = new LoginPlaceholder() + Child = placeholder = new LoginPlaceholder(placeholder_message) }, }; } diff --git a/osu.Game/Online/Placeholders/LoginPlaceholder.cs b/osu.Game/Online/Placeholders/LoginPlaceholder.cs index ffc6623229..f3b5a86785 100644 --- a/osu.Game/Online/Placeholders/LoginPlaceholder.cs +++ b/osu.Game/Online/Placeholders/LoginPlaceholder.cs @@ -14,7 +14,7 @@ namespace osu.Game.Online.Placeholders [Resolved(CanBeNull = true)] private LoginOverlay login { get; set; } - public LoginPlaceholder() + public LoginPlaceholder(string actionMessage) { AddIcon(FontAwesome.Solid.UserLock, cp => { @@ -22,7 +22,7 @@ namespace osu.Game.Online.Placeholders cp.Padding = new MarginPadding { Right = 10 }; }); - AddText(@"Please sign in to view online leaderboards!"); + AddText(actionMessage); } protected override bool OnMouseDown(MouseDownEvent e) From 8f6c6ad77a6198c8954195e656099b6fc4450732 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 12 Jan 2020 17:43:44 +0100 Subject: [PATCH 003/216] Fix class name not corresponding to filename --- osu.Game/Online/{OnlineContainer.cs => OnlineViewContainer.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename osu.Game/Online/{OnlineContainer.cs => OnlineViewContainer.cs} (100%) diff --git a/osu.Game/Online/OnlineContainer.cs b/osu.Game/Online/OnlineViewContainer.cs similarity index 100% rename from osu.Game/Online/OnlineContainer.cs rename to osu.Game/Online/OnlineViewContainer.cs From 0422b326ad3faa719ba34852a4d80e3b22ce273d Mon Sep 17 00:00:00 2001 From: Lucas A Date: Mon, 13 Jan 2020 21:12:19 +0100 Subject: [PATCH 004/216] Add visual tests --- .../Online/TestSceneOnlineViewContainer.cs | 75 +++++++++++++++++++ osu.Game/Online/API/DummyAPIAccess.cs | 2 +- osu.Game/Online/OnlineViewContainer.cs | 25 ++++--- 3 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs new file mode 100644 index 0000000000..a8c50a37e7 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -0,0 +1,75 @@ +// Copyright (c) ppy Pty Ltd . 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.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Sprites; +using osu.Game.Online; +using osu.Game.Online.API; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.Online +{ + [TestFixture] + public class TestSceneOnlineViewContainer : OsuTestScene + { + private OnlineViewContainer onlineView; + private Box box; + + public TestSceneOnlineViewContainer() + { + Child = new Container + { + RelativeSizeAxes = Axes.Both, + Child = onlineView = new OnlineViewContainer(@"Please login to view dummy test content") + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + box = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Blue.Opacity(0.8f), + }, + new OsuSpriteText + { + Text = "dummy online content", + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load() + { + AddStep("set status to offline", () => + { + (API as DummyAPIAccess).State = APIState.Offline; + }); + + AddAssert("children are hidden", () => + { + return !onlineView.Children.First().Parent.IsPresent; + }); + + AddStep("set status to online", () => + { + (API as DummyAPIAccess).State = APIState.Online; + }); + + AddAssert("children are visible", () => + { + return onlineView.Children.First().Parent.IsPresent; + }); + } + } +} diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 7f23f9b5d5..a1c3475fd9 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -33,7 +33,7 @@ namespace osu.Game.Online.API public APIState State { get => state; - private set + set { if (state == value) return; diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 6a8963599f..a7f81b4776 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -1,4 +1,7 @@ -using osu.Framework.Allocation; +// 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.Online.API; @@ -20,7 +23,7 @@ namespace osu.Game.Online protected override Container Content => content; - public OnlineViewContainer(string placeholder_message) + public OnlineViewContainer(string placeholderMessage) { InternalChildren = new Drawable[] { @@ -32,7 +35,7 @@ namespace osu.Game.Online { RelativeSizeAxes = Axes.Both, Alpha = 0, - Child = placeholder = new LoginPlaceholder(placeholder_message) + Child = placeholder = new LoginPlaceholder(placeholderMessage) }, }; } @@ -43,7 +46,7 @@ namespace osu.Game.Online { case APIState.Offline: case APIState.Connecting: - Schedule(() =>updatePlaceholderVisibility(true)); + Schedule(() => updatePlaceholderVisibility(true)); break; default: @@ -52,18 +55,18 @@ namespace osu.Game.Online } } - private void updatePlaceholderVisibility(bool show_placeholder) + private void updatePlaceholderVisibility(bool showPlaceholder) { - if (show_placeholder) + if (showPlaceholder) { - content.FadeOut(transform_time / 2, Easing.OutQuint); - placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 3 * transform_time, Easing.OutQuint); - placeholderContainer.FadeInFromZero(2 * transform_time, Easing.OutQuint); + content.FadeOut(transform_time / 2, Easing.OutQuint); + placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 3 * transform_time, Easing.OutQuint); + placeholderContainer.FadeInFromZero(2 * transform_time, Easing.OutQuint); } else { - placeholderContainer.FadeOut(transform_time / 2, Easing.OutQuint); - content.FadeIn(transform_time, Easing.OutQuint); + placeholderContainer.FadeOut(transform_time / 2, Easing.OutQuint); + content.FadeIn(transform_time, Easing.OutQuint); } } From f00938971eda2ba95c451792a6ce56234f073532 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 17 Jan 2020 18:53:17 +0100 Subject: [PATCH 005/216] Apply review suggestions --- .../Online/TestSceneOnlineViewContainer.cs | 2 +- osu.Game/Online/OnlineViewContainer.cs | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index a8c50a37e7..9b7de2b7f4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual.Online Child = new Container { RelativeSizeAxes = Axes.Both, - Child = onlineView = new OnlineViewContainer(@"Please login to view dummy test content") + Child = onlineView = new OnlineViewContainer(@"view dummy test content") { RelativeSizeAxes = Axes.Both, Children = new Drawable[] diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index a7f81b4776..ac3a3edd67 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -23,6 +23,9 @@ namespace osu.Game.Online protected override Container Content => content; + [Resolved] + protected IAPIProvider API { get; private set; } + public OnlineViewContainer(string placeholderMessage) { InternalChildren = new Drawable[] @@ -35,12 +38,12 @@ namespace osu.Game.Online { RelativeSizeAxes = Axes.Both, Alpha = 0, - Child = placeholder = new LoginPlaceholder(placeholderMessage) + Child = placeholder = new LoginPlaceholder($@"Please sign in to {placeholderMessage}") }, }; } - public void APIStateChanged(IAPIProvider api, APIState state) + public virtual void APIStateChanged(IAPIProvider api, APIState state) { switch (state) { @@ -70,10 +73,16 @@ namespace osu.Game.Online } } - [BackgroundDependencyLoader] - private void load(IAPIProvider api) + protected override void LoadComplete() { - api.Register(this); + API?.Register(this); + base.LoadComplete(); + } + + protected override void Dispose(bool isDisposing) + { + API?.Unregister(this); + base.Dispose(isDisposing); } } } From e1f172e3f820c88b481f546b49752a71a1b754bc Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 17 Jan 2020 19:29:42 +0100 Subject: [PATCH 006/216] Fix CI issues --- .../Online/TestSceneOnlineViewContainer.cs | 25 +++++-------------- osu.Game/Online/OnlineViewContainer.cs | 4 +-- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index 9b7de2b7f4..4579e4f428 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -18,8 +18,7 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneOnlineViewContainer : OsuTestScene { - private OnlineViewContainer onlineView; - private Box box; + private readonly OnlineViewContainer onlineView; public TestSceneOnlineViewContainer() { @@ -31,7 +30,7 @@ namespace osu.Game.Tests.Visual.Online RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - box = new Box + new Box { RelativeSizeAxes = Axes.Both, Colour = Color4.Blue.Opacity(0.8f), @@ -51,25 +50,13 @@ namespace osu.Game.Tests.Visual.Online [BackgroundDependencyLoader] private void load() { - AddStep("set status to offline", () => - { - (API as DummyAPIAccess).State = APIState.Offline; - }); + AddStep("set status to offline", () => ((DummyAPIAccess)API).State = APIState.Offline); - AddAssert("children are hidden", () => - { - return !onlineView.Children.First().Parent.IsPresent; - }); + AddAssert("children are hidden", () => !onlineView.Children.First().Parent.IsPresent); - AddStep("set status to online", () => - { - (API as DummyAPIAccess).State = APIState.Online; - }); + AddStep("set status to online", () => ((DummyAPIAccess)API).State = APIState.Online); - AddAssert("children are visible", () => - { - return onlineView.Children.First().Parent.IsPresent; - }); + AddAssert("children are visible", () => onlineView.Children.First().Parent.IsPresent); } } } diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index ac3a3edd67..0a8432ee12 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -62,13 +62,13 @@ namespace osu.Game.Online { if (showPlaceholder) { - content.FadeOut(transform_time / 2, Easing.OutQuint); + content.FadeOut(150, Easing.OutQuint); placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 3 * transform_time, Easing.OutQuint); placeholderContainer.FadeInFromZero(2 * transform_time, Easing.OutQuint); } else { - placeholderContainer.FadeOut(transform_time / 2, Easing.OutQuint); + placeholderContainer.FadeOut(150, Easing.OutQuint); content.FadeIn(transform_time, Easing.OutQuint); } } From 6d51b344abfc6929f5029044dc01b10f8e9dc28d Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 19 Jan 2020 20:24:46 +0100 Subject: [PATCH 007/216] Display a loading animation when the user is connecting --- .../Online/TestSceneOnlineViewContainer.cs | 4 ++ osu.Game/Online/OnlineViewContainer.cs | 57 ++++++++++++++----- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index 4579e4f428..ddb672dbf4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -57,6 +57,10 @@ namespace osu.Game.Tests.Visual.Online AddStep("set status to online", () => ((DummyAPIAccess)API).State = APIState.Online); AddAssert("children are visible", () => onlineView.Children.First().Parent.IsPresent); + + AddStep("set status to connecting", () => ((DummyAPIAccess)API).State = APIState.Connecting); + + AddAssert("children are hidden", () => !onlineView.Children.First().Parent.IsPresent); } } } diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 0a8432ee12..35296409e5 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.Placeholders; @@ -15,12 +16,13 @@ namespace osu.Game.Online /// public class OnlineViewContainer : Container, IOnlineComponent { - private readonly Container content; private readonly Container placeholderContainer; private readonly Placeholder placeholder; + private readonly LoadingAnimation loading; private const int transform_time = 300; + private readonly Container content; protected override Container Content => content; [Resolved] @@ -40,6 +42,10 @@ namespace osu.Game.Online Alpha = 0, Child = placeholder = new LoginPlaceholder($@"Please sign in to {placeholderMessage}") }, + loading = new LoadingAnimation + { + Alpha = 0, + } }; } @@ -47,29 +53,43 @@ namespace osu.Game.Online { switch (state) { - case APIState.Offline: + case APIState.Failing: case APIState.Connecting: - Schedule(() => updatePlaceholderVisibility(true)); + Schedule(() => UpdatePlaceholderVisibility(PlaceholderStatus.Connecting)); break; - default: - Schedule(() => updatePlaceholderVisibility(false)); + case APIState.Offline: + Schedule(() => UpdatePlaceholderVisibility(PlaceholderStatus.Offline)); + break; + + case APIState.Online: + Schedule(() => UpdatePlaceholderVisibility(PlaceholderStatus.Online)); break; } } - private void updatePlaceholderVisibility(bool showPlaceholder) + protected void UpdatePlaceholderVisibility(PlaceholderStatus status) { - if (showPlaceholder) + switch (status) { - content.FadeOut(150, Easing.OutQuint); - placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 3 * transform_time, Easing.OutQuint); - placeholderContainer.FadeInFromZero(2 * transform_time, Easing.OutQuint); - } - else - { - placeholderContainer.FadeOut(150, Easing.OutQuint); - content.FadeIn(transform_time, Easing.OutQuint); + case PlaceholderStatus.Offline: + Content.FadeOut(150, Easing.OutQuint); + placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 3 * transform_time, Easing.OutQuint); + placeholderContainer.FadeInFromZero(2 * transform_time, Easing.OutQuint); + loading.Hide(); + break; + + case PlaceholderStatus.Online: + placeholderContainer.FadeOut(150, Easing.OutQuint); + Content.FadeIn(transform_time, Easing.OutQuint); + loading.Hide(); + break; + + case PlaceholderStatus.Connecting: + loading.Show(); + placeholderContainer.FadeOut(150, Easing.OutQuint); + Content.FadeOut(150, Easing.OutQuint); + break; } } @@ -84,5 +104,12 @@ namespace osu.Game.Online API?.Unregister(this); base.Dispose(isDisposing); } + + protected enum PlaceholderStatus + { + Offline, + Online, + Connecting, + } } } From d3dc0b63ff9cc9715b5e46909e39ef76435d5007 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Thu, 23 Jan 2020 19:09:34 +0100 Subject: [PATCH 008/216] Remove string concatenation from ctor --- osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs | 2 +- osu.Game/Online/OnlineViewContainer.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index ddb672dbf4..fddb82d400 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.Online Child = new Container { RelativeSizeAxes = Axes.Both, - Child = onlineView = new OnlineViewContainer(@"view dummy test content") + Child = onlineView = new OnlineViewContainer(@"Please sign in to view dummy test content") { RelativeSizeAxes = Axes.Both, Children = new Drawable[] diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 35296409e5..49174320d3 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -40,7 +40,7 @@ namespace osu.Game.Online { RelativeSizeAxes = Axes.Both, Alpha = 0, - Child = placeholder = new LoginPlaceholder($@"Please sign in to {placeholderMessage}") + Child = placeholder = new LoginPlaceholder(placeholderMessage) }, loading = new LoadingAnimation { From 7ca9f4dc2091c56bd66b11365cbc2dfaa403e4df Mon Sep 17 00:00:00 2001 From: Lucas A Date: Fri, 24 Jan 2020 21:10:31 +0100 Subject: [PATCH 009/216] Apply review suggestions --- .../Online/TestSceneOnlineViewContainer.cs | 85 ++++++++++++------- osu.Game/Online/OnlineViewContainer.cs | 48 +++-------- 2 files changed, 66 insertions(+), 67 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index fddb82d400..277146e4be 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -1,14 +1,13 @@ // Copyright (c) ppy Pty Ltd . 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.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Online; using osu.Game.Online.API; using osuTK.Graphics; @@ -18,49 +17,75 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneOnlineViewContainer : OsuTestScene { - private readonly OnlineViewContainer onlineView; + private readonly TestOnlineViewContainer onlineView; public TestSceneOnlineViewContainer() { Child = new Container { RelativeSizeAxes = Axes.Both, - Child = onlineView = new OnlineViewContainer(@"Please sign in to view dummy test content") - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Blue.Opacity(0.8f), - }, - new OsuSpriteText - { - Text = "dummy online content", - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } - } - } + Child = onlineView = new TestOnlineViewContainer() }; } - [BackgroundDependencyLoader] - private void load() + private class TestOnlineViewContainer : OnlineViewContainer + { + public new Container Content => base.Content; + + public new LoadingAnimation LoadingAnimation => base.LoadingAnimation; + + public TestOnlineViewContainer() + : base(@"Please sign in to view dummy test content") + { + RelativeSizeAxes = Axes.Both; + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Blue.Opacity(0.8f), + }, + new OsuSpriteText + { + Text = "dummy online content", + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; + } + } + + [Test] + public void TestOnlineStateVisibility() + { + AddStep("set status to online", () => ((DummyAPIAccess)API).State = APIState.Online); + + AddAssert("children are visible", () => onlineView.Content.IsPresent); + AddAssert("loading animation is not visible", () => !onlineView.LoadingAnimation.IsPresent); + } + + [Test] + public void TestOfflineStateVisibility() { AddStep("set status to offline", () => ((DummyAPIAccess)API).State = APIState.Offline); - AddAssert("children are hidden", () => !onlineView.Children.First().Parent.IsPresent); - - AddStep("set status to online", () => ((DummyAPIAccess)API).State = APIState.Online); - - AddAssert("children are visible", () => onlineView.Children.First().Parent.IsPresent); + AddAssert("children are hidden", () => !onlineView.Content.IsPresent); + AddAssert("loading animation is not visible", () => !onlineView.LoadingAnimation.IsPresent); + } + [Test] + public void TestConnectingStateVisibility() + { AddStep("set status to connecting", () => ((DummyAPIAccess)API).State = APIState.Connecting); - AddAssert("children are hidden", () => !onlineView.Children.First().Parent.IsPresent); + AddAssert("children are hidden", () => !onlineView.Content.IsPresent); + AddAssert("loading animation is visible", () => onlineView.LoadingAnimation.IsPresent); + + AddStep("set status to failing", () => ((DummyAPIAccess)API).State = APIState.Failing); + + AddAssert("children are hidden", () => !onlineView.Content.IsPresent); + AddAssert("loading animation is visible", () => onlineView.LoadingAnimation.IsPresent); } } } diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 49174320d3..7874a9fcaf 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -14,16 +14,15 @@ namespace osu.Game.Online /// A for dislaying online content who require a local user to be logged in. /// Shows its children only when the local user is logged in and supports displaying a placeholder if not. /// - public class OnlineViewContainer : Container, IOnlineComponent + public abstract class OnlineViewContainer : Container, IOnlineComponent { private readonly Container placeholderContainer; private readonly Placeholder placeholder; - private readonly LoadingAnimation loading; + protected readonly LoadingAnimation LoadingAnimation; private const int transform_time = 300; - private readonly Container content; - protected override Container Content => content; + protected override Container Content { get; } [Resolved] protected IAPIProvider API { get; private set; } @@ -32,7 +31,7 @@ namespace osu.Game.Online { InternalChildren = new Drawable[] { - content = new Container + Content = new Container { RelativeSizeAxes = Axes.Both, }, @@ -42,7 +41,7 @@ namespace osu.Game.Online Alpha = 0, Child = placeholder = new LoginPlaceholder(placeholderMessage) }, - loading = new LoadingAnimation + LoadingAnimation = new LoadingAnimation { Alpha = 0, } @@ -53,40 +52,22 @@ namespace osu.Game.Online { switch (state) { - case APIState.Failing: - case APIState.Connecting: - Schedule(() => UpdatePlaceholderVisibility(PlaceholderStatus.Connecting)); - break; - case APIState.Offline: - Schedule(() => UpdatePlaceholderVisibility(PlaceholderStatus.Offline)); - break; - - case APIState.Online: - Schedule(() => UpdatePlaceholderVisibility(PlaceholderStatus.Online)); - break; - } - } - - protected void UpdatePlaceholderVisibility(PlaceholderStatus status) - { - switch (status) - { - case PlaceholderStatus.Offline: Content.FadeOut(150, Easing.OutQuint); placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 3 * transform_time, Easing.OutQuint); placeholderContainer.FadeInFromZero(2 * transform_time, Easing.OutQuint); - loading.Hide(); + LoadingAnimation.Hide(); break; - case PlaceholderStatus.Online: + case APIState.Online: placeholderContainer.FadeOut(150, Easing.OutQuint); Content.FadeIn(transform_time, Easing.OutQuint); - loading.Hide(); + LoadingAnimation.Hide(); break; - case PlaceholderStatus.Connecting: - loading.Show(); + case APIState.Failing: + case APIState.Connecting: + LoadingAnimation.Show(); placeholderContainer.FadeOut(150, Easing.OutQuint); Content.FadeOut(150, Easing.OutQuint); break; @@ -104,12 +85,5 @@ namespace osu.Game.Online API?.Unregister(this); base.Dispose(isDisposing); } - - protected enum PlaceholderStatus - { - Offline, - Online, - Connecting, - } } } From 30e0a34e50d083af8726aaaff54fde5c3133f4b0 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 5 Feb 2020 15:04:10 +0100 Subject: [PATCH 010/216] Wrap Content into a container for animating visibility. --- .../Online/TestSceneOnlineViewContainer.cs | 14 ++++--- osu.Game/Online/OnlineViewContainer.cs | 39 ++++++++++--------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index 277146e4be..5427db5af3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -30,8 +30,6 @@ namespace osu.Game.Tests.Visual.Online private class TestOnlineViewContainer : OnlineViewContainer { - public new Container Content => base.Content; - public new LoadingAnimation LoadingAnimation => base.LoadingAnimation; public TestOnlineViewContainer() @@ -54,6 +52,10 @@ namespace osu.Game.Tests.Visual.Online } }; } + + protected override void FadeContentOut(Drawable content) => content.Hide(); + + protected override void FadeContentIn(Drawable content) => content.Show(); } [Test] @@ -61,7 +63,7 @@ namespace osu.Game.Tests.Visual.Online { AddStep("set status to online", () => ((DummyAPIAccess)API).State = APIState.Online); - AddAssert("children are visible", () => onlineView.Content.IsPresent); + AddAssert("children are visible", () => onlineView.TransformationTarget.IsPresent); AddAssert("loading animation is not visible", () => !onlineView.LoadingAnimation.IsPresent); } @@ -70,7 +72,7 @@ namespace osu.Game.Tests.Visual.Online { AddStep("set status to offline", () => ((DummyAPIAccess)API).State = APIState.Offline); - AddAssert("children are hidden", () => !onlineView.Content.IsPresent); + AddAssert("children are hidden", () => !onlineView.TransformationTarget.IsPresent); AddAssert("loading animation is not visible", () => !onlineView.LoadingAnimation.IsPresent); } @@ -79,12 +81,12 @@ namespace osu.Game.Tests.Visual.Online { AddStep("set status to connecting", () => ((DummyAPIAccess)API).State = APIState.Connecting); - AddAssert("children are hidden", () => !onlineView.Content.IsPresent); + AddAssert("children are hidden", () => !onlineView.TransformationTarget.IsPresent); AddAssert("loading animation is visible", () => onlineView.LoadingAnimation.IsPresent); AddStep("set status to failing", () => ((DummyAPIAccess)API).State = APIState.Failing); - AddAssert("children are hidden", () => !onlineView.Content.IsPresent); + AddAssert("children are hidden", () => !onlineView.TransformationTarget.IsPresent); AddAssert("loading animation is visible", () => onlineView.LoadingAnimation.IsPresent); } } diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 7874a9fcaf..ac5a7941ea 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -11,36 +11,35 @@ using osu.Game.Online.Placeholders; namespace osu.Game.Online { /// - /// A for dislaying online content who require a local user to be logged in. + /// A for dislaying online content which require a local user to be logged in. /// Shows its children only when the local user is logged in and supports displaying a placeholder if not. /// public abstract class OnlineViewContainer : Container, IOnlineComponent { - private readonly Container placeholderContainer; private readonly Placeholder placeholder; protected readonly LoadingAnimation LoadingAnimation; - private const int transform_time = 300; + protected const double TRANSFORM_TIME = 300.0; + internal readonly Container TransformationTarget; protected override Container Content { get; } [Resolved] protected IAPIProvider API { get; private set; } - public OnlineViewContainer(string placeholderMessage) + protected OnlineViewContainer(string placeholderMessage) { InternalChildren = new Drawable[] { - Content = new Container + TransformationTarget = new Container { RelativeSizeAxes = Axes.Both, + Child = Content = new Container + { + RelativeSizeAxes = Axes.Both, + } }, - placeholderContainer = new Container - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - Child = placeholder = new LoginPlaceholder(placeholderMessage) - }, + placeholder = new LoginPlaceholder(placeholderMessage), LoadingAnimation = new LoadingAnimation { Alpha = 0, @@ -53,27 +52,31 @@ namespace osu.Game.Online switch (state) { case APIState.Offline: - Content.FadeOut(150, Easing.OutQuint); - placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 3 * transform_time, Easing.OutQuint); - placeholderContainer.FadeInFromZero(2 * transform_time, Easing.OutQuint); + FadeContentOut(TransformationTarget); + placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 3 * TRANSFORM_TIME, Easing.OutQuint); + placeholder.FadeInFromZero(2 * TRANSFORM_TIME, Easing.OutQuint); LoadingAnimation.Hide(); break; case APIState.Online: - placeholderContainer.FadeOut(150, Easing.OutQuint); - Content.FadeIn(transform_time, Easing.OutQuint); + FadeContentIn(TransformationTarget); + placeholder.FadeOut(TRANSFORM_TIME / 2, Easing.OutQuint); LoadingAnimation.Hide(); break; case APIState.Failing: case APIState.Connecting: + FadeContentOut(TransformationTarget); LoadingAnimation.Show(); - placeholderContainer.FadeOut(150, Easing.OutQuint); - Content.FadeOut(150, Easing.OutQuint); + placeholder.FadeOut(TRANSFORM_TIME / 2, Easing.OutQuint); break; } } + protected abstract void FadeContentOut(Drawable content); + + protected abstract void FadeContentIn(Drawable content); + protected override void LoadComplete() { API?.Register(this); From b45f1ef99a6489984534cf86ac219469b6d0265f Mon Sep 17 00:00:00 2001 From: Maximilian Junges Date: Sun, 9 Feb 2020 22:27:37 +0100 Subject: [PATCH 011/216] make timestamps hoverable --- osu.Game/Overlays/BeatmapSet/AuthorInfo.cs | 26 +++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index 096e91b65b..485ca100c6 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.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; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -50,7 +51,7 @@ namespace osu.Game.Overlays.BeatmapSet fields.Children = new Drawable[] { new Field("mapped by", BeatmapSet.Metadata.Author.Username, OsuFont.GetFont(weight: FontWeight.Regular, italics: true)), - new Field("submitted on", online.Submitted.ToString(@"MMMM d, yyyy"), OsuFont.GetFont(weight: FontWeight.Bold)) + new Field("submitted", online.Submitted, OsuFont.GetFont(weight: FontWeight.Bold)) { Margin = new MarginPadding { Top = 5 }, }, @@ -58,11 +59,11 @@ namespace osu.Game.Overlays.BeatmapSet if (online.Ranked.HasValue) { - fields.Add(new Field("ranked on", online.Ranked.Value.ToString(@"MMMM d, yyyy"), OsuFont.GetFont(weight: FontWeight.Bold))); + fields.Add(new Field("ranked", online.Ranked.Value, OsuFont.GetFont(weight: FontWeight.Bold))); } else if (online.LastUpdated.HasValue) { - fields.Add(new Field("last updated on", online.LastUpdated.Value.ToString(@"MMMM d, yyyy"), OsuFont.GetFont(weight: FontWeight.Bold))); + fields.Add(new Field("last updated", online.LastUpdated.Value, OsuFont.GetFont(weight: FontWeight.Bold))); } } @@ -126,6 +127,25 @@ namespace osu.Game.Overlays.BeatmapSet }, }; } + + public Field(string first, DateTimeOffset second, FontUsage secondFont) + { + AutoSizeAxes = Axes.Both; + Direction = FillDirection.Horizontal; + + Children = new[] + { + new OsuSpriteText + { + Text = $"{first} ", + Font = OsuFont.GetFont(size: 13) + }, + new DrawableDate(second) + { + Font = secondFont.With(size: 13) + } + }; + } } } } From 867c7338093934caf6164ba27029b3e65d006614 Mon Sep 17 00:00:00 2001 From: Maximilian Junges Date: Sun, 9 Feb 2020 23:19:32 +0100 Subject: [PATCH 012/216] make score date hoverable --- .../BeatmapSet/Scores/TopScoreUserSection.cs | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 72a7efd777..ba1db8ef03 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.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; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -12,7 +13,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Online.Leaderboards; using osu.Game.Scoring; using osu.Game.Users.Drawables; -using osu.Game.Utils; using osuTK; using osuTK.Graphics; @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly UpdateableRank rank; private readonly UpdateableAvatar avatar; private readonly LinkFlowContainer usernameText; - private readonly SpriteText date; + private readonly DrawableDate achievedOn; private readonly UpdateableFlag flag; public TopScoreUserSection() @@ -92,11 +92,24 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, }, - date = new OsuSpriteText + new FillFlowContainer() { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold) + Children = new[] + { + new OsuSpriteText + { + Text = "achieved ", + Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold) + }, + achievedOn = new DrawableDate(DateTimeOffset.MinValue) + { + Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold) + }, + } }, flag = new UpdateableFlag { @@ -125,7 +138,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { avatar.User = value.User; flag.Country = value.User.Country; - date.Text = $@"achieved {HumanizerUtils.Humanize(value.Date)}"; + achievedOn.Date = value.Date; usernameText.Clear(); usernameText.AddUserLink(value.User); @@ -134,4 +147,4 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } } -} +} \ No newline at end of file From 3e06324f61770bd6bcee4135c0573d5fc1720b0a Mon Sep 17 00:00:00 2001 From: Maximilian Junges Date: Sun, 9 Feb 2020 23:39:34 +0100 Subject: [PATCH 013/216] fix formatting issue --- osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index ba1db8ef03..6c33629c0e 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -92,7 +92,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, }, - new FillFlowContainer() + new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, From ed8cb1d6bf42b35b97370810216404532acb114a Mon Sep 17 00:00:00 2001 From: Maximilian Junges Date: Sun, 9 Feb 2020 23:46:06 +0100 Subject: [PATCH 014/216] add missing eof newline --- osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 6c33629c0e..94a6334401 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -147,4 +147,4 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } } -} \ No newline at end of file +} From 627833844839dec52e21f1ad7bc00cd796933a9c Mon Sep 17 00:00:00 2001 From: Maximilian Junges Date: Tue, 11 Feb 2020 14:21:12 +0100 Subject: [PATCH 015/216] implement custom tooltip for DrawableDate --- osu.Game/Graphics/DrawableDate.cs | 75 ++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 0224c77ee8..dcbea96071 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -4,13 +4,16 @@ using System; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Sprites; using osu.Game.Utils; +using osuTK; namespace osu.Game.Graphics { - public class DrawableDate : OsuSpriteText, IHasTooltip + public class DrawableDate : OsuSpriteText, IHasCustomTooltip { private DateTimeOffset date; @@ -75,6 +78,74 @@ namespace osu.Game.Graphics private void updateTime() => Text = Format(); - public virtual string TooltipText => string.Format($"{Date:MMMM d, yyyy h:mm tt \"UTC\"z}"); + public ITooltip GetCustomTooltip() => new DateTooltip(); + + public object TooltipContent => Date; + + private class DateTooltip : VisibilityContainer, ITooltip + { + private readonly OsuSpriteText dateText, timeText; + private readonly Box background; + + public DateTooltip() + { + AutoSizeAxes = Axes.Both; + Masking = true; + CornerRadius = 5; + + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Padding = new MarginPadding(10), + Children = new Drawable[] + { + dateText = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + }, + timeText = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular), + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + } + } + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + // Temporary colour since it's currently impossible to change it without bugs (see https://github.com/ppy/osu-framework/issues/3231) + // If above is fixed, this should use OverlayColourProvider + background.Colour = colours.Gray1; + timeText.Colour = colours.GreyCyanLighter; + } + + protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); + protected override void PopOut() => this.FadeOut(200, Easing.OutQuint); + + public bool SetContent(object content) + { + if (!(content is DateTimeOffset date)) + return false; + + dateText.Text = string.Format($"{date:d MMMM yyyy}") + " "; + timeText.Text = string.Format($"{date:hh:mm:ss \"UTC\"z}"); + return true; + } + + public void Move(Vector2 pos) => Position = pos; + } } } From b9e10cb49872c4eb0253a6498050e5cca49a96e0 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Tue, 11 Feb 2020 18:10:46 +0100 Subject: [PATCH 016/216] Privatize ViewTarget --- .../Online/TestSceneOnlineViewContainer.cs | 18 ++++++++++++------ osu.Game/Online/OnlineViewContainer.cs | 16 ++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index 5427db5af3..2b9609f6e0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -32,6 +32,8 @@ namespace osu.Game.Tests.Visual.Online { public new LoadingAnimation LoadingAnimation => base.LoadingAnimation; + public CompositeDrawable ViewTarget => base.Content.Parent; + public TestOnlineViewContainer() : base(@"Please sign in to view dummy test content") { @@ -53,9 +55,9 @@ namespace osu.Game.Tests.Visual.Online }; } - protected override void FadeContentOut(Drawable content) => content.Hide(); + protected override void PopContentOut(Drawable content) => content.Hide(); - protected override void FadeContentIn(Drawable content) => content.Show(); + protected override void PopContentIn(Drawable content) => content.Show(); } [Test] @@ -63,7 +65,7 @@ namespace osu.Game.Tests.Visual.Online { AddStep("set status to online", () => ((DummyAPIAccess)API).State = APIState.Online); - AddAssert("children are visible", () => onlineView.TransformationTarget.IsPresent); + AddAssert("children are visible", () => onlineView.ViewTarget.IsPresent); AddAssert("loading animation is not visible", () => !onlineView.LoadingAnimation.IsPresent); } @@ -72,7 +74,7 @@ namespace osu.Game.Tests.Visual.Online { AddStep("set status to offline", () => ((DummyAPIAccess)API).State = APIState.Offline); - AddAssert("children are hidden", () => !onlineView.TransformationTarget.IsPresent); + AddAssert("children are hidden", () => !onlineView.ViewTarget.IsPresent); AddAssert("loading animation is not visible", () => !onlineView.LoadingAnimation.IsPresent); } @@ -81,12 +83,16 @@ namespace osu.Game.Tests.Visual.Online { AddStep("set status to connecting", () => ((DummyAPIAccess)API).State = APIState.Connecting); - AddAssert("children are hidden", () => !onlineView.TransformationTarget.IsPresent); + AddAssert("children are hidden", () => !onlineView.ViewTarget.IsPresent); AddAssert("loading animation is visible", () => onlineView.LoadingAnimation.IsPresent); + } + [Test] + public void TestFailingStateVisibility() + { AddStep("set status to failing", () => ((DummyAPIAccess)API).State = APIState.Failing); - AddAssert("children are hidden", () => !onlineView.TransformationTarget.IsPresent); + AddAssert("children are hidden", () => !onlineView.ViewTarget.IsPresent); AddAssert("loading animation is visible", () => onlineView.LoadingAnimation.IsPresent); } } diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index ac5a7941ea..c512ca531a 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -11,7 +11,7 @@ using osu.Game.Online.Placeholders; namespace osu.Game.Online { /// - /// A for dislaying online content which require a local user to be logged in. + /// A for displaying online content which require a local user to be logged in. /// Shows its children only when the local user is logged in and supports displaying a placeholder if not. /// public abstract class OnlineViewContainer : Container, IOnlineComponent @@ -21,7 +21,7 @@ namespace osu.Game.Online protected const double TRANSFORM_TIME = 300.0; - internal readonly Container TransformationTarget; + private readonly Container viewTarget; protected override Container Content { get; } [Resolved] @@ -31,7 +31,7 @@ namespace osu.Game.Online { InternalChildren = new Drawable[] { - TransformationTarget = new Container + viewTarget = new Container { RelativeSizeAxes = Axes.Both, Child = Content = new Container @@ -52,30 +52,30 @@ namespace osu.Game.Online switch (state) { case APIState.Offline: - FadeContentOut(TransformationTarget); + PopContentOut(viewTarget); placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 3 * TRANSFORM_TIME, Easing.OutQuint); placeholder.FadeInFromZero(2 * TRANSFORM_TIME, Easing.OutQuint); LoadingAnimation.Hide(); break; case APIState.Online: - FadeContentIn(TransformationTarget); + PopContentIn(viewTarget); placeholder.FadeOut(TRANSFORM_TIME / 2, Easing.OutQuint); LoadingAnimation.Hide(); break; case APIState.Failing: case APIState.Connecting: - FadeContentOut(TransformationTarget); + PopContentOut(viewTarget); LoadingAnimation.Show(); placeholder.FadeOut(TRANSFORM_TIME / 2, Easing.OutQuint); break; } } - protected abstract void FadeContentOut(Drawable content); + protected abstract void PopContentOut(Drawable content); - protected abstract void FadeContentIn(Drawable content); + protected abstract void PopContentIn(Drawable content); protected override void LoadComplete() { From c386589cc09682ccf21db710775aa4bc6420e64e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Feb 2020 19:02:25 +0900 Subject: [PATCH 017/216] Reapply current state, not idle --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index e391157b5b..f4ce71b803 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -116,7 +116,7 @@ namespace osu.Game.Rulesets.Objects.Drawables HitObject.DefaultsApplied += onDefaultsApplied; startTimeBindable = HitObject.StartTimeBindable.GetBoundCopy(); - startTimeBindable.BindValueChanged(_ => updateState(ArmedState.Idle, true)); + startTimeBindable.BindValueChanged(_ => updateState(State.Value, true)); if (HitObject is IHasComboInformation combo) { From f7ee675102c4dc76f6b69711046f4678515988b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Feb 2020 19:02:54 +0900 Subject: [PATCH 018/216] Clear and revert to negative infinity, avoiding transforms getting left behind on StartTime change --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index f4ce71b803..d3a0b3450f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -250,8 +250,8 @@ namespace osu.Game.Rulesets.Objects.Drawables double transformTime = HitObject.StartTime - InitialLifetimeOffset; - base.ApplyTransformsAt(transformTime, true); - base.ClearTransformsAfter(transformTime, true); + base.ApplyTransformsAt(double.MinValue, true); + base.ClearTransformsAfter(double.MinValue, true); using (BeginAbsoluteSequence(transformTime, true)) { From 85a443783755a52cc2d46581644180a264339a2d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 12 Feb 2020 19:03:22 +0900 Subject: [PATCH 019/216] Fix editor custom FadeOut causing overlapping issues by removing existing FadeOut --- osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs index 22b4c3e82e..a8719e0aa8 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs @@ -40,6 +40,8 @@ namespace osu.Game.Rulesets.Osu.Edit if (existing == null) return; + hitObject.RemoveTransform(existing); + using (hitObject.BeginAbsoluteSequence(existing.StartTime)) hitObject.FadeOut(editor_hit_object_fade_out_extension).Expire(); break; From e34a24a063dc7e67a48dc16abe1463012e4133ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Feb 2020 10:45:16 +0900 Subject: [PATCH 020/216] Update placement blueprint more often for better display --- .../Components/ComposeBlueprintContainer.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index 8b47ea2c6c..7087eac6b6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -76,17 +76,6 @@ namespace osu.Game.Screens.Edit.Compose.Components #endregion - protected override bool OnMouseMove(MouseMoveEvent e) - { - if (currentPlacement != null) - { - updatePlacementPosition(e.ScreenSpaceMousePosition); - return true; - } - - return base.OnMouseMove(e); - } - protected override void Update() { base.Update(); @@ -95,6 +84,9 @@ namespace osu.Game.Screens.Edit.Compose.Components createPlacement(); else if (currentPlacement?.PlacementActive == false) removePlacement(); + + if (currentPlacement != null) + updatePlacementPosition(inputManager.CurrentState.Mouse.Position); } protected sealed override SelectionBlueprint CreateBlueprintFor(HitObject hitObject) From 03bf10f9a24a7a5b259e13435a9979c4e32adfea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Feb 2020 11:15:00 +0900 Subject: [PATCH 021/216] Remove unused using statement --- .../Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index 7087eac6b6..0eb77a8561 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -7,7 +7,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; -using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Objects; From 118f862342dd5903cfdea4661c15302ca6b361f1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 13 Feb 2020 12:02:10 +0900 Subject: [PATCH 022/216] Fix not being able to seek using scroll wheel in timeline while playing track --- .../Components/Timeline/ZoomableScrollContainer.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index 7ce8a751e0..baaad63e57 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -2,10 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Transforms; using osu.Framework.Input.Events; +using osu.Framework.Timing; using osu.Framework.Utils; using osu.Game.Graphics.Containers; using osuTK; @@ -30,6 +32,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private float currentZoom = 1; + [Resolved] + private IFrameBasedClock editorClock { get; set; } + public ZoomableScrollContainer() : base(Direction.Horizontal) { @@ -104,8 +109,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline protected override bool OnScroll(ScrollEvent e) { if (e.IsPrecise) + { + // can't handle scroll correctly while playing. + // the editor will handle this case for us. + if (editorClock.IsRunning) + return false; + // for now, we don't support zoom when using a precision scroll device. this needs gesture support. return base.OnScroll(e); + } setZoomTarget(zoomTarget + e.ScrollDelta.Y, zoomedContent.ToLocalSpace(e.ScreenSpaceMousePosition).X); return true; From 6f7196b0b81c4063c43006f655090e434df259a9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 12 Feb 2020 19:52:47 +0900 Subject: [PATCH 023/216] Make beatmap detail area abstractable --- osu.Game/Configuration/OsuConfigManager.cs | 2 +- osu.Game/Screens/Select/BeatmapDetailArea.cs | 106 +++++++------ .../Select/BeatmapDetailAreaDetailTabItem.cs | 10 ++ .../BeatmapDetailAreaLeaderboardTabItem.cs | 22 +++ .../Select/BeatmapDetailAreaTabControl.cs | 51 ++++--- .../Select/BeatmapDetailAreaTabItem.cs | 35 +++++ osu.Game/Screens/Select/MatchSongSelect.cs | 2 + .../Screens/Select/PlayBeatmapDetailArea.cs | 143 ++++++++++++++++++ osu.Game/Screens/Select/PlaySongSelect.cs | 4 + osu.Game/Screens/Select/SongSelect.cs | 20 +-- 10 files changed, 318 insertions(+), 77 deletions(-) create mode 100644 osu.Game/Screens/Select/BeatmapDetailAreaDetailTabItem.cs create mode 100644 osu.Game/Screens/Select/BeatmapDetailAreaLeaderboardTabItem.cs create mode 100644 osu.Game/Screens/Select/BeatmapDetailAreaTabItem.cs create mode 100644 osu.Game/Screens/Select/PlayBeatmapDetailArea.cs diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 6ae3c7ac64..ce959e9057 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -20,7 +20,7 @@ namespace osu.Game.Configuration Set(OsuSetting.Ruleset, 0, 0, int.MaxValue); Set(OsuSetting.Skin, 0, -1, int.MaxValue); - Set(OsuSetting.BeatmapDetailTab, BeatmapDetailTab.Details); + Set(OsuSetting.BeatmapDetailTab, PlayBeatmapDetailArea.TabType.Details); Set(OsuSetting.ShowConvertedBeatmaps, true); Set(OsuSetting.DisplayStarsMinimum, 0.0, 0, 10, 0.1); diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index 71733c9f06..1aae0cc243 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -2,37 +2,44 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; -using osu.Game.Screens.Select.Leaderboards; namespace osu.Game.Screens.Select { - public class BeatmapDetailArea : Container + public abstract class BeatmapDetailArea : Container { private const float details_padding = 10; - private readonly Container content; - protected override Container Content => content; - - public readonly BeatmapDetails Details; - public readonly BeatmapLeaderboard Leaderboard; - private WorkingBeatmap beatmap; - public WorkingBeatmap Beatmap + public virtual WorkingBeatmap Beatmap { get => beatmap; set { beatmap = value; - Details.Beatmap = beatmap?.BeatmapInfo; - Leaderboard.Beatmap = beatmap is DummyWorkingBeatmap ? null : beatmap?.BeatmapInfo; + + Details.Beatmap = value?.BeatmapInfo; } } - public BeatmapDetailArea() + public readonly BeatmapDetails Details; + + protected Bindable CurrentTab + { + get => tabControl.Current; + set => tabControl.Current = value; + } + + private readonly Container content; + protected override Container Content => content; + + private readonly BeatmapDetailAreaTabControl tabControl; + + protected BeatmapDetailArea() { AddRangeInternal(new Drawable[] { @@ -40,51 +47,62 @@ namespace osu.Game.Screens.Select { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT }, - }, - new BeatmapDetailAreaTabControl - { - RelativeSizeAxes = Axes.X, - OnFilter = (tab, mods) => + Child = Details = new BeatmapDetails { - Leaderboard.FilterMods = mods; - - switch (tab) - { - case BeatmapDetailTab.Details: - Details.Show(); - Leaderboard.Hide(); - break; - - default: - Details.Hide(); - Leaderboard.Scope = (BeatmapLeaderboardScope)tab - 1; - Leaderboard.Show(); - break; - } - }, + RelativeSizeAxes = Axes.X, + Alpha = 0, + Margin = new MarginPadding { Top = details_padding }, + } }, - }); - - AddRange(new Drawable[] - { - Details = new BeatmapDetails + tabControl = new BeatmapDetailAreaTabControl { RelativeSizeAxes = Axes.X, - Alpha = 0, - Margin = new MarginPadding { Top = details_padding }, + TabItems = CreateTabItems(), + OnFilter = OnTabChanged, }, - Leaderboard = new BeatmapLeaderboard - { - RelativeSizeAxes = Axes.Both, - } }); } + /// + /// Refreshes the currently-displayed details. + /// + public virtual void Refresh() + { + } + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); Details.Height = Math.Min(DrawHeight - details_padding * 3 - BeatmapDetailAreaTabControl.HEIGHT, 450); } + + /// + /// Invoked when a new tab is selected. + /// + /// The tab that was selected. + /// Whether the currently-selected mods should be considered. + protected virtual void OnTabChanged(BeatmapDetailAreaTabItem tab, bool selectedMods) + { + switch (tab) + { + case BeatmapDetailAreaDetailTabItem _: + Details.Show(); + break; + + default: + Details.Hide(); + break; + } + } + + /// + /// Creates the tabs to be displayed. + /// + /// The tabs. + protected virtual BeatmapDetailAreaTabItem[] CreateTabItems() => new BeatmapDetailAreaTabItem[] + { + new BeatmapDetailAreaDetailTabItem(), + }; } } diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaDetailTabItem.cs b/osu.Game/Screens/Select/BeatmapDetailAreaDetailTabItem.cs new file mode 100644 index 0000000000..7376cb4708 --- /dev/null +++ b/osu.Game/Screens/Select/BeatmapDetailAreaDetailTabItem.cs @@ -0,0 +1,10 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Screens.Select +{ + public class BeatmapDetailAreaDetailTabItem : BeatmapDetailAreaTabItem + { + public override string Name => "Details"; + } +} diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaLeaderboardTabItem.cs b/osu.Game/Screens/Select/BeatmapDetailAreaLeaderboardTabItem.cs new file mode 100644 index 0000000000..066944e9d2 --- /dev/null +++ b/osu.Game/Screens/Select/BeatmapDetailAreaLeaderboardTabItem.cs @@ -0,0 +1,22 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; + +namespace osu.Game.Screens.Select +{ + public class BeatmapDetailAreaLeaderboardTabItem : BeatmapDetailAreaTabItem + where TScope : Enum + { + public override string Name => Scope.ToString(); + + public override bool FilterableByMods => true; + + public readonly TScope Scope; + + public BeatmapDetailAreaLeaderboardTabItem(TScope scope) + { + Scope = scope; + } + } +} diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index 19ecdb6dbf..f4bf1ab059 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -18,14 +19,25 @@ namespace osu.Game.Screens.Select public class BeatmapDetailAreaTabControl : Container { public const float HEIGHT = 24; + + public Bindable Current + { + get => tabs.Current; + set => tabs.Current = value; + } + + public Action OnFilter; //passed the selected tab and if mods is checked + + public IReadOnlyList TabItems + { + get => tabs.Items; + set => tabs.Items = value; + } + private readonly OsuTabControlCheckbox modsCheckbox; - private readonly OsuTabControl tabs; + private readonly OsuTabControl tabs; private readonly Container tabsContainer; - public Action OnFilter; //passed the selected tab and if mods is checked - - private Bindable selectedTab; - public BeatmapDetailAreaTabControl() { Height = HEIGHT; @@ -43,7 +55,7 @@ namespace osu.Game.Screens.Select tabsContainer = new Container { RelativeSizeAxes = Axes.Both, - Child = tabs = new OsuTabControl + Child = tabs = new OsuTabControl { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -68,29 +80,22 @@ namespace osu.Game.Screens.Select private void load(OsuColour colour, OsuConfigManager config) { modsCheckbox.AccentColour = tabs.AccentColour = colour.YellowLight; - - selectedTab = config.GetBindable(OsuSetting.BeatmapDetailTab); - - tabs.Current.BindTo(selectedTab); - tabs.Current.TriggerChange(); } private void invokeOnFilter() { OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value); - modsCheckbox.FadeTo(tabs.Current.Value == BeatmapDetailTab.Details ? 0 : 1, 200, Easing.OutQuint); - - tabsContainer.Padding = new MarginPadding { Right = tabs.Current.Value == BeatmapDetailTab.Details ? 0 : 100 }; + if (tabs.Current.Value.FilterableByMods) + { + modsCheckbox.FadeTo(1, 200, Easing.OutQuint); + tabsContainer.Padding = new MarginPadding { Right = 100 }; + } + else + { + modsCheckbox.FadeTo(0, 200, Easing.OutQuint); + tabsContainer.Padding = new MarginPadding(); + } } } - - public enum BeatmapDetailTab - { - Details, - Local, - Country, - Global, - Friends - } } diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabItem.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabItem.cs new file mode 100644 index 0000000000..f28e5a7c22 --- /dev/null +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabItem.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; + +namespace osu.Game.Screens.Select +{ + public abstract class BeatmapDetailAreaTabItem : IEquatable + { + /// + /// The name of this tab, to be displayed in the tab control. + /// + public abstract string Name { get; } + + /// + /// Whether the contents of this tab can be filtered by the user's currently-selected mods. + /// + public virtual bool FilterableByMods => false; + + public override string ToString() => Name; + + public bool Equals(BeatmapDetailAreaTabItem other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return Name == other.Name; + } + + public override int GetHashCode() + { + return Name != null ? Name.GetHashCode() : 0; + } + } +} diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 6ba4157797..fd7a8a539c 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -34,6 +34,8 @@ namespace osu.Game.Screens.Select Padding = new MarginPadding { Horizontal = HORIZONTAL_OVERFLOW_PADDING }; } + protected override BeatmapDetailArea CreateBeatmapDetailArea() => new PlayBeatmapDetailArea(); // Todo: Temporary + protected override bool OnStart() { var item = new PlaylistItem diff --git a/osu.Game/Screens/Select/PlayBeatmapDetailArea.cs b/osu.Game/Screens/Select/PlayBeatmapDetailArea.cs new file mode 100644 index 0000000000..d719502a4f --- /dev/null +++ b/osu.Game/Screens/Select/PlayBeatmapDetailArea.cs @@ -0,0 +1,143 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Screens.Select.Leaderboards; + +namespace osu.Game.Screens.Select +{ + public class PlayBeatmapDetailArea : BeatmapDetailArea + { + public readonly BeatmapLeaderboard Leaderboard; + + public override WorkingBeatmap Beatmap + { + get => base.Beatmap; + set + { + base.Beatmap = value; + + Leaderboard.Beatmap = value is DummyWorkingBeatmap ? null : value?.BeatmapInfo; + } + } + + private Bindable selectedTab; + + public PlayBeatmapDetailArea() + { + Add(Leaderboard = new BeatmapLeaderboard { RelativeSizeAxes = Axes.Both }); + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + selectedTab = config.GetBindable(OsuSetting.BeatmapDetailTab); + selectedTab.BindValueChanged(tab => CurrentTab.Value = getTabItemFromTabType(tab.NewValue), true); + CurrentTab.BindValueChanged(tab => selectedTab.Value = getTabTypeFromTabItem(tab.NewValue)); + } + + public override void Refresh() + { + base.Refresh(); + + Leaderboard.RefreshScores(); + } + + protected override void OnTabChanged(BeatmapDetailAreaTabItem tab, bool selectedMods) + { + base.OnTabChanged(tab, selectedMods); + + Leaderboard.FilterMods = selectedMods; + + switch (tab) + { + case BeatmapDetailAreaLeaderboardTabItem leaderboard: + Leaderboard.Scope = leaderboard.Scope; + Leaderboard.Show(); + break; + + default: + Leaderboard.Hide(); + break; + } + } + + protected override BeatmapDetailAreaTabItem[] CreateTabItems() => base.CreateTabItems().Concat(new BeatmapDetailAreaTabItem[] + { + new BeatmapDetailAreaLeaderboardTabItem(BeatmapLeaderboardScope.Local), + new BeatmapDetailAreaLeaderboardTabItem(BeatmapLeaderboardScope.Country), + new BeatmapDetailAreaLeaderboardTabItem(BeatmapLeaderboardScope.Global), + new BeatmapDetailAreaLeaderboardTabItem(BeatmapLeaderboardScope.Friend), + }).ToArray(); + + private BeatmapDetailAreaTabItem getTabItemFromTabType(TabType type) + { + switch (type) + { + case TabType.Details: + return new BeatmapDetailAreaDetailTabItem(); + + case TabType.Local: + return new BeatmapDetailAreaLeaderboardTabItem(BeatmapLeaderboardScope.Local); + + case TabType.Country: + return new BeatmapDetailAreaLeaderboardTabItem(BeatmapLeaderboardScope.Country); + + case TabType.Global: + return new BeatmapDetailAreaLeaderboardTabItem(BeatmapLeaderboardScope.Global); + + case TabType.Friends: + return new BeatmapDetailAreaLeaderboardTabItem(BeatmapLeaderboardScope.Friend); + + default: + throw new ArgumentOutOfRangeException(nameof(type)); + } + } + + private TabType getTabTypeFromTabItem(BeatmapDetailAreaTabItem item) + { + switch (item) + { + case BeatmapDetailAreaDetailTabItem _: + return TabType.Details; + + case BeatmapDetailAreaLeaderboardTabItem leaderboardTab: + switch (leaderboardTab.Scope) + { + case BeatmapLeaderboardScope.Local: + return TabType.Local; + + case BeatmapLeaderboardScope.Country: + return TabType.Country; + + case BeatmapLeaderboardScope.Global: + return TabType.Global; + + case BeatmapLeaderboardScope.Friend: + return TabType.Friends; + + default: + throw new ArgumentOutOfRangeException(nameof(item)); + } + + default: + throw new ArgumentOutOfRangeException(nameof(item)); + } + } + + public enum TabType + { + Details, + Local, + Country, + Global, + Friends + } + } +} diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index f1dd125362..e744fd6a7b 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -29,8 +29,12 @@ namespace osu.Game.Screens.Select ValidForResume = false; Edit(); }, Key.Number4); + + ((PlayBeatmapDetailArea)BeatmapDetails).Leaderboard.ScoreSelected += score => this.Push(new SoloResults(score)); } + protected override BeatmapDetailArea CreateBeatmapDetailArea() => new PlayBeatmapDetailArea(); + public override void OnResuming(IScreen last) { base.OnResuming(last); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 0da260d752..67626d1e4f 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -23,7 +23,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Edit; using osu.Game.Screens.Menu; -using osu.Game.Screens.Play; using osu.Game.Screens.Select.Options; using osu.Game.Skinning; using osuTK; @@ -207,11 +206,11 @@ namespace osu.Game.Screens.Select Left = left_area_padding, Right = left_area_padding * 2, }, - Child = BeatmapDetails = new BeatmapDetailArea + Child = BeatmapDetails = CreateBeatmapDetailArea().With(d => { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = 10, Right = 5 }, - }, + d.RelativeSizeAxes = Axes.Both; + d.Padding = new MarginPadding { Top = 10, Right = 5 }; + }) }, } }, @@ -262,8 +261,6 @@ namespace osu.Game.Screens.Select }); } - BeatmapDetails.Leaderboard.ScoreSelected += score => this.Push(new SoloResults(score)); - if (Footer != null) { Footer.AddButton(new FooterButtonMods { Current = Mods }, ModSelect); @@ -319,6 +316,11 @@ namespace osu.Game.Screens.Select return dependencies; } + /// + /// Creates the beatmap details to be displayed underneath the wedge. + /// + protected abstract BeatmapDetailArea CreateBeatmapDetailArea(); + public void Edit(BeatmapInfo beatmap = null) { if (!AllowEditing) @@ -533,7 +535,7 @@ namespace osu.Game.Screens.Select Carousel.AllowSelection = true; - BeatmapDetails.Leaderboard.RefreshScores(); + BeatmapDetails.Refresh(); Beatmap.Value.Track.Looping = true; music?.ResetTrackAdjustments(); @@ -716,7 +718,7 @@ namespace osu.Game.Screens.Select dialogOverlay?.Push(new BeatmapClearScoresDialog(beatmap, () => // schedule done here rather than inside the dialog as the dialog may fade out and never callback. - Schedule(() => BeatmapDetails.Leaderboard.RefreshScores()))); + Schedule(() => BeatmapDetails.Refresh()))); } public virtual bool OnPressed(GlobalAction action) From b2fbeab7732437b8671c512fe69eabeb6deefb47 Mon Sep 17 00:00:00 2001 From: Maximilian Junges Date: Thu, 13 Feb 2020 14:07:14 +0100 Subject: [PATCH 024/216] simplify string formatting and fix color --- osu.Game/Graphics/DrawableDate.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index dcbea96071..8c520f4e10 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -126,10 +126,8 @@ namespace osu.Game.Graphics [BackgroundDependencyLoader] private void load(OsuColour colours) { - // Temporary colour since it's currently impossible to change it without bugs (see https://github.com/ppy/osu-framework/issues/3231) - // If above is fixed, this should use OverlayColourProvider - background.Colour = colours.Gray1; - timeText.Colour = colours.GreyCyanLighter; + background.Colour = colours.GreySeafoamDarker; + timeText.Colour = colours.BlueLighter; } protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); @@ -140,8 +138,8 @@ namespace osu.Game.Graphics if (!(content is DateTimeOffset date)) return false; - dateText.Text = string.Format($"{date:d MMMM yyyy}") + " "; - timeText.Text = string.Format($"{date:hh:mm:ss \"UTC\"z}"); + dateText.Text = $"{date:d MMMM yyyy} "; + timeText.Text = $"{date:hh:mm:ss \"UTC\"z}"; return true; } From e67e4f708ea996e594992321a0e01cf037a967ed Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 13 Feb 2020 19:01:26 +0300 Subject: [PATCH 025/216] Adjust country name design --- .../Rankings/Tables/CountriesTable.cs | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index a0e4f694bd..ed8e956e5e 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -8,6 +8,7 @@ using osu.Game.Users; using osu.Game.Graphics.Sprites; using osu.Game.Graphics; using System.Collections.Generic; +using osu.Framework.Allocation; namespace osu.Game.Overlays.Rankings.Tables { @@ -30,11 +31,7 @@ namespace osu.Game.Overlays.Rankings.Tables protected override Country GetCountry(CountryStatistics item) => item.Country; - protected override Drawable CreateFlagContent(CountryStatistics item) => new OsuSpriteText - { - Font = OsuFont.GetFont(size: TEXT_SIZE), - Text = $@"{item.Country.FullName}", - }; + protected override Drawable CreateFlagContent(CountryStatistics item) => new CountryName(item.Country); protected override Drawable[] CreateAdditionalContent(CountryStatistics item) => new Drawable[] { @@ -63,5 +60,20 @@ namespace osu.Game.Overlays.Rankings.Tables Text = $@"{item.Performance / Math.Max(item.ActiveUsers, 1):N0}", } }; + + private class CountryName : OsuSpriteText + { + public CountryName(Country country) + { + Font = OsuFont.GetFont(size: 12, italics: true); + Text = $@"{country.FullName}"; + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + Colour = colourProvider.Light2; + } + } } } From 791bf6bc0197118f44654f754f9a407f4bda5f6b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 13 Feb 2020 19:03:07 +0300 Subject: [PATCH 026/216] Make username text italic --- osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs index 0e77d7d764..cad7364103 100644 --- a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Rankings.Tables protected sealed override Drawable CreateFlagContent(UserStatistics item) { - var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: TEXT_SIZE)) { AutoSizeAxes = Axes.Both }; + var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: TEXT_SIZE, italics: true)) { AutoSizeAxes = Axes.Both }; username.AddUserLink(item.User); return username; } From dac0148c94076026b579a8bc31fbba93bdd134c3 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Thu, 13 Feb 2020 20:08:14 +0100 Subject: [PATCH 027/216] Apply review suggestions. --- .../Online/TestSceneOnlineViewContainer.cs | 2 +- osu.Game/Online/OnlineViewContainer.cs | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index 2b9609f6e0..9dac28d347 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Online { public new LoadingAnimation LoadingAnimation => base.LoadingAnimation; - public CompositeDrawable ViewTarget => base.Content.Parent; + public CompositeDrawable ViewTarget => base.Content; public TestOnlineViewContainer() : base(@"Please sign in to view dummy test content") diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index c512ca531a..4b59f6ae80 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -21,8 +21,8 @@ namespace osu.Game.Online protected const double TRANSFORM_TIME = 300.0; - private readonly Container viewTarget; - protected override Container Content { get; } + private Container viewContent; + protected override Container Content => viewContent; [Resolved] protected IAPIProvider API { get; private set; } @@ -31,13 +31,9 @@ namespace osu.Game.Online { InternalChildren = new Drawable[] { - viewTarget = new Container + viewContent = new Container { RelativeSizeAxes = Axes.Both, - Child = Content = new Container - { - RelativeSizeAxes = Axes.Both, - } }, placeholder = new LoginPlaceholder(placeholderMessage), LoadingAnimation = new LoadingAnimation @@ -52,21 +48,21 @@ namespace osu.Game.Online switch (state) { case APIState.Offline: - PopContentOut(viewTarget); + PopContentOut(viewContent); placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 3 * TRANSFORM_TIME, Easing.OutQuint); placeholder.FadeInFromZero(2 * TRANSFORM_TIME, Easing.OutQuint); LoadingAnimation.Hide(); break; case APIState.Online: - PopContentIn(viewTarget); + PopContentIn(viewContent); placeholder.FadeOut(TRANSFORM_TIME / 2, Easing.OutQuint); LoadingAnimation.Hide(); break; case APIState.Failing: case APIState.Connecting: - PopContentOut(viewTarget); + PopContentOut(viewContent); LoadingAnimation.Show(); placeholder.FadeOut(TRANSFORM_TIME / 2, Easing.OutQuint); break; From 049b0d93d13530c090612a20a27124ee79fcaf38 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Thu, 13 Feb 2020 21:40:08 +0100 Subject: [PATCH 028/216] Add back default content fade transitions --- .../Visual/Online/TestSceneOnlineViewContainer.cs | 4 ---- osu.Game/Online/OnlineViewContainer.cs | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index 9dac28d347..39b9fd71d0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -54,10 +54,6 @@ namespace osu.Game.Tests.Visual.Online } }; } - - protected override void PopContentOut(Drawable content) => content.Hide(); - - protected override void PopContentIn(Drawable content) => content.Show(); } [Test] diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 4b59f6ae80..2a9aa60e2d 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -21,7 +21,7 @@ namespace osu.Game.Online protected const double TRANSFORM_TIME = 300.0; - private Container viewContent; + private readonly Container viewContent; protected override Container Content => viewContent; [Resolved] @@ -69,9 +69,9 @@ namespace osu.Game.Online } } - protected abstract void PopContentOut(Drawable content); + protected virtual void PopContentOut(Drawable content) => content.FadeOut(TRANSFORM_TIME / 2, Easing.OutQuint); - protected abstract void PopContentIn(Drawable content); + protected virtual void PopContentIn(Drawable content) => content.FadeIn(TRANSFORM_TIME, Easing.OutQuint); protected override void LoadComplete() { From c68c347503df8514ca0337ec01f9716d643b7da7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 14 Feb 2020 00:40:52 +0300 Subject: [PATCH 029/216] Remove unwanted property interpolation --- osu.Game/Overlays/Rankings/Tables/CountriesTable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index ed8e956e5e..997438ac07 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -66,7 +66,7 @@ namespace osu.Game.Overlays.Rankings.Tables public CountryName(Country country) { Font = OsuFont.GetFont(size: 12, italics: true); - Text = $@"{country.FullName}"; + Text = country.FullName ?? string.Empty; } [BackgroundDependencyLoader] From 50899ddccba2e8dfc89d0282ee5a547728c53f3e Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Fri, 14 Feb 2020 03:19:25 +0100 Subject: [PATCH 030/216] Use Span for OsuColour.FromHex --- osu.Game/Graphics/OsuColour.cs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index c8298543a1..59dd823266 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Globalization; using osu.Game.Beatmaps; using osuTK.Graphics; @@ -14,41 +15,40 @@ namespace osu.Game.Graphics public static Color4 FromHex(string hex) { - if (hex[0] == '#') - hex = hex.Substring(1); + var hexSpan = hex[0] == '#' ? hex.AsSpan().Slice(1) : hex.AsSpan(); - switch (hex.Length) + switch (hexSpan.Length) { default: throw new ArgumentException(@"Invalid hex string length!"); case 3: return new Color4( - (byte)(Convert.ToByte(hex.Substring(0, 1), 16) * 17), - (byte)(Convert.ToByte(hex.Substring(1, 1), 16) * 17), - (byte)(Convert.ToByte(hex.Substring(2, 1), 16) * 17), + (byte)(byte.Parse(hexSpan.Slice(0, 1), NumberStyles.HexNumber) * 17), + (byte)(byte.Parse(hexSpan.Slice(1, 1), NumberStyles.HexNumber) * 17), + (byte)(byte.Parse(hexSpan.Slice(2, 1), NumberStyles.HexNumber) * 17), 255); case 6: return new Color4( - Convert.ToByte(hex.Substring(0, 2), 16), - Convert.ToByte(hex.Substring(2, 2), 16), - Convert.ToByte(hex.Substring(4, 2), 16), + byte.Parse(hexSpan.Slice(0, 2), NumberStyles.HexNumber), + byte.Parse(hexSpan.Slice(2, 2), NumberStyles.HexNumber), + byte.Parse(hexSpan.Slice(4, 2), NumberStyles.HexNumber), 255); case 4: return new Color4( - (byte)(Convert.ToByte(hex.Substring(0, 1), 16) * 17), - (byte)(Convert.ToByte(hex.Substring(1, 1), 16) * 17), - (byte)(Convert.ToByte(hex.Substring(2, 1), 16) * 17), - (byte)(Convert.ToByte(hex.Substring(3, 1), 16) * 17)); + (byte)(byte.Parse(hexSpan.Slice(0, 1), NumberStyles.HexNumber) * 17), + (byte)(byte.Parse(hexSpan.Slice(1, 1), NumberStyles.HexNumber) * 17), + (byte)(byte.Parse(hexSpan.Slice(0, 1), NumberStyles.HexNumber) * 17), + (byte)(byte.Parse(hexSpan.Slice(0, 1), NumberStyles.HexNumber) * 17)); case 8: return new Color4( - Convert.ToByte(hex.Substring(0, 2), 16), - Convert.ToByte(hex.Substring(2, 2), 16), - Convert.ToByte(hex.Substring(4, 2), 16), - Convert.ToByte(hex.Substring(6, 2), 16)); + byte.Parse(hexSpan.Slice(0, 2), NumberStyles.HexNumber), + byte.Parse(hexSpan.Slice(2, 2), NumberStyles.HexNumber), + byte.Parse(hexSpan.Slice(4, 2), NumberStyles.HexNumber), + byte.Parse(hexSpan.Slice(6, 2), NumberStyles.HexNumber)); } } From 884a5fbad44f1eb58731de2176d7cf67428dd521 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 12:30:11 +0900 Subject: [PATCH 031/216] Fix osu! gameplay cursor not adjusting to mod/convert circle size changes --- .../TestSceneGameplayCursor.cs | 46 +++++++++++++++++-- .../UI/Cursor/OsuCursorContainer.cs | 44 +++++++++++++----- osu.Game/Screens/Play/GameplayBeatmap.cs | 42 +++++++++++++++++ osu.Game/Screens/Play/Player.cs | 11 +++++ 4 files changed, 128 insertions(+), 15 deletions(-) create mode 100644 osu.Game/Screens/Play/GameplayBeatmap.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs index aa170eae1e..90f1cdb2ea 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs @@ -7,7 +7,9 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Testing.Input; +using osu.Game.Configuration; using osu.Game.Rulesets.Osu.UI.Cursor; +using osu.Game.Screens.Play; using osuTK; namespace osu.Game.Rulesets.Osu.Tests @@ -21,12 +23,50 @@ namespace osu.Game.Rulesets.Osu.Tests typeof(CursorTrail) }; - [BackgroundDependencyLoader] - private void load() + [Cached] + private GameplayBeatmap gameplayBeatmap; + + private ClickingCursorContainer lastContainer; + + [Resolved] + private OsuConfigManager config { get; set; } + + public TestSceneGameplayCursor() + { + gameplayBeatmap = new GameplayBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)); + } + + [TestCase(1, 1)] + [TestCase(5, 1)] + [TestCase(10, 1)] + [TestCase(1, 1.5f)] + [TestCase(5, 1.5f)] + [TestCase(10, 1.5f)] + public void TestSizing(int circleSize, float userScale) + { + AddStep($"set user scale to {userScale}", () => config.Set(OsuSetting.GameplayCursorSize, userScale)); + AddStep($"adjust cs to {circleSize}", () => gameplayBeatmap.BeatmapInfo.BaseDifficulty.CircleSize = circleSize); + AddStep("turn on autosizing", () => config.Set(OsuSetting.AutoCursorSize, true)); + + AddStep("load content", loadContent); + + AddUntilStep("cursor size correct", () => lastContainer.ActiveCursor.Scale.X == OsuCursorContainer.GetScaleForCircleSize(circleSize) * userScale); + + AddStep("set user scale to 1", () => config.Set(OsuSetting.GameplayCursorSize, 1f)); + AddUntilStep("cursor size correct", () => lastContainer.ActiveCursor.Scale.X == OsuCursorContainer.GetScaleForCircleSize(circleSize)); + + AddStep("turn off autosizing", () => config.Set(OsuSetting.AutoCursorSize, false)); + AddUntilStep("cursor size correct", () => lastContainer.ActiveCursor.Scale.X == 1); + + AddStep($"set user scale to {userScale}", () => config.Set(OsuSetting.GameplayCursorSize, userScale)); + AddUntilStep("cursor size correct", () => lastContainer.ActiveCursor.Scale.X == userScale); + } + + private void loadContent() { SetContents(() => new MovingCursorInputManager { - Child = new ClickingCursorContainer + Child = lastContainer = new ClickingCursorContainer { RelativeSizeAxes = Axes.Both, Masking = true, diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 79b5d1b7f8..7ebc26ebfb 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -12,6 +12,7 @@ using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Play; using osu.Game.Skinning; using osuTK; @@ -32,7 +33,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor public Bindable CursorScale; private Bindable userCursorScale; private Bindable autoCursorScale; - private readonly IBindable beatmap = new Bindable(); public OsuCursorContainer() { @@ -43,13 +43,21 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor }; } + [Resolved(canBeNull: true)] + private GameplayBeatmap beatmap { get; set; } + + [Resolved] + private OsuConfigManager config { get; set; } + [BackgroundDependencyLoader(true)] - private void load(OsuConfigManager config, OsuRulesetConfigManager rulesetConfig, IBindable beatmap) + private void load(OsuConfigManager config, OsuRulesetConfigManager rulesetConfig) { rulesetConfig?.BindWith(OsuRulesetSetting.ShowCursorTrail, showTrail); + } - this.beatmap.BindTo(beatmap); - this.beatmap.ValueChanged += _ => calculateScale(); + protected override void LoadComplete() + { + showTrail.BindValueChanged(v => cursorTrail.FadeTo(v.NewValue ? 1 : 0, 200), true); userCursorScale = config.GetBindable(OsuSetting.GameplayCursorSize); userCursorScale.ValueChanged += _ => calculateScale(); @@ -58,29 +66,41 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor autoCursorScale.ValueChanged += _ => calculateScale(); CursorScale = new BindableFloat(); - CursorScale.ValueChanged += e => ActiveCursor.Scale = cursorTrail.Scale = new Vector2(e.NewValue); + CursorScale.ValueChanged += e => + { + var newScale = new Vector2(e.NewValue); + + ActiveCursor.Scale = newScale; + cursorTrail.Scale = newScale; + }; calculateScale(); + + base.LoadComplete(); } + /// + /// Get the scale applicable to the ActiveCursor based on a beatmap's circle size. + /// + public static float GetScaleForCircleSize(float circleSize) => + 1f - 0.7f * (1f + circleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY; + private void calculateScale() { float scale = userCursorScale.Value; - if (autoCursorScale.Value && beatmap.Value != null) + if (autoCursorScale.Value && beatmap != null) { // if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier. - scale *= 1f - 0.7f * (1f + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY; + scale *= GetScaleForCircleSize(beatmap.BeatmapInfo.BaseDifficulty.CircleSize); } CursorScale.Value = scale; - } - protected override void LoadComplete() - { - base.LoadComplete(); + var newScale = new Vector2(scale); - showTrail.BindValueChanged(v => cursorTrail.FadeTo(v.NewValue ? 1 : 0, 200), true); + ActiveCursor.ScaleTo(newScale, 400, Easing.OutQuint); + cursorTrail.Scale = newScale; } private int downCount; diff --git a/osu.Game/Screens/Play/GameplayBeatmap.cs b/osu.Game/Screens/Play/GameplayBeatmap.cs new file mode 100644 index 0000000000..d7f939a883 --- /dev/null +++ b/osu.Game/Screens/Play/GameplayBeatmap.cs @@ -0,0 +1,42 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Beatmaps.Timing; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Screens.Play +{ + public class GameplayBeatmap : Component, IBeatmap + { + public readonly IBeatmap PlayableBeatmap; + + public GameplayBeatmap(IBeatmap playableBeatmap) + { + PlayableBeatmap = playableBeatmap; + } + + public BeatmapInfo BeatmapInfo + { + get => PlayableBeatmap.BeatmapInfo; + set => PlayableBeatmap.BeatmapInfo = value; + } + + public BeatmapMetadata Metadata => PlayableBeatmap.Metadata; + + public ControlPointInfo ControlPointInfo => PlayableBeatmap.ControlPointInfo; + + public List Breaks => PlayableBeatmap.Breaks; + + public double TotalBreakTime => PlayableBeatmap.TotalBreakTime; + + public IReadOnlyList HitObjects => PlayableBeatmap.HitObjects; + + public IEnumerable GetStatistics() => PlayableBeatmap.GetStatistics(); + + public IBeatmap Clone() => PlayableBeatmap.Clone(); + } +} diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index aecd35f7dc..9bfdcd79fe 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -110,6 +110,13 @@ namespace osu.Game.Screens.Play this.showResults = showResults; } + private GameplayBeatmap gameplayBeatmap; + + private DependencyContainer dependencies; + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + [BackgroundDependencyLoader] private void load(AudioManager audio, IAPIProvider api, OsuConfigManager config) { @@ -143,6 +150,10 @@ namespace osu.Game.Screens.Play InternalChild = GameplayClockContainer = new GameplayClockContainer(Beatmap.Value, Mods.Value, DrawableRuleset.GameplayStartTime); + AddInternal(gameplayBeatmap = new GameplayBeatmap(playableBeatmap)); + + dependencies.CacheAs(gameplayBeatmap); + addUnderlayComponents(GameplayClockContainer); addGameplayComponents(GameplayClockContainer, Beatmap.Value); addOverlayComponents(GameplayClockContainer, Beatmap.Value); From 0e439e3a7025a2cfded813fda28f90c8d9a79a88 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 14:41:55 +0900 Subject: [PATCH 032/216] Fix missing dependency in ZoomableScrollContainer test --- .../Compose/Components/Timeline/ZoomableScrollContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index baaad63e57..227eecf9c7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private float currentZoom = 1; - [Resolved] + [Resolved(canBeNull: true)] private IFrameBasedClock editorClock { get; set; } public ZoomableScrollContainer() @@ -112,7 +112,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { // can't handle scroll correctly while playing. // the editor will handle this case for us. - if (editorClock.IsRunning) + if (editorClock?.IsRunning == true) return false; // for now, we don't support zoom when using a precision scroll device. this needs gesture support. From 3a0b2508d42b1d09da1aa30bbc356d88b5b4f76d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 15:01:30 +0900 Subject: [PATCH 033/216] Fix possible nullrefs --- osu.Game/Overlays/Direct/PanelDownloadButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Direct/PanelDownloadButton.cs b/osu.Game/Overlays/Direct/PanelDownloadButton.cs index ed44f1e960..1b3657f010 100644 --- a/osu.Game/Overlays/Direct/PanelDownloadButton.cs +++ b/osu.Game/Overlays/Direct/PanelDownloadButton.cs @@ -45,7 +45,7 @@ namespace osu.Game.Overlays.Direct [BackgroundDependencyLoader(true)] private void load(OsuGame game, BeatmapManager beatmaps) { - if (BeatmapSet.Value.OnlineInfo.Availability?.DownloadDisabled ?? false) + if (BeatmapSet.Value?.OnlineInfo?.Availability?.DownloadDisabled ?? false) { button.Enabled.Value = false; button.TooltipText = "this beatmap is currently not available for download."; @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Direct break; case DownloadState.LocallyAvailable: - game.PresentBeatmap(BeatmapSet.Value); + game?.PresentBeatmap(BeatmapSet.Value); break; default: From eb14dbcd77ffc141ff717f4307df40028027d451 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 15:01:45 +0900 Subject: [PATCH 034/216] Initial implementation of rearrangeable playlist --- .../TestSceneDrawableRoomPlaylist.cs | 86 +++++ .../Screens/Multi/DrawableRoomPlaylist.cs | 81 ++++ .../Screens/Multi/DrawableRoomPlaylistItem.cs | 347 ++++++++++++++++++ 3 files changed, 514 insertions(+) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs create mode 100644 osu.Game/Screens/Multi/DrawableRoomPlaylist.cs create mode 100644 osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs new file mode 100644 index 0000000000..b906ce82e9 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -0,0 +1,86 @@ +// Copyright (c) ppy Pty Ltd . 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.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Utils; +using osu.Game.Beatmaps; +using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Screens.Multi; +using osuTK; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneDrawableRoomPlaylist : OsuTestScene + { + [Resolved] + private BeatmapManager beatmapManager { get; set; } + + [Resolved] + private RulesetStore rulesetStore { get; set; } + + private DrawableRoomPlaylist playlist; + + [Test] + public void TestItemsCanNotBeRemovedOrSelectedFromNonEditableAndNonSelectablePlaylist() + { + createPlaylist(false, false); + } + + [Test] + public void TestItemsCanBeRemovedFromEditablePlaylist() + { + createPlaylist(true, false); + } + + [Test] + public void TestItemsCanBeSelectedInSelectablePlaylist() + { + createPlaylist(false, true); + } + + [Test] + public void TestItemsCanBeSelectedAndRemovedFromEditableAndSelectablePlaylist() + { + createPlaylist(true, true); + } + + private void createPlaylist(bool allowEdit, bool allowSelection) => AddStep("create playlist", () => + { + Child = playlist = new DrawableRoomPlaylist(allowEdit, allowSelection) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(500, 300) + }; + + var beatmapSets = beatmapManager.GetAllUsableBeatmapSets(); + var rulesets = rulesetStore.AvailableRulesets.ToList(); + + for (int i = 0; i < 20; i++) + { + var set = beatmapSets[RNG.Next(0, beatmapSets.Count)]; + var beatmap = set.Beatmaps[RNG.Next(0, set.Beatmaps.Count)]; + + beatmap.BeatmapSet = set; + beatmap.Metadata = set.Metadata; + + playlist.Items.Add(new PlaylistItem + { + Beatmap = { Value = beatmap }, + Ruleset = { Value = rulesets[RNG.Next(0, rulesets.Count)] }, + RequiredMods = + { + new OsuModHardRock(), + new OsuModDoubleTime(), + new OsuModAutoplay() + } + }); + } + }); + } +} diff --git a/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs b/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs new file mode 100644 index 0000000000..b42a8575ec --- /dev/null +++ b/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs @@ -0,0 +1,81 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Containers; +using osu.Game.Online.Multiplayer; +using osuTK; + +namespace osu.Game.Screens.Multi +{ + public class DrawableRoomPlaylist : RearrangeableListContainer + { + public readonly Bindable SelectedItem = new Bindable(); + + private readonly bool allowEdit; + private readonly bool allowSelection; + + public DrawableRoomPlaylist(bool allowEdit, bool allowSelection) + { + this.allowEdit = allowEdit; + this.allowSelection = allowSelection; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + SelectedItem.BindValueChanged(item => + { + if (item.OldValue != null && ItemMap.TryGetValue(item.OldValue, out var oldItem)) + ((DrawableRoomPlaylistItem)oldItem).Deselect(); + + if (item.NewValue != null && ItemMap.TryGetValue(item.NewValue, out var newItem)) + ((DrawableRoomPlaylistItem)newItem).Select(); + }, true); + + Items.ItemsRemoved += items => + { + if (items.Any(i => i == SelectedItem.Value)) + SelectedItem.Value = null; + }; + } + + protected override ScrollContainer CreateScrollContainer() => new OsuScrollContainer + { + ScrollbarVisible = false + }; + + protected override FillFlowContainer> CreateListFillFlowContainer() => new FillFlowContainer> + { + LayoutDuration = 200, + LayoutEasing = Easing.OutQuint, + Spacing = new Vector2(0, 2) + }; + + protected override RearrangeableListItem CreateDrawable(PlaylistItem item) => new DrawableRoomPlaylistItem(item, allowEdit, allowSelection) + { + RequestSelection = requestSelection, + RequestDeletion = requestDeletion + }; + + private void requestSelection(PlaylistItem item) => SelectedItem.Value = item; + + private void requestDeletion(PlaylistItem item) + { + if (SelectedItem.Value == item) + { + if (Items.Count == 1) + SelectedItem.Value = null; + else + SelectedItem.Value = Items.GetNext(item) ?? Items[^2]; + } + + Items.Remove(item); + } + } +} diff --git a/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs new file mode 100644 index 0000000000..d2788a5c4b --- /dev/null +++ b/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs @@ -0,0 +1,347 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Framework.Threading; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Chat; +using osu.Game.Online.Multiplayer; +using osu.Game.Overlays.Direct; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Play.HUD; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Multi +{ + public class DrawableRoomPlaylistItem : RearrangeableListItem + { + public Action RequestSelection; + public Action RequestDeletion; + + private Container maskingContainer; + private Container difficultyIconContainer; + private LinkFlowContainer beatmapText; + private LinkFlowContainer authorText; + private ItemHandle handle; + private ModDisplay modDisplay; + + private readonly Bindable beatmap = new Bindable(); + private readonly Bindable ruleset = new Bindable(); + private readonly BindableList requiredMods = new BindableList(); + + private readonly PlaylistItem item; + private readonly bool allowEdit; + private readonly bool allowSelection; + + public DrawableRoomPlaylistItem(PlaylistItem item, bool allowEdit, bool allowSelection) + : base(item) + { + this.item = item; + this.allowEdit = allowEdit; + this.allowSelection = allowSelection; + + RelativeSizeAxes = Axes.X; + Height = 50; + + beatmap.BindTo(item.Beatmap); + ruleset.BindTo(item.Ruleset); + requiredMods.BindTo(item.RequiredMods); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + InternalChild = new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Alpha = allowEdit ? 1 : 0, + Child = handle = new ItemHandle + { + Size = new Vector2(12), + AlwaysPresent = true, + Alpha = 0, + }, + }, + maskingContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 10, + BorderColour = colours.Yellow, + Children = new Drawable[] + { + new Box // A transparent box that forces the border to be drawn if the panel background is opaque + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + }, + new PanelBackground + { + RelativeSizeAxes = Axes.Both, + Beatmap = { BindTarget = beatmap } + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = 8 }, + Spacing = new Vector2(8, 0), + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + difficultyIconContainer = new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + beatmapText = new LinkFlowContainer { AutoSizeAxes = Axes.Both }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + authorText = new LinkFlowContainer { AutoSizeAxes = Axes.Both }, + modDisplay = new ModDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Scale = new Vector2(0.4f), + DisplayUnrankedText = false, + ExpansionMode = ExpansionMode.AlwaysExpanded + } + } + } + } + } + } + }, + new Container + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + X = -18, + Children = new Drawable[] + { + new IconButton + { + Icon = FontAwesome.Solid.MinusSquare, + Alpha = allowEdit ? 1 : 0, + Action = () => RequestDeletion?.Invoke(Model), + }, + new PanelDownloadButton(item.Beatmap.Value.BeatmapSet) + { + Size = new Vector2(50, 30), + Alpha = allowEdit ? 0 : 1 + } + } + } + } + } + }, + }, + ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + beatmap.BindValueChanged(_ => scheduleRefresh()); + ruleset.BindValueChanged(_ => scheduleRefresh()); + + requiredMods.ItemsAdded += _ => scheduleRefresh(); + requiredMods.ItemsRemoved += _ => scheduleRefresh(); + + refresh(); + } + + private ScheduledDelegate scheduledRefresh; + + private void scheduleRefresh() + { + scheduledRefresh?.Cancel(); + scheduledRefresh = Schedule(refresh); + } + + private void refresh() + { + difficultyIconContainer.Child = new DifficultyIcon(beatmap.Value, ruleset.Value) { Size = new Vector2(32) }; + + beatmapText.Clear(); + beatmapText.AddLink(item.Beatmap.ToString(), LinkAction.OpenBeatmap, item.Beatmap.Value.OnlineBeatmapID.ToString()); + + authorText.Clear(); + + if (item.Beatmap?.Value?.Metadata?.Author != null) + { + authorText.AddText("mapped by "); + authorText.AddUserLink(item.Beatmap.Value?.Metadata.Author); + } + + modDisplay.Current.Value = requiredMods.ToArray(); + } + + protected override bool IsDraggableAt(Vector2 screenSpacePos) => handle.HandlingDrag; + + protected override bool OnHover(HoverEvent e) + { + handle.UpdateHoverState(true); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) => handle.UpdateHoverState(false); + + protected override bool OnClick(ClickEvent e) + { + if (allowSelection) + RequestSelection?.Invoke(Model); + return true; + } + + public void Select() => maskingContainer.BorderThickness = 5; + + public void Deselect() => maskingContainer.BorderThickness = 0; + + // For now, this is the same implementation as in PanelBackground, but supports a beatmap info rather than a working beatmap + private class PanelBackground : Container // todo: should be a buffered container (https://github.com/ppy/osu-framework/issues/3222) + { + public readonly Bindable Beatmap = new Bindable(); + + public PanelBackground() + { + InternalChildren = new Drawable[] + { + new UpdateableBeatmapBackgroundSprite + { + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fill, + Beatmap = { BindTarget = Beatmap } + }, + new Container + { + Depth = -1, + RelativeSizeAxes = Axes.Both, + // This makes the gradient not be perfectly horizontal, but diagonal at a ~40° angle + Shear = new Vector2(0.8f, 0), + Alpha = 0.5f, + Children = new[] + { + // The left half with no gradient applied + new Box + { + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + Colour = Color4.Black, + Width = 0.4f, + }, + // Piecewise-linear gradient with 3 segments to make it appear smoother + new Box + { + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(Color4.Black, new Color4(0f, 0f, 0f, 0.9f)), + Width = 0.05f, + X = 0.4f, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.9f), new Color4(0f, 0f, 0f, 0.1f)), + Width = 0.2f, + X = 0.45f, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.1f), new Color4(0, 0, 0, 0)), + Width = 0.05f, + X = 0.65f, + }, + } + } + }; + } + } + + private class ItemHandle : SpriteIcon + { + public bool HandlingDrag { get; private set; } + private bool isHovering; + + public ItemHandle() + { + Margin = new MarginPadding { Horizontal = 5 }; + + Icon = FontAwesome.Solid.Bars; + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + base.OnMouseDown(e); + + HandlingDrag = true; + UpdateHoverState(isHovering); + + return false; + } + + protected override void OnMouseUp(MouseUpEvent e) + { + base.OnMouseUp(e); + + HandlingDrag = false; + UpdateHoverState(isHovering); + } + + public void UpdateHoverState(bool hovering) + { + isHovering = hovering; + + if (isHovering || HandlingDrag) + this.FadeIn(100); + else + this.FadeOut(100); + } + } + } +} From aa7efe6141e0ca80c3a908e3902b1dba5c95d4e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 15:26:55 +0900 Subject: [PATCH 035/216] Fix tests potentially failing due to timing issues --- .../Online/TestSceneOnlineViewContainer.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index 39b9fd71d0..d656600a18 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -61,8 +61,8 @@ namespace osu.Game.Tests.Visual.Online { AddStep("set status to online", () => ((DummyAPIAccess)API).State = APIState.Online); - AddAssert("children are visible", () => onlineView.ViewTarget.IsPresent); - AddAssert("loading animation is not visible", () => !onlineView.LoadingAnimation.IsPresent); + AddUntilStep("children are visible", () => onlineView.ViewTarget.IsPresent); + AddUntilStep("loading animation is not visible", () => !onlineView.LoadingAnimation.IsPresent); } [Test] @@ -70,8 +70,8 @@ namespace osu.Game.Tests.Visual.Online { AddStep("set status to offline", () => ((DummyAPIAccess)API).State = APIState.Offline); - AddAssert("children are hidden", () => !onlineView.ViewTarget.IsPresent); - AddAssert("loading animation is not visible", () => !onlineView.LoadingAnimation.IsPresent); + AddUntilStep("children are not visible", () => !onlineView.ViewTarget.IsPresent); + AddUntilStep("loading animation is not visible", () => !onlineView.LoadingAnimation.IsPresent); } [Test] @@ -79,8 +79,8 @@ namespace osu.Game.Tests.Visual.Online { AddStep("set status to connecting", () => ((DummyAPIAccess)API).State = APIState.Connecting); - AddAssert("children are hidden", () => !onlineView.ViewTarget.IsPresent); - AddAssert("loading animation is visible", () => onlineView.LoadingAnimation.IsPresent); + AddUntilStep("children are not visible", () => !onlineView.ViewTarget.IsPresent); + AddUntilStep("loading animation is visible", () => onlineView.LoadingAnimation.IsPresent); } [Test] @@ -88,8 +88,8 @@ namespace osu.Game.Tests.Visual.Online { AddStep("set status to failing", () => ((DummyAPIAccess)API).State = APIState.Failing); - AddAssert("children are hidden", () => !onlineView.ViewTarget.IsPresent); - AddAssert("loading animation is visible", () => onlineView.LoadingAnimation.IsPresent); + AddUntilStep("children are not visible", () => !onlineView.ViewTarget.IsPresent); + AddUntilStep("loading animation is visible", () => onlineView.LoadingAnimation.IsPresent); } } } From c34f1f40eafd8e06f6a7009fc4661105e40664cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 15:27:09 +0900 Subject: [PATCH 036/216] Fix test text not being centered --- osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index d656600a18..2bd0d59632 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -6,6 +6,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online; @@ -38,6 +39,7 @@ namespace osu.Game.Tests.Visual.Online : base(@"Please sign in to view dummy test content") { RelativeSizeAxes = Axes.Both; + Children = new Drawable[] { new Box @@ -48,7 +50,7 @@ namespace osu.Game.Tests.Visual.Online new OsuSpriteText { Text = "dummy online content", - RelativeSizeAxes = Axes.Both, + Font = OsuFont.Default.With(size: 40), Anchor = Anchor.Centre, Origin = Anchor.Centre, } From b86b5e9adb3369f675346d0ef2b22429d87c7a61 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 15:27:39 +0900 Subject: [PATCH 037/216] Move nested class to bottom of file --- .../Online/TestSceneOnlineViewContainer.cs | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index 2bd0d59632..3c2735ca56 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -29,35 +29,6 @@ namespace osu.Game.Tests.Visual.Online }; } - private class TestOnlineViewContainer : OnlineViewContainer - { - public new LoadingAnimation LoadingAnimation => base.LoadingAnimation; - - public CompositeDrawable ViewTarget => base.Content; - - public TestOnlineViewContainer() - : base(@"Please sign in to view dummy test content") - { - RelativeSizeAxes = Axes.Both; - - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Blue.Opacity(0.8f), - }, - new OsuSpriteText - { - Text = "dummy online content", - Font = OsuFont.Default.With(size: 40), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } - }; - } - } - [Test] public void TestOnlineStateVisibility() { @@ -93,5 +64,34 @@ namespace osu.Game.Tests.Visual.Online AddUntilStep("children are not visible", () => !onlineView.ViewTarget.IsPresent); AddUntilStep("loading animation is visible", () => onlineView.LoadingAnimation.IsPresent); } + + private class TestOnlineViewContainer : OnlineViewContainer + { + public new LoadingAnimation LoadingAnimation => base.LoadingAnimation; + + public CompositeDrawable ViewTarget => base.Content; + + public TestOnlineViewContainer() + : base(@"Please sign in to view dummy test content") + { + RelativeSizeAxes = Axes.Both; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Blue.Opacity(0.8f), + }, + new OsuSpriteText + { + Text = "dummy online content", + Font = OsuFont.Default.With(size: 40), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; + } + } } } From 4d5abab2ee0b39704f0e5b91bf41e01e7b50f83b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 15:29:50 +0900 Subject: [PATCH 038/216] Remove unnecessary content private storage --- osu.Game/Online/OnlineViewContainer.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 2a9aa60e2d..0ffb342bfc 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -21,8 +21,7 @@ namespace osu.Game.Online protected const double TRANSFORM_TIME = 300.0; - private readonly Container viewContent; - protected override Container Content => viewContent; + protected override Container Content { get; } [Resolved] protected IAPIProvider API { get; private set; } @@ -31,7 +30,7 @@ namespace osu.Game.Online { InternalChildren = new Drawable[] { - viewContent = new Container + Content = new Container { RelativeSizeAxes = Axes.Both, }, @@ -48,21 +47,21 @@ namespace osu.Game.Online switch (state) { case APIState.Offline: - PopContentOut(viewContent); + PopContentOut(Content); placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 3 * TRANSFORM_TIME, Easing.OutQuint); placeholder.FadeInFromZero(2 * TRANSFORM_TIME, Easing.OutQuint); LoadingAnimation.Hide(); break; case APIState.Online: - PopContentIn(viewContent); + PopContentIn(Content); placeholder.FadeOut(TRANSFORM_TIME / 2, Easing.OutQuint); LoadingAnimation.Hide(); break; case APIState.Failing: case APIState.Connecting: - PopContentOut(viewContent); + PopContentOut(Content); LoadingAnimation.Show(); placeholder.FadeOut(TRANSFORM_TIME / 2, Easing.OutQuint); break; From 7e6c194d4a9c9f04712db293bc39f5f6baf201f5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 15:34:46 +0900 Subject: [PATCH 039/216] Add missing xmldoc --- osu.Game/Online/OnlineViewContainer.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 0ffb342bfc..50b4820d15 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -68,8 +68,14 @@ namespace osu.Game.Online } } + /// + /// Applies a transform to the online content to make it hidden. + /// protected virtual void PopContentOut(Drawable content) => content.FadeOut(TRANSFORM_TIME / 2, Easing.OutQuint); + /// + /// Applies a transform to the online content to make it visible. + /// protected virtual void PopContentIn(Drawable content) => content.FadeIn(TRANSFORM_TIME, Easing.OutQuint); protected override void LoadComplete() From 6f1cecd86f7fc4efa6e00c0da8e44972f332f880 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 15:35:39 +0900 Subject: [PATCH 040/216] Move LoadComplete up in method --- osu.Game/Online/OnlineViewContainer.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 50b4820d15..3b2243c97a 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -42,6 +42,12 @@ namespace osu.Game.Online }; } + protected override void LoadComplete() + { + API?.Register(this); + base.LoadComplete(); + } + public virtual void APIStateChanged(IAPIProvider api, APIState state) { switch (state) @@ -78,12 +84,6 @@ namespace osu.Game.Online /// protected virtual void PopContentIn(Drawable content) => content.FadeIn(TRANSFORM_TIME, Easing.OutQuint); - protected override void LoadComplete() - { - API?.Register(this); - base.LoadComplete(); - } - protected override void Dispose(bool isDisposing) { API?.Unregister(this); From edf9cfc8635580d7e40c188828a2533ec5b824ab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 15:36:06 +0900 Subject: [PATCH 041/216] API can't be null on load --- osu.Game/Online/OnlineViewContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 3b2243c97a..b16fbb7aed 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -44,7 +44,7 @@ namespace osu.Game.Online protected override void LoadComplete() { - API?.Register(this); + API.Register(this); base.LoadComplete(); } From eb75d26c8f5c3365fda1965401f4df77fb900078 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 15:36:16 +0900 Subject: [PATCH 042/216] Extract common rearrangeable list design --- .../OsuRearrangeableListContainer.cs | 26 +++ .../Containers/OsuRearrangeableListItem.cs | 149 ++++++++++++++++++ osu.Game/Overlays/Music/Playlist.cs | 12 +- osu.Game/Overlays/Music/PlaylistItem.cs | 121 ++------------ 4 files changed, 190 insertions(+), 118 deletions(-) create mode 100644 osu.Game/Graphics/Containers/OsuRearrangeableListContainer.cs create mode 100644 osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs diff --git a/osu.Game/Graphics/Containers/OsuRearrangeableListContainer.cs b/osu.Game/Graphics/Containers/OsuRearrangeableListContainer.cs new file mode 100644 index 0000000000..47aed1c500 --- /dev/null +++ b/osu.Game/Graphics/Containers/OsuRearrangeableListContainer.cs @@ -0,0 +1,26 @@ +// 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.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Graphics.Containers +{ + public abstract class OsuRearrangeableListContainer : RearrangeableListContainer + { + /// + /// Whether any item is currently being dragged. Used to hide other items' drag handles. + /// + private readonly BindableBool playlistDragActive = new BindableBool(); + + protected override ScrollContainer CreateScrollContainer() => new OsuScrollContainer(); + + protected sealed override RearrangeableListItem CreateDrawable(TModel item) => CreateOsuDrawable(item).With(d => + { + d.PlaylistDragActive.BindTo(playlistDragActive); + }); + + protected abstract OsuRearrangeableListItem CreateOsuDrawable(TModel item); + } +} diff --git a/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs b/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs new file mode 100644 index 0000000000..f75a3330e2 --- /dev/null +++ b/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs @@ -0,0 +1,149 @@ +// 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.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Graphics.Containers +{ + public abstract class OsuRearrangeableListItem : RearrangeableListItem + { + public const float FADE_DURATION = 100; + + /// + /// Whether any item is currently being dragged. Used to hide other items' drag handles. + /// + public readonly BindableBool PlaylistDragActive = new BindableBool(); + + private Color4 handleColour = Color4.White; + + protected Color4 HandleColour + { + get => handleColour; + set + { + if (handleColour == value) + return; + + handleColour = value; + + if (handle != null) + handle.Colour = value; + } + } + + private PlaylistItemHandle handle; + + protected OsuRearrangeableListItem(TModel item) + : base(item) + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = new GridContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Content = new[] + { + new[] + { + new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = 5 }, + Child = handle = new PlaylistItemHandle + { + Size = new Vector2(12), + Colour = HandleColour, + AlwaysPresent = true, + Alpha = 0 + } + }, + CreateContent() + } + }, + ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } + }; + } + + protected override bool OnDragStart(DragStartEvent e) + { + if (!base.OnDragStart(e)) + return false; + + PlaylistDragActive.Value = true; + return true; + } + + protected override void OnDragEnd(DragEndEvent e) + { + PlaylistDragActive.Value = false; + base.OnDragEnd(e); + } + + protected override bool IsDraggableAt(Vector2 screenSpacePos) => handle.HandlingDrag; + + protected override bool OnHover(HoverEvent e) + { + handle.UpdateHoverState(IsDragged || !PlaylistDragActive.Value); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) => handle.UpdateHoverState(false); + + protected abstract Drawable CreateContent(); + + private class PlaylistItemHandle : SpriteIcon + { + public bool HandlingDrag { get; private set; } + private bool isHovering; + + public PlaylistItemHandle() + { + Icon = FontAwesome.Solid.Bars; + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + base.OnMouseDown(e); + + HandlingDrag = true; + UpdateHoverState(isHovering); + + return false; + } + + protected override void OnMouseUp(MouseUpEvent e) + { + base.OnMouseUp(e); + + HandlingDrag = false; + UpdateHoverState(isHovering); + } + + public void UpdateHoverState(bool hovering) + { + isHovering = hovering; + + if (isHovering || HandlingDrag) + this.FadeIn(FADE_DURATION); + else + this.FadeOut(FADE_DURATION); + } + } + } +} diff --git a/osu.Game/Overlays/Music/Playlist.cs b/osu.Game/Overlays/Music/Playlist.cs index 1ba568443d..621a533dd6 100644 --- a/osu.Game/Overlays/Music/Playlist.cs +++ b/osu.Game/Overlays/Music/Playlist.cs @@ -12,17 +12,12 @@ using osuTK; namespace osu.Game.Overlays.Music { - public class Playlist : RearrangeableListContainer + public class Playlist : OsuRearrangeableListContainer { public Action RequestSelection; public readonly Bindable SelectedSet = new Bindable(); - /// - /// Whether any item is currently being dragged. Used to hide other items' drag handles. - /// - private readonly BindableBool playlistDragActive = new BindableBool(); - public new MarginPadding Padding { get => base.Padding; @@ -33,15 +28,12 @@ namespace osu.Game.Overlays.Music public BeatmapSetInfo FirstVisibleSet => Items.FirstOrDefault(i => ((PlaylistItem)ItemMap[i]).MatchingFilter); - protected override RearrangeableListItem CreateDrawable(BeatmapSetInfo item) => new PlaylistItem(item) + protected override OsuRearrangeableListItem CreateOsuDrawable(BeatmapSetInfo item) => new PlaylistItem(item) { SelectedSet = { BindTarget = SelectedSet }, - PlaylistDragActive = { BindTarget = playlistDragActive }, RequestSelection = set => RequestSelection?.Invoke(set) }; - protected override ScrollContainer CreateScrollContainer() => new OsuScrollContainer(); - protected override FillFlowContainer> CreateListFillFlowContainer() => new SearchContainer> { Spacing = new Vector2(0, 3), diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 0569261867..8cafbc694a 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -14,36 +14,27 @@ using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.Music { - public class PlaylistItem : RearrangeableListItem, IFilterable + public class PlaylistItem : OsuRearrangeableListItem, IFilterable { - private const float fade_duration = 100; - - public BindableBool PlaylistDragActive = new BindableBool(); - public readonly Bindable SelectedSet = new Bindable(); public Action RequestSelection; - private PlaylistItemHandle handle; private TextFlowContainer text; private IEnumerable titleSprites; private ILocalisedBindableString titleBind; private ILocalisedBindableString artistBind; - private Color4 hoverColour; + private Color4 selectedColour; private Color4 artistColour; public PlaylistItem(BeatmapSetInfo item) : base(item) { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - Padding = new MarginPadding { Left = 5 }; FilterTerms = item.Metadata.SearchableTerms; @@ -52,42 +43,12 @@ namespace osu.Game.Overlays.Music [BackgroundDependencyLoader] private void load(OsuColour colours, LocalisationManager localisation) { - hoverColour = colours.Yellow; + selectedColour = colours.Yellow; artistColour = colours.Gray9; - - InternalChild = new GridContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Content = new[] - { - new Drawable[] - { - handle = new PlaylistItemHandle - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Size = new Vector2(12), - Colour = colours.Gray5, - AlwaysPresent = true, - Alpha = 0 - }, - text = new OsuTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = 5 }, - }, - } - }, - ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, - RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } - }; + HandleColour = colours.Gray5; titleBind = localisation.GetLocalisedString(new LocalisedString((Model.Metadata.TitleUnicode, Model.Metadata.Title))); artistBind = localisation.GetLocalisedString(new LocalisedString((Model.Metadata.ArtistUnicode, Model.Metadata.Artist))); - - artistBind.BindValueChanged(_ => recreateText(), true); } protected override void LoadComplete() @@ -100,10 +61,18 @@ namespace osu.Game.Overlays.Music return; foreach (Drawable s in titleSprites) - s.FadeColour(set.NewValue == Model ? hoverColour : Color4.White, fade_duration); + s.FadeColour(set.NewValue == Model ? selectedColour : Color4.White, FADE_DURATION); }, true); + + artistBind.BindValueChanged(_ => recreateText(), true); } + protected override Drawable CreateContent() => text = new OsuTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }; + private void recreateText() { text.Clear(); @@ -125,31 +94,6 @@ namespace osu.Game.Overlays.Music return true; } - protected override bool OnDragStart(DragStartEvent e) - { - if (!base.OnDragStart(e)) - return false; - - PlaylistDragActive.Value = true; - return true; - } - - protected override void OnDragEnd(DragEndEvent e) - { - PlaylistDragActive.Value = false; - base.OnDragEnd(e); - } - - protected override bool IsDraggableAt(Vector2 screenSpacePos) => handle.HandlingDrag; - - protected override bool OnHover(HoverEvent e) - { - handle.UpdateHoverState(IsDragged || !PlaylistDragActive.Value); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) => handle.UpdateHoverState(false); - public IEnumerable FilterTerms { get; } private bool matching = true; @@ -168,44 +112,5 @@ namespace osu.Game.Overlays.Music } public bool FilteringActive { get; set; } - - private class PlaylistItemHandle : SpriteIcon - { - public bool HandlingDrag { get; private set; } - private bool isHovering; - - public PlaylistItemHandle() - { - Icon = FontAwesome.Solid.Bars; - } - - protected override bool OnMouseDown(MouseDownEvent e) - { - base.OnMouseDown(e); - - HandlingDrag = true; - UpdateHoverState(isHovering); - - return false; - } - - protected override void OnMouseUp(MouseUpEvent e) - { - base.OnMouseUp(e); - - HandlingDrag = false; - UpdateHoverState(isHovering); - } - - public void UpdateHoverState(bool hovering) - { - isHovering = hovering; - - if (isHovering || HandlingDrag) - this.FadeIn(fade_duration); - else - this.FadeOut(fade_duration); - } - } } } From 5e871f9838b16f5319cfa5886dc4a81c93137641 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 15:36:47 +0900 Subject: [PATCH 043/216] Make room playlist use the common rearrangeable design --- .../TestSceneDrawableRoomPlaylist.cs | 16 +- .../Screens/Multi/DrawableRoomPlaylist.cs | 10 +- .../Screens/Multi/DrawableRoomPlaylistItem.cs | 263 +++++++----------- 3 files changed, 112 insertions(+), 177 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index b906ce82e9..393fd281d4 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -1,6 +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 System; +using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -17,6 +19,12 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneDrawableRoomPlaylist : OsuTestScene { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(DrawableRoomPlaylist), + typeof(DrawableRoomPlaylistItem) + }; + [Resolved] private BeatmapManager beatmapManager { get; set; } @@ -26,25 +34,25 @@ namespace osu.Game.Tests.Visual.Multiplayer private DrawableRoomPlaylist playlist; [Test] - public void TestItemsCanNotBeRemovedOrSelectedFromNonEditableAndNonSelectablePlaylist() + public void TestNonEditableNonSelectable() { createPlaylist(false, false); } [Test] - public void TestItemsCanBeRemovedFromEditablePlaylist() + public void TestEditable() { createPlaylist(true, false); } [Test] - public void TestItemsCanBeSelectedInSelectablePlaylist() + public void TestSelectable() { createPlaylist(false, true); } [Test] - public void TestItemsCanBeSelectedAndRemovedFromEditableAndSelectablePlaylist() + public void TestEditableSelectable() { createPlaylist(true, true); } diff --git a/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs b/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs index b42a8575ec..021a8ca176 100644 --- a/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs +++ b/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Screens.Multi { - public class DrawableRoomPlaylist : RearrangeableListContainer + public class DrawableRoomPlaylist : OsuRearrangeableListContainer { public readonly Bindable SelectedItem = new Bindable(); @@ -45,10 +45,10 @@ namespace osu.Game.Screens.Multi }; } - protected override ScrollContainer CreateScrollContainer() => new OsuScrollContainer + protected override ScrollContainer CreateScrollContainer() => base.CreateScrollContainer().With(d => { - ScrollbarVisible = false - }; + d.ScrollbarVisible = false; + }); protected override FillFlowContainer> CreateListFillFlowContainer() => new FillFlowContainer> { @@ -57,7 +57,7 @@ namespace osu.Game.Screens.Multi Spacing = new Vector2(0, 2) }; - protected override RearrangeableListItem CreateDrawable(PlaylistItem item) => new DrawableRoomPlaylistItem(item, allowEdit, allowSelection) + protected override OsuRearrangeableListItem CreateOsuDrawable(PlaylistItem item) => new DrawableRoomPlaylistItem(item, allowEdit, allowSelection) { RequestSelection = requestSelection, RequestDeletion = requestDeletion diff --git a/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs index d2788a5c4b..2bc593d779 100644 --- a/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs @@ -5,6 +5,7 @@ using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -28,7 +29,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.Multi { - public class DrawableRoomPlaylistItem : RearrangeableListItem + public class DrawableRoomPlaylistItem : OsuRearrangeableListItem { public Action RequestSelection; public Action RequestDeletion; @@ -37,7 +38,6 @@ namespace osu.Game.Screens.Multi private Container difficultyIconContainer; private LinkFlowContainer beatmapText; private LinkFlowContainer authorText; - private ItemHandle handle; private ModDisplay modDisplay; private readonly Bindable beatmap = new Bindable(); @@ -55,9 +55,6 @@ namespace osu.Game.Screens.Multi this.allowEdit = allowEdit; this.allowSelection = allowSelection; - RelativeSizeAxes = Axes.X; - Height = 50; - beatmap.BindTo(item.Beatmap); ruleset.BindTo(item.Ruleset); requiredMods.BindTo(item.RequiredMods); @@ -66,118 +63,10 @@ namespace osu.Game.Screens.Multi [BackgroundDependencyLoader] private void load(OsuColour colours) { - InternalChild = new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] - { - new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Alpha = allowEdit ? 1 : 0, - Child = handle = new ItemHandle - { - Size = new Vector2(12), - AlwaysPresent = true, - Alpha = 0, - }, - }, - maskingContainer = new Container - { - RelativeSizeAxes = Axes.Both, - Masking = true, - CornerRadius = 10, - BorderColour = colours.Yellow, - Children = new Drawable[] - { - new Box // A transparent box that forces the border to be drawn if the panel background is opaque - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true - }, - new PanelBackground - { - RelativeSizeAxes = Axes.Both, - Beatmap = { BindTarget = beatmap } - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = 8 }, - Spacing = new Vector2(8, 0), - Direction = FillDirection.Horizontal, - Children = new Drawable[] - { - difficultyIconContainer = new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - }, - new FillFlowContainer - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - beatmapText = new LinkFlowContainer { AutoSizeAxes = Axes.Both }, - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new Drawable[] - { - authorText = new LinkFlowContainer { AutoSizeAxes = Axes.Both }, - modDisplay = new ModDisplay - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Scale = new Vector2(0.4f), - DisplayUnrankedText = false, - ExpansionMode = ExpansionMode.AlwaysExpanded - } - } - } - } - } - } - }, - new Container - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, - X = -18, - Children = new Drawable[] - { - new IconButton - { - Icon = FontAwesome.Solid.MinusSquare, - Alpha = allowEdit ? 1 : 0, - Action = () => RequestDeletion?.Invoke(Model), - }, - new PanelDownloadButton(item.Beatmap.Value.BeatmapSet) - { - Size = new Vector2(50, 30), - Alpha = allowEdit ? 0 : 1 - } - } - } - } - } - }, - }, - ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, - }; + if (!allowEdit) + HandleColour = HandleColour.Opacity(0); + + maskingContainer.BorderColour = colours.Yellow; } protected override void LoadComplete() @@ -193,6 +82,95 @@ namespace osu.Game.Screens.Multi refresh(); } + protected override Drawable CreateContent() => maskingContainer = new Container + { + RelativeSizeAxes = Axes.X, + Height = 50, + Masking = true, + CornerRadius = 10, + Children = new Drawable[] + { + new Box // A transparent box that forces the border to be drawn if the panel background is opaque + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + }, + new PanelBackground + { + RelativeSizeAxes = Axes.Both, + Beatmap = { BindTarget = beatmap } + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = 8 }, + Spacing = new Vector2(8, 0), + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + difficultyIconContainer = new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + beatmapText = new LinkFlowContainer { AutoSizeAxes = Axes.Both }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + authorText = new LinkFlowContainer { AutoSizeAxes = Axes.Both }, + modDisplay = new ModDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Scale = new Vector2(0.4f), + DisplayUnrankedText = false, + ExpansionMode = ExpansionMode.AlwaysExpanded + } + } + } + } + } + } + }, + new Container + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + X = -18, + Children = new Drawable[] + { + new IconButton + { + Icon = FontAwesome.Solid.MinusSquare, + Alpha = allowEdit ? 1 : 0, + Action = () => RequestDeletion?.Invoke(Model), + }, + new PanelDownloadButton(item.Beatmap.Value.BeatmapSet) + { + Size = new Vector2(50, 30), + Alpha = allowEdit ? 0 : 1 + } + } + } + } + }; + private ScheduledDelegate scheduledRefresh; private void scheduleRefresh() @@ -219,16 +197,6 @@ namespace osu.Game.Screens.Multi modDisplay.Current.Value = requiredMods.ToArray(); } - protected override bool IsDraggableAt(Vector2 screenSpacePos) => handle.HandlingDrag; - - protected override bool OnHover(HoverEvent e) - { - handle.UpdateHoverState(true); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) => handle.UpdateHoverState(false); - protected override bool OnClick(ClickEvent e) { if (allowSelection) @@ -302,46 +270,5 @@ namespace osu.Game.Screens.Multi }; } } - - private class ItemHandle : SpriteIcon - { - public bool HandlingDrag { get; private set; } - private bool isHovering; - - public ItemHandle() - { - Margin = new MarginPadding { Horizontal = 5 }; - - Icon = FontAwesome.Solid.Bars; - } - - protected override bool OnMouseDown(MouseDownEvent e) - { - base.OnMouseDown(e); - - HandlingDrag = true; - UpdateHoverState(isHovering); - - return false; - } - - protected override void OnMouseUp(MouseUpEvent e) - { - base.OnMouseUp(e); - - HandlingDrag = false; - UpdateHoverState(isHovering); - } - - public void UpdateHoverState(bool hovering) - { - isHovering = hovering; - - if (isHovering || HandlingDrag) - this.FadeIn(100); - else - this.FadeOut(100); - } - } } } From 720ceca78a3cdd5c90acf75684c8a0d65af2f67b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 15:38:47 +0900 Subject: [PATCH 044/216] Final tidy-up pass --- osu.Game/Online/OnlineViewContainer.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index b16fbb7aed..83fbff733f 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -19,7 +19,7 @@ namespace osu.Game.Online private readonly Placeholder placeholder; protected readonly LoadingAnimation LoadingAnimation; - protected const double TRANSFORM_TIME = 300.0; + private const double transform_duration = 300; protected override Container Content { get; } @@ -44,8 +44,9 @@ namespace osu.Game.Online protected override void LoadComplete() { - API.Register(this); base.LoadComplete(); + + API.Register(this); } public virtual void APIStateChanged(IAPIProvider api, APIState state) @@ -54,14 +55,14 @@ namespace osu.Game.Online { case APIState.Offline: PopContentOut(Content); - placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 3 * TRANSFORM_TIME, Easing.OutQuint); - placeholder.FadeInFromZero(2 * TRANSFORM_TIME, Easing.OutQuint); + placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 3 * transform_duration, Easing.OutQuint); + placeholder.FadeInFromZero(2 * transform_duration, Easing.OutQuint); LoadingAnimation.Hide(); break; case APIState.Online: PopContentIn(Content); - placeholder.FadeOut(TRANSFORM_TIME / 2, Easing.OutQuint); + placeholder.FadeOut(transform_duration / 2, Easing.OutQuint); LoadingAnimation.Hide(); break; @@ -69,7 +70,7 @@ namespace osu.Game.Online case APIState.Connecting: PopContentOut(Content); LoadingAnimation.Show(); - placeholder.FadeOut(TRANSFORM_TIME / 2, Easing.OutQuint); + placeholder.FadeOut(transform_duration / 2, Easing.OutQuint); break; } } @@ -77,12 +78,12 @@ namespace osu.Game.Online /// /// Applies a transform to the online content to make it hidden. /// - protected virtual void PopContentOut(Drawable content) => content.FadeOut(TRANSFORM_TIME / 2, Easing.OutQuint); + protected virtual void PopContentOut(Drawable content) => content.FadeOut(transform_duration / 2, Easing.OutQuint); /// /// Applies a transform to the online content to make it visible. /// - protected virtual void PopContentIn(Drawable content) => content.FadeIn(TRANSFORM_TIME, Easing.OutQuint); + protected virtual void PopContentIn(Drawable content) => content.FadeIn(transform_duration, Easing.OutQuint); protected override void Dispose(bool isDisposing) { From a75715607b3882c14ccab7984cc9ee4a97534522 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 15:41:46 +0900 Subject: [PATCH 045/216] Move drawable load to asynchronous context --- osu.Game/Online/OnlineViewContainer.cs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 83fbff733f..689c1c0afb 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -16,24 +16,30 @@ namespace osu.Game.Online /// public abstract class OnlineViewContainer : Container, IOnlineComponent { - private readonly Placeholder placeholder; - protected readonly LoadingAnimation LoadingAnimation; + protected LoadingAnimation LoadingAnimation { get; private set; } + + protected override Container Content { get; } = new Container { RelativeSizeAxes = Axes.Both }; + + private readonly string placeholderMessage; + + private Placeholder placeholder; private const double transform_duration = 300; - protected override Container Content { get; } - [Resolved] protected IAPIProvider API { get; private set; } protected OnlineViewContainer(string placeholderMessage) + { + this.placeholderMessage = placeholderMessage; + } + + [BackgroundDependencyLoader] + private void load() { InternalChildren = new Drawable[] { - Content = new Container - { - RelativeSizeAxes = Axes.Both, - }, + Content, placeholder = new LoginPlaceholder(placeholderMessage), LoadingAnimation = new LoadingAnimation { From 9cbb37b682fe35508c1aa030b4a97dad3ece41f4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 15:59:59 +0900 Subject: [PATCH 046/216] Fix bindable being created far too late in construction --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 7ebc26ebfb..28600ef55b 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -30,7 +30,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly Drawable cursorTrail; - public Bindable CursorScale; + public Bindable CursorScale = new BindableFloat(1); + private Bindable userCursorScale; private Bindable autoCursorScale; @@ -57,6 +58,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor protected override void LoadComplete() { + base.LoadComplete(); + showTrail.BindValueChanged(v => cursorTrail.FadeTo(v.NewValue ? 1 : 0, 200), true); userCursorScale = config.GetBindable(OsuSetting.GameplayCursorSize); @@ -65,7 +68,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor autoCursorScale = config.GetBindable(OsuSetting.AutoCursorSize); autoCursorScale.ValueChanged += _ => calculateScale(); - CursorScale = new BindableFloat(); CursorScale.ValueChanged += e => { var newScale = new Vector2(e.NewValue); @@ -75,8 +77,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor }; calculateScale(); - - base.LoadComplete(); } /// From 1909ea2bd3a17cd3d6a877dd4b01c1585d4f631c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 16:09:15 +0900 Subject: [PATCH 047/216] Add a way to hide the drag handle --- .../Containers/OsuRearrangeableListItem.cs | 17 +++++++++++++++-- .../Screens/Multi/DrawableRoomPlaylistItem.cs | 2 ++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs b/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs index f75a3330e2..29553954fe 100644 --- a/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs +++ b/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs @@ -23,6 +23,9 @@ namespace osu.Game.Graphics.Containers private Color4 handleColour = Color4.White; + /// + /// The colour of the drag handle. + /// protected Color4 HandleColour { get => handleColour; @@ -38,6 +41,11 @@ namespace osu.Game.Graphics.Containers } } + /// + /// Whether the drag handle should be shown. + /// + protected virtual bool ShowDragHandle => true; + private PlaylistItemHandle handle; protected OsuRearrangeableListItem(TModel item) @@ -50,6 +58,8 @@ namespace osu.Game.Graphics.Containers [BackgroundDependencyLoader] private void load() { + Container handleContainer; + InternalChild = new GridContainer { RelativeSizeAxes = Axes.X, @@ -58,7 +68,7 @@ namespace osu.Game.Graphics.Containers { new[] { - new Container + handleContainer = new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -78,6 +88,9 @@ namespace osu.Game.Graphics.Containers ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } }; + + if (!ShowDragHandle) + handleContainer.Alpha = 0; } protected override bool OnDragStart(DragStartEvent e) @@ -107,7 +120,7 @@ namespace osu.Game.Graphics.Containers protected abstract Drawable CreateContent(); - private class PlaylistItemHandle : SpriteIcon + public class PlaylistItemHandle : SpriteIcon { public bool HandlingDrag { get; private set; } private bool isHovering; diff --git a/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs index 2bc593d779..7156839dfc 100644 --- a/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs @@ -34,6 +34,8 @@ namespace osu.Game.Screens.Multi public Action RequestSelection; public Action RequestDeletion; + protected override bool ShowDragHandle => allowEdit; + private Container maskingContainer; private Container difficultyIconContainer; private LinkFlowContainer beatmapText; From d6768bba628c2feafac4c28b5719cc83ed83e48a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 16:09:30 +0900 Subject: [PATCH 048/216] Make test playlist items unique --- .../Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index 393fd281d4..d43bf9edea 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -79,6 +79,7 @@ namespace osu.Game.Tests.Visual.Multiplayer playlist.Items.Add(new PlaylistItem { + ID = i, Beatmap = { Value = beatmap }, Ruleset = { Value = rulesets[RNG.Next(0, rulesets.Count)] }, RequiredMods = From afd3e4604b5649e4f27e52afa6869e64249e8e2a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 16:48:23 +0900 Subject: [PATCH 049/216] Fix race condition causing selection to be reset incorrectly --- osu.Game/Screens/Multi/DrawableRoomPlaylist.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs b/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs index 021a8ca176..01f173db4e 100644 --- a/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs +++ b/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; @@ -38,11 +37,11 @@ namespace osu.Game.Screens.Multi ((DrawableRoomPlaylistItem)newItem).Select(); }, true); - Items.ItemsRemoved += items => + Items.ItemsRemoved += items => Schedule(() => { - if (items.Any(i => i == SelectedItem.Value)) + if (!Items.Contains(SelectedItem.Value)) SelectedItem.Value = null; - }; + }); } protected override ScrollContainer CreateScrollContainer() => base.CreateScrollContainer().With(d => From 6a466ea2f584e8c8c74ed8e92414ea00c5532dce Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 16:48:30 +0900 Subject: [PATCH 050/216] Improve test cases --- .../TestSceneDrawableRoomPlaylist.cs | 148 +++++++++++++++++- 1 file changed, 147 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index d43bf9edea..267496bba2 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -7,17 +7,22 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Beatmaps; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.Multi; using osuTK; +using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneDrawableRoomPlaylist : OsuTestScene + public class TestSceneDrawableRoomPlaylist : ManualInputManagerTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -37,26 +42,167 @@ namespace osu.Game.Tests.Visual.Multiplayer public void TestNonEditableNonSelectable() { createPlaylist(false, false); + + moveToItem(0); + assertHandleVisibility(0, false); + assertDeleteButtonVisibility(0, false); } [Test] public void TestEditable() { createPlaylist(true, false); + + moveToItem(0); + assertHandleVisibility(0, true); + assertDeleteButtonVisibility(0, true); } [Test] public void TestSelectable() { createPlaylist(false, true); + + moveToItem(0); + assertHandleVisibility(0, false); + assertDeleteButtonVisibility(0, false); + + AddStep("click", () => InputManager.Click(MouseButton.Left)); + + AddAssert("item 0 is selected", () => playlist.SelectedItem.Value == playlist.Items[0]); } [Test] public void TestEditableSelectable() { createPlaylist(true, true); + + moveToItem(0); + assertHandleVisibility(0, true); + assertDeleteButtonVisibility(0, true); + + AddStep("click", () => InputManager.Click(MouseButton.Left)); + + AddAssert("item 0 is selected", () => playlist.SelectedItem.Value == playlist.Items[0]); } + [Test] + public void TestSelectionNotLostAfterRearrangement() + { + createPlaylist(true, true); + + moveToItem(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + + moveToDragger(0); + AddStep("begin drag", () => InputManager.PressButton(MouseButton.Left)); + moveToDragger(1, new Vector2(0, 5)); + AddStep("end drag", () => InputManager.ReleaseButton(MouseButton.Left)); + + AddAssert("item 1 is selected", () => playlist.SelectedItem.Value == playlist.Items[1]); + } + + [Test] + public void TestItemRemovedOnDeletion() + { + PlaylistItem selectedItem = null; + + createPlaylist(true, true); + + moveToItem(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("retrieve selection", () => selectedItem = playlist.SelectedItem.Value); + + moveToDeleteButton(0); + AddStep("click delete button", () => InputManager.Click(MouseButton.Left)); + + AddAssert("item removed", () => !playlist.Items.Contains(selectedItem)); + } + + [Test] + public void TestNextItemSelectedAfterDeletion() + { + createPlaylist(true, true); + + moveToItem(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + + moveToDeleteButton(0); + AddStep("click delete button", () => InputManager.Click(MouseButton.Left)); + + AddAssert("item 0 is selected", () => playlist.SelectedItem.Value == playlist.Items[0]); + } + + [Test] + public void TestLastItemSelectedAfterLastItemDeleted() + { + createPlaylist(true, true); + + AddWaitStep("wait for flow", 5); // Items may take 1 update frame to flow. A wait count of 5 is guaranteed to result in the flow being updated as desired. + AddStep("scroll to bottom", () => playlist.ChildrenOfType>().First().ScrollToEnd(false)); + + moveToItem(19); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + + moveToDeleteButton(19); + AddStep("click delete button", () => InputManager.Click(MouseButton.Left)); + + AddAssert("item 18 is selected", () => playlist.SelectedItem.Value == playlist.Items[18]); + } + + [Test] + public void TestSelectionResetWhenAllItemsDeleted() + { + createPlaylist(true, true); + + AddStep("remove all but one item", () => + { + playlist.Items.RemoveRange(1, playlist.Items.Count - 1); + }); + + moveToItem(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + moveToDeleteButton(0); + AddStep("click delete button", () => InputManager.Click(MouseButton.Left)); + + AddAssert("selected item is null", () => playlist.SelectedItem.Value == null); + } + + // Todo: currently not possible due to bindable list shortcomings (https://github.com/ppy/osu-framework/issues/3081) + // [Test] + public void TestNextItemSelectedAfterExternalDeletion() + { + createPlaylist(true, true); + + moveToItem(0); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("remove item 0", () => playlist.Items.RemoveAt(0)); + + AddAssert("item 0 is selected", () => playlist.SelectedItem.Value == playlist.Items[0]); + } + + private void moveToItem(int index, Vector2? offset = null) + => AddStep($"move mouse to item {index}", () => InputManager.MoveMouseTo(playlist.ChildrenOfType>().ElementAt(index), offset)); + + private void moveToDragger(int index, Vector2? offset = null) => AddStep($"move mouse to dragger {index}", () => + { + var item = playlist.ChildrenOfType>().ElementAt(index); + InputManager.MoveMouseTo(item.ChildrenOfType.PlaylistItemHandle>().Single(), offset); + }); + + private void moveToDeleteButton(int index, Vector2? offset = null) => AddStep($"move mouse to delete button {index}", () => + { + var item = playlist.ChildrenOfType>().ElementAt(index); + InputManager.MoveMouseTo(item.ChildrenOfType().ElementAt(0), offset); + }); + + private void assertHandleVisibility(int index, bool visible) + => AddAssert($"handle {index} {(visible ? "is" : "is not")} visible", + () => (playlist.ChildrenOfType.PlaylistItemHandle>().ElementAt(index).Alpha > 0) == visible); + + private void assertDeleteButtonVisibility(int index, bool visible) + => AddAssert($"delete button {index} {(visible ? "is" : "is not")} visible", () => (playlist.ChildrenOfType().ElementAt(2 + index * 2).Alpha > 0) == visible); + private void createPlaylist(bool allowEdit, bool allowSelection) => AddStep("create playlist", () => { Child = playlist = new DrawableRoomPlaylist(allowEdit, allowSelection) From aceba8791c2e3bbbb1a541351257900ae3a56fa0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 16:55:05 +0900 Subject: [PATCH 051/216] Clean up selection handling --- .../TestSceneDrawableRoomPlaylist.cs | 8 ++- .../Screens/Multi/DrawableRoomPlaylist.cs | 12 +--- .../Screens/Multi/DrawableRoomPlaylistItem.cs | 63 +++++++++---------- 3 files changed, 40 insertions(+), 43 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index 267496bba2..c93d59acdf 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -46,6 +46,9 @@ namespace osu.Game.Tests.Visual.Multiplayer moveToItem(0); assertHandleVisibility(0, false); assertDeleteButtonVisibility(0, false); + + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddAssert("no item selected", () => playlist.SelectedItem.Value == null); } [Test] @@ -56,6 +59,9 @@ namespace osu.Game.Tests.Visual.Multiplayer moveToItem(0); assertHandleVisibility(0, true); assertDeleteButtonVisibility(0, true); + + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddAssert("no item selected", () => playlist.SelectedItem.Value == null); } [Test] @@ -165,7 +171,7 @@ namespace osu.Game.Tests.Visual.Multiplayer moveToDeleteButton(0); AddStep("click delete button", () => InputManager.Click(MouseButton.Left)); - AddAssert("selected item is null", () => playlist.SelectedItem.Value == null); + AddAssert("no item selected", () => playlist.SelectedItem.Value == null); } // Todo: currently not possible due to bindable list shortcomings (https://github.com/ppy/osu-framework/issues/3081) diff --git a/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs b/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs index 01f173db4e..b139c61166 100644 --- a/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs +++ b/osu.Game/Screens/Multi/DrawableRoomPlaylist.cs @@ -28,15 +28,7 @@ namespace osu.Game.Screens.Multi { base.LoadComplete(); - SelectedItem.BindValueChanged(item => - { - if (item.OldValue != null && ItemMap.TryGetValue(item.OldValue, out var oldItem)) - ((DrawableRoomPlaylistItem)oldItem).Deselect(); - - if (item.NewValue != null && ItemMap.TryGetValue(item.NewValue, out var newItem)) - ((DrawableRoomPlaylistItem)newItem).Select(); - }, true); - + // Scheduled since items are removed and re-added upon rearrangement Items.ItemsRemoved += items => Schedule(() => { if (!Items.Contains(SelectedItem.Value)) @@ -58,7 +50,7 @@ namespace osu.Game.Screens.Multi protected override OsuRearrangeableListItem CreateOsuDrawable(PlaylistItem item) => new DrawableRoomPlaylistItem(item, allowEdit, allowSelection) { - RequestSelection = requestSelection, + SelectedItem = { BindTarget = SelectedItem }, RequestDeletion = requestDeletion }; diff --git a/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs index 7156839dfc..b1e69e4c4f 100644 --- a/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs @@ -31,9 +31,10 @@ namespace osu.Game.Screens.Multi { public class DrawableRoomPlaylistItem : OsuRearrangeableListItem { - public Action RequestSelection; public Action RequestDeletion; + public readonly Bindable SelectedItem = new Bindable(); + protected override bool ShowDragHandle => allowEdit; private Container maskingContainer; @@ -75,6 +76,8 @@ namespace osu.Game.Screens.Multi { base.LoadComplete(); + SelectedItem.BindValueChanged(selected => maskingContainer.BorderThickness = selected.NewValue == Model ? 5 : 0); + beatmap.BindValueChanged(_ => scheduleRefresh()); ruleset.BindValueChanged(_ => scheduleRefresh()); @@ -84,6 +87,32 @@ namespace osu.Game.Screens.Multi refresh(); } + private ScheduledDelegate scheduledRefresh; + + private void scheduleRefresh() + { + scheduledRefresh?.Cancel(); + scheduledRefresh = Schedule(refresh); + } + + private void refresh() + { + difficultyIconContainer.Child = new DifficultyIcon(beatmap.Value, ruleset.Value) { Size = new Vector2(32) }; + + beatmapText.Clear(); + beatmapText.AddLink(item.Beatmap.ToString(), LinkAction.OpenBeatmap, item.Beatmap.Value.OnlineBeatmapID.ToString()); + + authorText.Clear(); + + if (item.Beatmap?.Value?.Metadata?.Author != null) + { + authorText.AddText("mapped by "); + authorText.AddUserLink(item.Beatmap.Value?.Metadata.Author); + } + + modDisplay.Current.Value = requiredMods.ToArray(); + } + protected override Drawable CreateContent() => maskingContainer = new Container { RelativeSizeAxes = Axes.X, @@ -173,43 +202,13 @@ namespace osu.Game.Screens.Multi } }; - private ScheduledDelegate scheduledRefresh; - - private void scheduleRefresh() - { - scheduledRefresh?.Cancel(); - scheduledRefresh = Schedule(refresh); - } - - private void refresh() - { - difficultyIconContainer.Child = new DifficultyIcon(beatmap.Value, ruleset.Value) { Size = new Vector2(32) }; - - beatmapText.Clear(); - beatmapText.AddLink(item.Beatmap.ToString(), LinkAction.OpenBeatmap, item.Beatmap.Value.OnlineBeatmapID.ToString()); - - authorText.Clear(); - - if (item.Beatmap?.Value?.Metadata?.Author != null) - { - authorText.AddText("mapped by "); - authorText.AddUserLink(item.Beatmap.Value?.Metadata.Author); - } - - modDisplay.Current.Value = requiredMods.ToArray(); - } - protected override bool OnClick(ClickEvent e) { if (allowSelection) - RequestSelection?.Invoke(Model); + SelectedItem.Value = Model; return true; } - public void Select() => maskingContainer.BorderThickness = 5; - - public void Deselect() => maskingContainer.BorderThickness = 0; - // For now, this is the same implementation as in PanelBackground, but supports a beatmap info rather than a working beatmap private class PanelBackground : Container // todo: should be a buffered container (https://github.com/ppy/osu-framework/issues/3222) { From 9ea6912520954aa28e6a5b1eb23d16da90716f95 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 16:58:56 +0900 Subject: [PATCH 052/216] Improve overall readability of OsuModeRelax --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 45 +++++++++++++++-------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 649b01c132..7ebb6fd76d 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -19,33 +19,46 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things."; public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray(); + /// + /// How early before a hitobject's start time to trigger a hit. + /// + private const float relax_leniency = 3; + public void Update(Playfield playfield) { bool requiresHold = false; bool requiresHit = false; - const float relax_leniency = 3; + double time = playfield.Clock.CurrentTime; - foreach (var drawable in playfield.HitObjectContainer.AliveObjects) + foreach (var h in playfield.HitObjectContainer.AliveObjects.OfType()) { - if (!(drawable is DrawableOsuHitObject osuHit)) + // we are not yet close enough to the object. + if (time < h.HitObject.StartTime - relax_leniency) + break; + + // already hit or beyond the hittable end time. + if (h.IsHit || (h.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime)) continue; - double time = osuHit.Clock.CurrentTime; - double relativetime = time - osuHit.HitObject.StartTime; - - if (time < osuHit.HitObject.StartTime - relax_leniency) continue; - - if ((osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime) || osuHit.IsHit) - continue; - - if (osuHit is DrawableHitCircle && osuHit.IsHovered) + switch (h) { - Debug.Assert(osuHit.HitObject.HitWindows != null); - requiresHit |= osuHit.HitObject.HitWindows.CanBeHit(relativetime); - } + case DrawableHitCircle _: + if (!h.IsHovered) + break; - requiresHold |= (osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered)) || osuHit is DrawableSpinner; + Debug.Assert(h.HitObject.HitWindows != null); + requiresHit |= h.HitObject.HitWindows.CanBeHit(time - h.HitObject.StartTime); + break; + + case DrawableSlider slider: + requiresHold |= slider.Ball.IsHovered || h.IsHovered; + break; + + case DrawableSpinner _: + requiresHold = true; + break; + } } if (requiresHit) From cd2d1b06697d5b49fda11240425b8982d2af66b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 17:00:55 +0900 Subject: [PATCH 053/216] Fix 2B maps not playing correctly with relax mod enabled --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 7ebb6fd76d..d971e777ec 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -43,15 +43,15 @@ namespace osu.Game.Rulesets.Osu.Mods switch (h) { - case DrawableHitCircle _: - if (!h.IsHovered) - break; - - Debug.Assert(h.HitObject.HitWindows != null); - requiresHit |= h.HitObject.HitWindows.CanBeHit(time - h.HitObject.StartTime); + case DrawableHitCircle circle: + handleHitCircle(circle); break; case DrawableSlider slider: + // Handles cases like "2B" beatmaps, where sliders may be overlapping and simply holding is not enough. + if (!slider.HeadCircle.IsHit) + handleHitCircle(slider.HeadCircle); + requiresHold |= slider.Ball.IsHovered || h.IsHovered; break; @@ -68,6 +68,15 @@ namespace osu.Game.Rulesets.Osu.Mods } addAction(requiresHold); + + void handleHitCircle(DrawableHitCircle circle) + { + if (!circle.IsHovered) + return; + + Debug.Assert(circle.HitObject.HitWindows != null); + requiresHit |= circle.HitObject.HitWindows.CanBeHit(time - circle.HitObject.StartTime); + } } private bool wasHit; From 4ce687d608badbf3828992852e4070dcfb978cf4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 17:03:23 +0900 Subject: [PATCH 054/216] Move public methods up --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index d971e777ec..f874bc271f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -24,6 +24,18 @@ namespace osu.Game.Rulesets.Osu.Mods /// private const float relax_leniency = 3; + private bool wasHit; + private bool wasLeft; + + private OsuInputManager osuInputManager; + + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) + { + // grab the input manager for future use. + osuInputManager = (OsuInputManager)drawableRuleset.KeyBindingInputManager; + osuInputManager.AllowUserPresses = false; + } + public void Update(Playfield playfield) { bool requiresHold = false; @@ -79,11 +91,6 @@ namespace osu.Game.Rulesets.Osu.Mods } } - private bool wasHit; - private bool wasLeft; - - private OsuInputManager osuInputManager; - private void addAction(bool hitting) { if (wasHit == hitting) @@ -104,12 +111,5 @@ namespace osu.Game.Rulesets.Osu.Mods state.Apply(osuInputManager.CurrentState, osuInputManager); } - - public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) - { - // grab the input manager for future use. - osuInputManager = (OsuInputManager)drawableRuleset.KeyBindingInputManager; - osuInputManager.AllowUserPresses = false; - } } } From 61a7f04efb7036a9998160b73d3f6166a671005c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 17:13:50 +0900 Subject: [PATCH 055/216] Add a sane key up delay to relax mod --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 50 +++++++++++++--------- osu.Game/Rulesets/Replays/AutoGenerator.cs | 2 +- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index f874bc271f..6286c80d7c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -9,6 +9,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.UI; using static osu.Game.Input.Handlers.ReplayInputHandler; @@ -24,11 +25,14 @@ namespace osu.Game.Rulesets.Osu.Mods /// private const float relax_leniency = 3; - private bool wasHit; + private bool isDownState; private bool wasLeft; private OsuInputManager osuInputManager; + private ReplayState state; + private double lastStateChangeTime; + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { // grab the input manager for future use. @@ -75,11 +79,14 @@ namespace osu.Game.Rulesets.Osu.Mods if (requiresHit) { - addAction(false); - addAction(true); + changeState(false); + changeState(true); } - addAction(requiresHold); + if (requiresHold) + changeState(true); + else if (isDownState && time - lastStateChangeTime > AutoGenerator.KEY_UP_DELAY) + changeState(false); void handleHitCircle(DrawableHitCircle circle) { @@ -89,27 +96,28 @@ namespace osu.Game.Rulesets.Osu.Mods Debug.Assert(circle.HitObject.HitWindows != null); requiresHit |= circle.HitObject.HitWindows.CanBeHit(time - circle.HitObject.StartTime); } - } - private void addAction(bool hitting) - { - if (wasHit == hitting) - return; - - wasHit = hitting; - - var state = new ReplayState + void changeState(bool down) { - PressedActions = new List() - }; + if (isDownState == down) + return; - if (hitting) - { - state.PressedActions.Add(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); - wasLeft = !wasLeft; + isDownState = down; + lastStateChangeTime = time; + + state = new ReplayState + { + PressedActions = new List() + }; + + if (down) + { + state.PressedActions.Add(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); + wasLeft = !wasLeft; + } + + state?.Apply(osuInputManager.CurrentState, osuInputManager); } - - state.Apply(osuInputManager.CurrentState, osuInputManager); } } } diff --git a/osu.Game/Rulesets/Replays/AutoGenerator.cs b/osu.Game/Rulesets/Replays/AutoGenerator.cs index 3319f30a6f..b3c609f2f4 100644 --- a/osu.Game/Rulesets/Replays/AutoGenerator.cs +++ b/osu.Game/Rulesets/Replays/AutoGenerator.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Replays #region Constants // Shared amongst all modes - protected const double KEY_UP_DELAY = 50; + public const double KEY_UP_DELAY = 50; #endregion From 5ec9f454d5f5caf792d287bf34e1524b6410123e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 17:20:38 +0900 Subject: [PATCH 056/216] Implement the match beatmap detail area --- .../TestSceneMatchBeatmapDetailArea.cs | 67 +++++++++++++ .../Multiplayer/TestSceneMatchSongSelect.cs | 37 +++++++ .../BeatmapDetailAreaPlaylistTabItem.cs | 12 +++ .../Components/MatchBeatmapDetailArea.cs | 98 +++++++++++++++++++ osu.Game/Screens/Select/MatchSongSelect.cs | 3 +- 5 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs create mode 100644 osu.Game/Screens/Multi/Components/BeatmapDetailAreaPlaylistTabItem.cs create mode 100644 osu.Game/Screens/Multi/Components/MatchBeatmapDetailArea.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs new file mode 100644 index 0000000000..09d882a265 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs @@ -0,0 +1,67 @@ +// Copyright (c) ppy Pty Ltd . 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.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Utils; +using osu.Game.Beatmaps; +using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Screens.Multi.Components; +using osuTK; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneMatchBeatmapDetailArea : MultiplayerTestScene + { + [Resolved] + private BeatmapManager beatmapManager { get; set; } + + [Resolved] + + private RulesetStore rulesetStore { get; set; } + + private MatchBeatmapDetailArea detailArea; + + [SetUp] + public void Setup() => Schedule(() => + { + Room.Playlist.Clear(); + + Child = detailArea = new MatchBeatmapDetailArea + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(500), + CreateNewItem = createNewItem + }; + }); + + private void createNewItem() + { + var set = beatmapManager.GetAllUsableBeatmapSetsEnumerable().First(); + var rulesets = rulesetStore.AvailableRulesets.ToList(); + + var beatmap = set.Beatmaps[RNG.Next(0, set.Beatmaps.Count)]; + + beatmap.BeatmapSet = set; + beatmap.Metadata = set.Metadata; + + Room.Playlist.Add(new PlaylistItem + { + ID = Room.Playlist.Count, + Beatmap = { Value = beatmap }, + Ruleset = { Value = rulesets[RNG.Next(0, rulesets.Count)] }, + RequiredMods = + { + new OsuModHardRock(), + new OsuModDoubleTime(), + new OsuModAutoplay() + } + }); + } + } +} diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs new file mode 100644 index 0000000000..f6e4715182 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs @@ -0,0 +1,37 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Game.Beatmaps; +using osu.Game.Screens.Multi.Components; +using osu.Game.Screens.Select; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneMatchSongSelect : MultiplayerTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(MatchSongSelect), + typeof(MatchBeatmapDetailArea), + }; + + [Resolved] + private BeatmapManager beatmapManager { get; set; } + + [SetUp] + public void Setup() => Schedule(() => + { + Room.Playlist.Clear(); + }); + + [Test] + public void TestLoadSongSelect() + { + AddStep("create song select", () => LoadScreen(new MatchSongSelect())); + } + } +} diff --git a/osu.Game/Screens/Multi/Components/BeatmapDetailAreaPlaylistTabItem.cs b/osu.Game/Screens/Multi/Components/BeatmapDetailAreaPlaylistTabItem.cs new file mode 100644 index 0000000000..3f2ab28f1a --- /dev/null +++ b/osu.Game/Screens/Multi/Components/BeatmapDetailAreaPlaylistTabItem.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Screens.Select; + +namespace osu.Game.Screens.Multi.Components +{ + public class BeatmapDetailAreaPlaylistTabItem : BeatmapDetailAreaTabItem + { + public override string Name => "Playlist"; + } +} diff --git a/osu.Game/Screens/Multi/Components/MatchBeatmapDetailArea.cs b/osu.Game/Screens/Multi/Components/MatchBeatmapDetailArea.cs new file mode 100644 index 0000000000..8e085d6979 --- /dev/null +++ b/osu.Game/Screens/Multi/Components/MatchBeatmapDetailArea.cs @@ -0,0 +1,98 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Select; +using osuTK; + +namespace osu.Game.Screens.Multi.Components +{ + public class MatchBeatmapDetailArea : BeatmapDetailArea + { + public Action CreateNewItem; + + public readonly Bindable SelectedItem = new Bindable(); + + [Resolved(typeof(Room))] + protected BindableList Playlist { get; private set; } + + private readonly Drawable playlistArea; + private readonly DrawableRoomPlaylist playlist; + + public MatchBeatmapDetailArea() + { + Add(playlistArea = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Vertical = 10 }, + Child = new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Bottom = 10 }, + Child = playlist = new DrawableRoomPlaylist(true, false) + { + RelativeSizeAxes = Axes.Both, + } + } + }, + new Drawable[] + { + new TriangleButton + { + Text = "create new item", + RelativeSizeAxes = Axes.Both, + Size = Vector2.One, + Action = () => CreateNewItem?.Invoke() + } + }, + }, + RowDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.Absolute, 50), + } + } + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + playlist.Items.BindTo(Playlist); + playlist.SelectedItem.BindTo(SelectedItem); + } + + protected override void OnTabChanged(BeatmapDetailAreaTabItem tab, bool selectedMods) + { + base.OnTabChanged(tab, selectedMods); + + switch (tab) + { + case BeatmapDetailAreaPlaylistTabItem _: + playlistArea.Show(); + break; + + default: + playlistArea.Hide(); + break; + } + } + + protected override BeatmapDetailAreaTabItem[] CreateTabItems() => base.CreateTabItems().Prepend(new BeatmapDetailAreaPlaylistTabItem()).ToArray(); + } +} diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 826677ee30..94d65889d1 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -12,6 +12,7 @@ using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi; +using osu.Game.Screens.Multi.Components; namespace osu.Game.Screens.Select { @@ -35,7 +36,7 @@ namespace osu.Game.Screens.Select Padding = new MarginPadding { Horizontal = HORIZONTAL_OVERFLOW_PADDING }; } - protected override BeatmapDetailArea CreateBeatmapDetailArea() => new PlayBeatmapDetailArea(); // Todo: Temporary + protected override BeatmapDetailArea CreateBeatmapDetailArea() => new MatchBeatmapDetailArea(); protected override bool OnStart() { From 66910f1ee3489ed83890b772599e6ce02475a30e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 17:50:53 +0900 Subject: [PATCH 057/216] Remove unnecessary bindable setter --- osu.Game/Screens/Select/BeatmapDetailArea.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index 1aae0cc243..2e78b1aed2 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -28,11 +28,7 @@ namespace osu.Game.Screens.Select public readonly BeatmapDetails Details; - protected Bindable CurrentTab - { - get => tabControl.Current; - set => tabControl.Current = value; - } + protected Bindable CurrentTab => tabControl.Current; private readonly Container content; protected override Container Content => content; From f0f739707f2e9a91cc4d64096afe4aae1e8a5ab0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 17:51:42 +0900 Subject: [PATCH 058/216] Add playlist support to match song select --- .../Multiplayer/TestSceneMatchSongSelect.cs | 101 +++++++++++++++++- osu.Game/Screens/Select/MatchSongSelect.cs | 42 +++----- 2 files changed, 114 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs index f6e4715182..434b265f9c 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs @@ -3,9 +3,19 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Extensions; +using osu.Framework.Platform; +using osu.Framework.Screens; +using osu.Framework.Utils; using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Select; @@ -22,6 +32,72 @@ namespace osu.Game.Tests.Visual.Multiplayer [Resolved] private BeatmapManager beatmapManager { get; set; } + private BeatmapManager manager; + + private RulesetStore rulesets; + + private TestMatchSongSelect songSelect; + + [BackgroundDependencyLoader] + private void load(GameHost host, AudioManager audio) + { + Dependencies.Cache(rulesets = new RulesetStore(ContextFactory)); + Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, Beatmap.Default)); + + var beatmaps = new List(); + + for (int i = 0; i < 6; i++) + { + int beatmapId = 10 * 10 + i; + + int length = RNG.Next(30000, 200000); + double bpm = RNG.NextSingle(80, 200); + + beatmaps.Add(new BeatmapInfo + { + Ruleset = new OsuRuleset().RulesetInfo, + OnlineBeatmapID = beatmapId, + Path = "normal.osu", + Version = $"{beatmapId} (length {TimeSpan.FromMilliseconds(length):m\\:ss}, bpm {bpm:0.#})", + Length = length, + BPM = bpm, + BaseDifficulty = new BeatmapDifficulty + { + OverallDifficulty = 3.5f, + }, + }); + } + + manager.Import(new BeatmapSetInfo + { + OnlineBeatmapSetID = 10, + Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), + Metadata = new BeatmapMetadata + { + // Create random metadata, then we can check if sorting works based on these + Artist = "Some Artist " + RNG.Next(0, 9), + Title = $"Some Song (set id 10), max bpm {beatmaps.Max(b => b.BPM):0.#})", + AuthorString = "Some Guy " + RNG.Next(0, 9), + }, + Beatmaps = beatmaps, + DateAdded = DateTimeOffset.UtcNow, + }).Wait(); + } + + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("reset", () => + { + Ruleset.Value = new OsuRuleset().RulesetInfo; + Beatmap.SetDefault(); + }); + + AddStep("create song select", () => LoadScreen(songSelect = new TestMatchSongSelect())); + AddUntilStep("wait for present", () => songSelect.IsCurrentScreen()); + } + [SetUp] public void Setup() => Schedule(() => { @@ -29,9 +105,30 @@ namespace osu.Game.Tests.Visual.Multiplayer }); [Test] - public void TestLoadSongSelect() + public void TestItemAddedIfEmptyOnStart() { - AddStep("create song select", () => LoadScreen(new MatchSongSelect())); + AddStep("finalise selection", () => songSelect.FinaliseSelection()); + AddAssert("playlist has 1 item", () => Room.Playlist.Count == 1); + } + + [Test] + public void TestItemAddedWhenCreateNewItemClicked() + { + AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem()); + AddAssert("playlist has 1 item", () => Room.Playlist.Count == 1); + } + + [Test] + public void TestItemNotAddedIfExistingOnStart() + { + AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem()); + AddStep("finalise selection", () => songSelect.FinaliseSelection()); + AddAssert("playlist has 1 item", () => Room.Playlist.Count == 1); + } + + private class TestMatchSongSelect : MatchSongSelect + { + public new MatchBeatmapDetailArea BeatmapDetails => (MatchBeatmapDetailArea)base.BeatmapDetails; } } } diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 94d65889d1..4edc968e8a 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Linq; using Humanizer; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -10,7 +9,6 @@ using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi; using osu.Game.Screens.Multi.Components; @@ -36,42 +34,32 @@ namespace osu.Game.Screens.Select Padding = new MarginPadding { Horizontal = HORIZONTAL_OVERFLOW_PADDING }; } - protected override BeatmapDetailArea CreateBeatmapDetailArea() => new MatchBeatmapDetailArea(); + protected override BeatmapDetailArea CreateBeatmapDetailArea() => new MatchBeatmapDetailArea + { + CreateNewItem = createNewItem + }; protected override bool OnStart() { - var item = new PlaylistItem - { - Beatmap = { Value = Beatmap.Value.BeatmapInfo }, - Ruleset = { Value = Ruleset.Value }, - RulesetID = Ruleset.Value.ID ?? 0 - }; + if (Playlist.Count == 0) + createNewItem(); - item.RequiredMods.AddRange(Mods.Value); - - Selected?.Invoke(item); - - if (this.IsCurrentScreen()) - this.Exit(); + this.Exit(); return true; } - public override bool OnExiting(IScreen next) + private void createNewItem() { - if (base.OnExiting(next)) - return true; - - var firstItem = Playlist.FirstOrDefault(); - - if (firstItem != null) + PlaylistItem item = new PlaylistItem { - Ruleset.Value = firstItem.Ruleset.Value; - Beatmap.Value = beatmaps.GetWorkingBeatmap(firstItem.Beatmap.Value); - Mods.Value = firstItem.RequiredMods?.ToArray() ?? Array.Empty(); - } + Beatmap = { Value = Beatmap.Value.BeatmapInfo }, + Ruleset = { Value = Ruleset.Value } + }; - return false; + item.RequiredMods.AddRange(Mods.Value); + + Playlist.Add(item); } } } From 32fd713a9d4c4d40a5066e155efc463c207e3701 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 17:57:25 +0900 Subject: [PATCH 059/216] Use test beatmap instead of beatmap manager --- .../Multiplayer/TestSceneDrawableRoomPlaylist.cs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index c93d59acdf..4ba802730f 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -9,14 +9,15 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; -using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.Multi; +using osu.Game.Tests.Beatmaps; using osuTK; using osuTK.Input; @@ -218,22 +219,13 @@ namespace osu.Game.Tests.Visual.Multiplayer Size = new Vector2(500, 300) }; - var beatmapSets = beatmapManager.GetAllUsableBeatmapSets(); - var rulesets = rulesetStore.AvailableRulesets.ToList(); - for (int i = 0; i < 20; i++) { - var set = beatmapSets[RNG.Next(0, beatmapSets.Count)]; - var beatmap = set.Beatmaps[RNG.Next(0, set.Beatmaps.Count)]; - - beatmap.BeatmapSet = set; - beatmap.Metadata = set.Metadata; - playlist.Items.Add(new PlaylistItem { ID = i, - Beatmap = { Value = beatmap }, - Ruleset = { Value = rulesets[RNG.Next(0, rulesets.Count)] }, + Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, + Ruleset = { Value = new OsuRuleset().RulesetInfo }, RequiredMods = { new OsuModHardRock(), From de646649def7d7ca2d0322ab925f386c46343e63 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 17:59:14 +0900 Subject: [PATCH 060/216] Use test beatmap instead of beatmap manager --- .../TestSceneMatchBeatmapDetailArea.cs | 30 ++++--------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs index 09d882a265..13fcc18e56 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs @@ -1,37 +1,25 @@ // Copyright (c) ppy Pty Ltd . 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.Allocation; using osu.Framework.Graphics; -using osu.Framework.Utils; -using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.Multi.Components; +using osu.Game.Tests.Beatmaps; using osuTK; namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMatchBeatmapDetailArea : MultiplayerTestScene { - [Resolved] - private BeatmapManager beatmapManager { get; set; } - - [Resolved] - - private RulesetStore rulesetStore { get; set; } - - private MatchBeatmapDetailArea detailArea; - [SetUp] public void Setup() => Schedule(() => { Room.Playlist.Clear(); - Child = detailArea = new MatchBeatmapDetailArea + Child = new MatchBeatmapDetailArea { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -42,19 +30,11 @@ namespace osu.Game.Tests.Visual.Multiplayer private void createNewItem() { - var set = beatmapManager.GetAllUsableBeatmapSetsEnumerable().First(); - var rulesets = rulesetStore.AvailableRulesets.ToList(); - - var beatmap = set.Beatmaps[RNG.Next(0, set.Beatmaps.Count)]; - - beatmap.BeatmapSet = set; - beatmap.Metadata = set.Metadata; - Room.Playlist.Add(new PlaylistItem { ID = Room.Playlist.Count, - Beatmap = { Value = beatmap }, - Ruleset = { Value = rulesets[RNG.Next(0, rulesets.Count)] }, + Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, + Ruleset = { Value = new OsuRuleset().RulesetInfo }, RequiredMods = { new OsuModHardRock(), From fbc5ffbadbd27e5856b8c94c6d046a3513b5df16 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 17:59:47 +0900 Subject: [PATCH 061/216] Remove now unused members --- .../Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index 4ba802730f..d2d02412cd 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -5,15 +5,12 @@ 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.Testing; -using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.Multi; @@ -31,12 +28,6 @@ namespace osu.Game.Tests.Visual.Multiplayer typeof(DrawableRoomPlaylistItem) }; - [Resolved] - private BeatmapManager beatmapManager { get; set; } - - [Resolved] - private RulesetStore rulesetStore { get; set; } - private DrawableRoomPlaylist playlist; [Test] From be30ef3cca69c1b00beebdf1a579edc5f47f84f9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 18:13:52 +0900 Subject: [PATCH 062/216] Move BeatmapMetadataDisplay to its own class --- .../Screens/Play/BeatmapMetadataDisplay.cs | 180 ++++++++++++++++++ osu.Game/Screens/Play/PlayerLoader.cs | 163 ---------------- 2 files changed, 180 insertions(+), 163 deletions(-) create mode 100644 osu.Game/Screens/Play/BeatmapMetadataDisplay.cs diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs new file mode 100644 index 0000000000..074341226e --- /dev/null +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -0,0 +1,180 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Play.HUD; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Play +{ + /// + /// Displays beatmap metadata inside + /// + public class BeatmapMetadataDisplay : Container + { + private class MetadataLine : Container + { + public MetadataLine(string left, string right) + { + AutoSizeAxes = Axes.Both; + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopRight, + Margin = new MarginPadding { Right = 5 }, + Colour = OsuColour.Gray(0.8f), + Text = left, + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopLeft, + Margin = new MarginPadding { Left = 5 }, + Text = string.IsNullOrEmpty(right) ? @"-" : right, + } + }; + } + } + + private readonly WorkingBeatmap beatmap; + private readonly Bindable> mods; + private readonly Drawable facade; + private LoadingAnimation loading; + private Sprite backgroundSprite; + + public IBindable> Mods => mods; + + public bool Loading + { + set + { + if (value) + { + loading.Show(); + backgroundSprite.FadeColour(OsuColour.Gray(0.5f), 400, Easing.OutQuint); + } + else + { + loading.Hide(); + backgroundSprite.FadeColour(Color4.White, 400, Easing.OutQuint); + } + } + } + + public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Bindable> mods, Drawable facade) + { + this.beatmap = beatmap; + this.facade = facade; + + this.mods = new Bindable>(); + this.mods.BindTo(mods); + } + + [BackgroundDependencyLoader] + private void load() + { + var metadata = beatmap.BeatmapInfo?.Metadata ?? new BeatmapMetadata(); + + AutoSizeAxes = Axes.Both; + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Direction = FillDirection.Vertical, + Children = new[] + { + facade.With(d => + { + d.Anchor = Anchor.TopCentre; + d.Origin = Anchor.TopCentre; + }), + new OsuSpriteText + { + Text = new LocalisedString((metadata.TitleUnicode, metadata.Title)), + Font = OsuFont.GetFont(size: 36, italics: true), + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Margin = new MarginPadding { Top = 15 }, + }, + new OsuSpriteText + { + Text = new LocalisedString((metadata.ArtistUnicode, metadata.Artist)), + Font = OsuFont.GetFont(size: 26, italics: true), + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + }, + new Container + { + Size = new Vector2(300, 60), + Margin = new MarginPadding(10), + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + CornerRadius = 10, + Masking = true, + Children = new Drawable[] + { + backgroundSprite = new Sprite + { + RelativeSizeAxes = Axes.Both, + Texture = beatmap?.Background, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + FillMode = FillMode.Fill, + }, + loading = new LoadingAnimation { Scale = new Vector2(1.3f) } + } + }, + new OsuSpriteText + { + Text = beatmap?.BeatmapInfo?.Version, + Font = OsuFont.GetFont(size: 26, italics: true), + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Margin = new MarginPadding + { + Bottom = 40 + }, + }, + new MetadataLine("Source", metadata.Source) + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + }, + new MetadataLine("Mapper", metadata.AuthorString) + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + }, + new ModDisplay + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Top = 20 }, + Current = mods + } + }, + } + }; + + Loading = true; + } + } +} diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index f37faac988..ebc2422dc5 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; @@ -12,21 +11,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; -using osu.Framework.Localisation; using osu.Framework.Screens; using osu.Framework.Threading; -using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Input; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; -using osu.Game.Rulesets.Mods; using osu.Game.Screens.Menu; -using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.PlayerSettings; using osu.Game.Users; using osuTK; @@ -350,162 +343,6 @@ namespace osu.Game.Screens.Play } } - protected class BeatmapMetadataDisplay : Container - { - private class MetadataLine : Container - { - public MetadataLine(string left, string right) - { - AutoSizeAxes = Axes.Both; - Children = new Drawable[] - { - new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopRight, - Margin = new MarginPadding { Right = 5 }, - Colour = OsuColour.Gray(0.8f), - Text = left, - }, - new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopLeft, - Margin = new MarginPadding { Left = 5 }, - Text = string.IsNullOrEmpty(right) ? @"-" : right, - } - }; - } - } - - private readonly WorkingBeatmap beatmap; - private readonly Bindable> mods; - private readonly Drawable facade; - private LoadingAnimation loading; - private Sprite backgroundSprite; - - public IBindable> Mods => mods; - - public bool Loading - { - set - { - if (value) - { - loading.Show(); - backgroundSprite.FadeColour(OsuColour.Gray(0.5f), 400, Easing.OutQuint); - } - else - { - loading.Hide(); - backgroundSprite.FadeColour(Color4.White, 400, Easing.OutQuint); - } - } - } - - public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Bindable> mods, Drawable facade) - { - this.beatmap = beatmap; - this.facade = facade; - - this.mods = new Bindable>(); - this.mods.BindTo(mods); - } - - [BackgroundDependencyLoader] - private void load() - { - var metadata = beatmap.BeatmapInfo?.Metadata ?? new BeatmapMetadata(); - - AutoSizeAxes = Axes.Both; - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Direction = FillDirection.Vertical, - Children = new[] - { - facade.With(d => - { - d.Anchor = Anchor.TopCentre; - d.Origin = Anchor.TopCentre; - }), - new OsuSpriteText - { - Text = new LocalisedString((metadata.TitleUnicode, metadata.Title)), - Font = OsuFont.GetFont(size: 36, italics: true), - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Margin = new MarginPadding { Top = 15 }, - }, - new OsuSpriteText - { - Text = new LocalisedString((metadata.ArtistUnicode, metadata.Artist)), - Font = OsuFont.GetFont(size: 26, italics: true), - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - }, - new Container - { - Size = new Vector2(300, 60), - Margin = new MarginPadding(10), - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - CornerRadius = 10, - Masking = true, - Children = new Drawable[] - { - backgroundSprite = new Sprite - { - RelativeSizeAxes = Axes.Both, - Texture = beatmap?.Background, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - FillMode = FillMode.Fill, - }, - loading = new LoadingAnimation { Scale = new Vector2(1.3f) } - } - }, - new OsuSpriteText - { - Text = beatmap?.BeatmapInfo?.Version, - Font = OsuFont.GetFont(size: 26, italics: true), - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Margin = new MarginPadding - { - Bottom = 40 - }, - }, - new MetadataLine("Source", metadata.Source) - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - }, - new MetadataLine("Mapper", metadata.AuthorString) - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - }, - new ModDisplay - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Top = 20 }, - Current = mods - } - }, - } - }; - - Loading = true; - } - } - private class MutedNotification : SimpleNotification { public MutedNotification() From b69d1ad678b9052091777aad6669ac4e643d3513 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 18:22:57 +0900 Subject: [PATCH 063/216] Reorder and clean up PlayerLoader --- osu.Game/Screens/Play/PlayerLoader.cs | 308 +++++++++++++------------- 1 file changed, 158 insertions(+), 150 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index ebc2422dc5..6e968de397 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -31,30 +31,60 @@ namespace osu.Game.Screens.Play { protected const float BACKGROUND_BLUR = 15; + public override bool HideOverlaysOnEnter => hideOverlays; + + public override bool DisallowExternalBeatmapRulesetChanges => true; + + // Here because IsHovered will not update unless we do so. + public override bool HandlePositionalInput => true; + + // We show the previous screen status + protected override UserActivity InitialActivity => null; + + protected override bool PlayResumeSound => false; + + protected BeatmapMetadataDisplay MetadataInfo; + + protected VisualSettings VisualSettings; + + protected Task LoadTask { get; private set; } + + protected Task DisposalTask { get; private set; } + + private bool backgroundBrightnessReduction; + + protected bool BackgroundBrightnessReduction + { + set + { + if (value == backgroundBrightnessReduction) + return; + + backgroundBrightnessReduction = value; + + Background.FadeColour(OsuColour.Gray(backgroundBrightnessReduction ? 0.8f : 1), 200); + } + } + + private bool readyForPush => + player.LoadState == LoadState.Ready && (IsHovered || idleTracker.IsIdle.Value) && inputManager?.DraggedDrawable == null; + private readonly Func createPlayer; private Player player; private LogoTrackingContainer content; - protected BeatmapMetadataDisplay MetadataInfo; - private bool hideOverlays; - public override bool HideOverlaysOnEnter => hideOverlays; - - protected override UserActivity InitialActivity => null; //shows the previous screen status - - public override bool DisallowExternalBeatmapRulesetChanges => true; - - protected override bool PlayResumeSound => false; - - protected Task LoadTask { get; private set; } - - protected Task DisposalTask { get; private set; } private InputManager inputManager; + private IdleTracker idleTracker; + private Bindable muteWarningShownOnce; + + private ScheduledDelegate scheduledPushPlayer; + [Resolved(CanBeNull = true)] private NotificationOverlay notificationOverlay { get; set; } @@ -64,19 +94,11 @@ namespace osu.Game.Screens.Play [Resolved] private AudioManager audioManager { get; set; } - private Bindable muteWarningShownOnce; - public PlayerLoader(Func createPlayer) { this.createPlayer = createPlayer; } - private void restartRequested() - { - hideOverlays = true; - ValidForResume = true; - } - [BackgroundDependencyLoader] private void load(SessionStatics sessionStatics) { @@ -124,7 +146,7 @@ namespace osu.Game.Screens.Play { base.OnEntering(last); - loadNewPlayer(); + prepareNewPlayer(); content.ScaleTo(0.7f); Background?.FadeColour(Color4.White, 800, Easing.OutQuint); @@ -153,36 +175,32 @@ namespace osu.Game.Screens.Play MetadataInfo.Loading = true; - //we will only be resumed if the player has requested a re-run (see ValidForResume setting above) - loadNewPlayer(); + // we will only be resumed if the player has requested a re-run (see restartRequested). + prepareNewPlayer(); this.Delay(400).Schedule(pushWhenLoaded); } - private void loadNewPlayer() + public override void OnSuspending(IScreen next) { - var restartCount = player?.RestartCount + 1 ?? 0; + base.OnSuspending(next); - player = createPlayer(); - player.RestartCount = restartCount; - player.RestartRequested = restartRequested; + cancelLoad(); - LoadTask = LoadComponentAsync(player, _ => MetadataInfo.Loading = false); + BackgroundBrightnessReduction = false; } - private void contentIn() + public override bool OnExiting(IScreen next) { - content.ScaleTo(1, 650, Easing.OutQuint); - content.FadeInFromZero(400); - } + cancelLoad(); - private void contentOut() - { - // Ensure the logo is no longer tracking before we scale the content - content.StopTracking(); + content.ScaleTo(0.7f, 150, Easing.InQuint); + this.FadeOut(150); - content.ScaleTo(0.7f, 300, Easing.InQuint); - content.FadeOut(250); + Background.EnableUserDim.Value = false; + BackgroundBrightnessReduction = false; + + return base.OnExiting(next); } protected override void LogoArriving(OsuLogo logo, bool resuming) @@ -191,10 +209,7 @@ namespace osu.Game.Screens.Play const double duration = 300; - if (!resuming) - { - logo.MoveTo(new Vector2(0.5f), duration, Easing.In); - } + if (!resuming) logo.MoveTo(new Vector2(0.5f), duration, Easing.In); logo.ScaleTo(new Vector2(0.15f), duration, Easing.In); logo.FadeIn(350); @@ -212,110 +227,6 @@ namespace osu.Game.Screens.Play content.StopTracking(); } - private ScheduledDelegate pushDebounce; - protected VisualSettings VisualSettings; - - // Here because IsHovered will not update unless we do so. - public override bool HandlePositionalInput => true; - - private bool readyForPush => player.LoadState == LoadState.Ready && (IsHovered || idleTracker.IsIdle.Value) && inputManager?.DraggedDrawable == null; - - private void pushWhenLoaded() - { - if (!this.IsCurrentScreen()) return; - - try - { - if (!readyForPush) - { - // as the pushDebounce below has a delay, we need to keep checking and cancel a future debounce - // if we become unready for push during the delay. - cancelLoad(); - return; - } - - if (pushDebounce != null) - return; - - pushDebounce = Scheduler.AddDelayed(() => - { - contentOut(); - - this.Delay(250).Schedule(() => - { - if (!this.IsCurrentScreen()) return; - - LoadTask = null; - - //By default, we want to load the player and never be returned to. - //Note that this may change if the player we load requested a re-run. - ValidForResume = false; - - if (player.LoadedBeatmapSuccessfully) - this.Push(player); - else - this.Exit(); - }); - }, 500); - } - finally - { - Schedule(pushWhenLoaded); - } - } - - private void cancelLoad() - { - pushDebounce?.Cancel(); - pushDebounce = null; - } - - public override void OnSuspending(IScreen next) - { - BackgroundBrightnessReduction = false; - base.OnSuspending(next); - cancelLoad(); - } - - public override bool OnExiting(IScreen next) - { - content.ScaleTo(0.7f, 150, Easing.InQuint); - this.FadeOut(150); - cancelLoad(); - - Background.EnableUserDim.Value = false; - BackgroundBrightnessReduction = false; - - return base.OnExiting(next); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - if (isDisposing) - { - // if the player never got pushed, we should explicitly dispose it. - DisposalTask = LoadTask?.ContinueWith(_ => player.Dispose()); - } - } - - private bool backgroundBrightnessReduction; - - protected bool BackgroundBrightnessReduction - { - get => backgroundBrightnessReduction; - set - { - if (value == backgroundBrightnessReduction) - return; - - backgroundBrightnessReduction = value; - - Background.FadeColour(OsuColour.Gray(backgroundBrightnessReduction ? 0.8f : 1), 200); - } - } - protected override void Update() { base.Update(); @@ -343,15 +254,112 @@ namespace osu.Game.Screens.Play } } + private void prepareNewPlayer() + { + var restartCount = player?.RestartCount + 1 ?? 0; + + player = createPlayer(); + player.RestartCount = restartCount; + player.RestartRequested = restartRequested; + + LoadTask = LoadComponentAsync(player, _ => MetadataInfo.Loading = false); + } + + private void restartRequested() + { + hideOverlays = true; + ValidForResume = true; + } + + private void contentIn() + { + content.ScaleTo(1, 650, Easing.OutQuint); + content.FadeInFromZero(400); + } + + private void contentOut() + { + // Ensure the logo is no longer tracking before we scale the content + content.StopTracking(); + + content.ScaleTo(0.7f, 300, Easing.InQuint); + content.FadeOut(250); + } + + private void pushWhenLoaded() + { + if (!this.IsCurrentScreen()) return; + + try + { + if (!readyForPush) + { + // as the pushDebounce below has a delay, we need to keep checking and cancel a future debounce + // if we become unready for push during the delay. + cancelLoad(); + return; + } + + if (scheduledPushPlayer != null) + return; + + scheduledPushPlayer = Scheduler.AddDelayed(() => + { + contentOut(); + + this.Delay(250).Schedule(() => + { + if (!this.IsCurrentScreen()) return; + + LoadTask = null; + + //By default, we want to load the player and never be returned to. + //Note that this may change if the player we load requested a re-run. + ValidForResume = false; + + if (player.LoadedBeatmapSuccessfully) + this.Push(player); + else + this.Exit(); + }); + }, 500); + } + finally + { + Schedule(pushWhenLoaded); + } + } + + private void cancelLoad() + { + scheduledPushPlayer?.Cancel(); + scheduledPushPlayer = null; + } + + #region Disposal + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (isDisposing) + { + // if the player never got pushed, we should explicitly dispose it. + DisposalTask = LoadTask?.ContinueWith(_ => player.Dispose()); + } + } + + #endregion + private class MutedNotification : SimpleNotification { + public override bool IsImportant => true; + public MutedNotification() { Text = "Your music volume is set to 0%! Click here to restore it."; } - public override bool IsImportant => true; - [BackgroundDependencyLoader] private void load(OsuColour colours, AudioManager audioManager, NotificationOverlay notificationOverlay, VolumeOverlay volumeOverlay) { From 2808f8167dd40866481315156fd3b1954614f6ef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 18:28:58 +0900 Subject: [PATCH 064/216] Use more regions --- osu.Game/Screens/Play/PlayerLoader.cs | 35 ++++++++++++++++++--------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 6e968de397..01873f7114 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -81,8 +81,6 @@ namespace osu.Game.Screens.Play private IdleTracker idleTracker; - private Bindable muteWarningShownOnce; - private ScheduledDelegate scheduledPushPlayer; [Resolved(CanBeNull = true)] @@ -142,6 +140,8 @@ namespace osu.Game.Screens.Play inputManager = GetContainingInputManager(); } + #region Screen handling + public override void OnEntering(IScreen last) { base.OnEntering(last); @@ -156,15 +156,7 @@ namespace osu.Game.Screens.Play MetadataInfo.Delay(750).FadeIn(500); this.Delay(1800).Schedule(pushWhenLoaded); - if (!muteWarningShownOnce.Value) - { - //Checks if the notification has not been shown yet and also if master volume is muted, track/music volume is muted or if the whole game is muted. - if (volumeOverlay?.IsMuted.Value == true || audioManager.Volume.Value <= audioManager.Volume.MinValue || audioManager.VolumeTrack.Value <= audioManager.VolumeTrack.MinValue) - { - notificationOverlay?.Post(new MutedNotification()); - muteWarningShownOnce.Value = true; - } - } + showMuteWarningIfNeeded(); } public override void OnResuming(IScreen last) @@ -227,6 +219,8 @@ namespace osu.Game.Screens.Play content.StopTracking(); } + #endregion + protected override void Update() { base.Update(); @@ -351,6 +345,23 @@ namespace osu.Game.Screens.Play #endregion + #region Mute warning + + private Bindable muteWarningShownOnce; + + private void showMuteWarningIfNeeded() + { + if (!muteWarningShownOnce.Value) + { + //Checks if the notification has not been shown yet and also if master volume is muted, track/music volume is muted or if the whole game is muted. + if (volumeOverlay?.IsMuted.Value == true || audioManager.Volume.Value <= audioManager.Volume.MinValue || audioManager.VolumeTrack.Value <= audioManager.VolumeTrack.MinValue) + { + notificationOverlay?.Post(new MutedNotification()); + muteWarningShownOnce.Value = true; + } + } + } + private class MutedNotification : SimpleNotification { public override bool IsImportant => true; @@ -378,5 +389,7 @@ namespace osu.Game.Screens.Play }; } } + + #endregion } } From 47325601f42a293d6b259e27489cfedf7b72e807 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 19:02:11 +0900 Subject: [PATCH 065/216] Add failing test --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 33ecbed62e..4f19067126 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -91,9 +91,44 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep("load dummy beatmap", () => ResetPlayer(false)); AddUntilStep("wait for current", () => loader.IsCurrentScreen()); - AddRepeatStep("move mouse", () => InputManager.MoveMouseTo(loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft + (loader.VisualSettings.ScreenSpaceDrawQuad.BottomRight - loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft) * RNG.NextSingle()), 20); + + AddUntilStep("wait for load ready", () => + { + moveMouse(); + return player.LoadState == LoadState.Ready; + }); + AddRepeatStep("move mouse", moveMouse, 20); + AddAssert("loader still active", () => loader.IsCurrentScreen()); AddUntilStep("loads after idle", () => !loader.IsCurrentScreen()); + + void moveMouse() + { + InputManager.MoveMouseTo( + loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft + + (loader.VisualSettings.ScreenSpaceDrawQuad.BottomRight - loader.VisualSettings.ScreenSpaceDrawQuad.TopLeft) + * RNG.NextSingle()); + } + } + + [Test] + public void TestBlockLoadViaFocus() + { + OsuFocusedOverlayContainer overlay = null; + + AddStep("load dummy beatmap", () => ResetPlayer(false)); + AddUntilStep("wait for current", () => loader.IsCurrentScreen()); + + AddStep("show focused overlay", () => { container.Add(overlay = new ChangelogOverlay { State = { Value = Visibility.Visible } }); }); + AddUntilStep("overlay visible", () => overlay.IsPresent); + + AddUntilStep("wait for load ready", () => player.LoadState == LoadState.Ready); + AddRepeatStep("twiddle thumbs", () => { }, 20); + + AddAssert("loader still active", () => loader.IsCurrentScreen()); + + AddStep("hide overlay", () => overlay.Hide()); + AddUntilStep("loads after idle", () => !loader.IsCurrentScreen()); } [Test] From 4d4ec3515d50bb184d33ab053d06b5d0ff17ca36 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 19:02:37 +0900 Subject: [PATCH 066/216] Fix player loading sequence continuing even when a priority overlay is visible --- osu.Game/Screens/Play/PlayerLoader.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 01873f7114..c0d88feda2 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -67,7 +67,14 @@ namespace osu.Game.Screens.Play } private bool readyForPush => - player.LoadState == LoadState.Ready && (IsHovered || idleTracker.IsIdle.Value) && inputManager?.DraggedDrawable == null; + // don't push unless the player is completely loaded + player.LoadState == LoadState.Ready + // don't push if the user is hovering one of the panes, unless they are idle. + && (IsHovered || idleTracker.IsIdle.Value) + // don't push if the user is dragging a slider or otherwise. + && inputManager?.DraggedDrawable == null + // don't push if a focused overlay is visible, like settings. + && inputManager?.FocusedDrawable == null; private readonly Func createPlayer; From 05c48cd92950b604cff21490f2ead15a91b15c78 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 19:27:32 +0900 Subject: [PATCH 067/216] Fix volume mute tests regressing --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 4f19067126..100f99d130 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -194,13 +194,22 @@ namespace osu.Game.Tests.Visual.Gameplay } [Test] - public void TestMutedNotificationMasterVolume() => addVolumeSteps("master volume", () => audioManager.Volume.Value = 0, null, () => audioManager.Volume.IsDefault); + public void TestMutedNotificationMasterVolume() + { + addVolumeSteps("master volume", () => audioManager.Volume.Value = 0, null, () => audioManager.Volume.IsDefault); + } [Test] - public void TestMutedNotificationTrackVolume() => addVolumeSteps("music volume", () => audioManager.VolumeTrack.Value = 0, null, () => audioManager.VolumeTrack.IsDefault); + public void TestMutedNotificationTrackVolume() + { + addVolumeSteps("music volume", () => audioManager.VolumeTrack.Value = 0, null, () => audioManager.VolumeTrack.IsDefault); + } [Test] - public void TestMutedNotificationMuteButton() => addVolumeSteps("mute button", null, () => container.VolumeOverlay.IsMuted.Value = true, () => !container.VolumeOverlay.IsMuted.Value); + public void TestMutedNotificationMuteButton() + { + addVolumeSteps("mute button", null, () => container.VolumeOverlay.IsMuted.Value = true, () => !container.VolumeOverlay.IsMuted.Value); + } /// /// Created for avoiding copy pasting code for the same steps. @@ -214,7 +223,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("reset notification lock", () => sessionStatics.GetBindable(Static.MutedAudioNotificationShownOnce).Value = false); AddStep("load player", () => ResetPlayer(false, beforeLoad, afterLoad)); - AddUntilStep("wait for player", () => player.IsLoaded); + AddUntilStep("wait for player", () => player.LoadState == LoadState.Ready); AddAssert("check for notification", () => container.NotificationOverlay.UnreadCount.Value == 1); AddStep("click notification", () => @@ -228,6 +237,8 @@ namespace osu.Game.Tests.Visual.Gameplay }); AddAssert("check " + volumeName, assert); + + AddUntilStep("wait for player load", () => player.IsLoaded); } private class TestPlayerLoaderContainer : Container From f31220c1ee7aaf3f559b73248961d79208a089d8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 19:56:01 +0900 Subject: [PATCH 068/216] Fix exception when adding duplicate items --- .../Visual/Multiplayer/TestSceneMatchSongSelect.cs | 8 ++++++++ osu.Game/Screens/Select/MatchSongSelect.cs | 2 ++ 2 files changed, 10 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs index 434b265f9c..5820da811d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs @@ -126,6 +126,14 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("playlist has 1 item", () => Room.Playlist.Count == 1); } + [Test] + public void TestAddSameItemMultipleTimes() + { + AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem()); + AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem()); + AddAssert("playlist has 2 items", () => Room.Playlist.Count == 2); + } + private class TestMatchSongSelect : MatchSongSelect { public new MatchBeatmapDetailArea BeatmapDetails => (MatchBeatmapDetailArea)base.BeatmapDetails; diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 4edc968e8a..cb0d09b6bb 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using Humanizer; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -53,6 +54,7 @@ namespace osu.Game.Screens.Select { PlaylistItem item = new PlaylistItem { + ID = (Playlist.LastOrDefault()?.ID + 1) ?? 0, Beatmap = { Value = Beatmap.Value.BeatmapInfo }, Ruleset = { Value = Ruleset.Value } }; From 1e80facfe8e67c03d83c3a0ca7c78e152097f3aa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 20:03:37 +0900 Subject: [PATCH 069/216] Add subscreen test scene --- .../Multiplayer/TestSceneMatchSubScreen.cs | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs new file mode 100644 index 0000000000..76d950b847 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs @@ -0,0 +1,87 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Game.Beatmaps; +using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets; +using osu.Game.Screens.Multi.Match; +using osu.Game.Screens.Multi.Match.Components; +using osu.Game.Screens.Select; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneMatchSubScreen : ScreenTestScene + { + protected override bool UseOnlineAPI => true; + + public override IReadOnlyList RequiredTypes => new[] + { + typeof(Screens.Multi.Multiplayer), + typeof(MatchSubScreen), + typeof(Header), + typeof(Footer) + }; + + [Cached] + private readonly Bindable currentRoom = new Bindable(); + + [Resolved] + private BeatmapManager beatmaps { get; set; } + + [Resolved] + private RulesetStore rulesets { get; set; } + + public TestSceneMatchSubScreen() + { + currentRoom.Value = new Room(); + } + + [Test] + public void TestShowRoom() + { + AddStep(@"show", () => + { + currentRoom.Value.RoomID.Value = 1; + currentRoom.Value.Availability.Value = RoomAvailability.Public; + currentRoom.Value.Duration.Value = TimeSpan.FromHours(24); + currentRoom.Value.Host.Value = new User { Username = "peppy", Id = 2 }; + currentRoom.Value.Name.Value = "super secret room"; + currentRoom.Value.Participants.AddRange(new[] + { + new User { Username = "peppy", Id = 2 }, + new User { Username = "smoogipoo", Id = 1040328 } + }); + currentRoom.Value.Playlist.Add(new PlaylistItem + { + Beatmap = { Value = beatmaps.GetAllUsableBeatmapSets()[0].Beatmaps[0] }, + Ruleset = { Value = rulesets.GetRuleset(2) }, + }); + + LoadScreen(new MatchSubScreen(currentRoom.Value)); + }); + } + + [Test] + public void TestShowSettings() + { + AddStep(@"show", () => + { + currentRoom.Value.RoomID.Value = null; + LoadScreen(new MatchSubScreen(currentRoom.Value)); + }); + } + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new CachedModelDependencyContainer(base.CreateChildDependencies(parent)); + dependencies.Model.BindTo(currentRoom); + return dependencies; + } + } +} From b0793b06edd594f452dbc2b788f8105927884f28 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 20:07:52 +0900 Subject: [PATCH 070/216] Re-implement the match header --- .../Multiplayer/TestSceneMatchBeatmapPanel.cs | 41 ----- .../Multiplayer/TestSceneMatchHeader.cs | 5 +- .../Visual/Multiplayer/TestSceneMatchInfo.cs | 84 --------- .../Screens/Multi/Match/Components/Header.cs | 174 +++++------------- .../Match/Components/MatchBeatmapPanel.cs | 67 ------- .../Multi/Match/Components/MatchPage.cs | 28 --- .../Multi/Match/Components/MatchTabControl.cs | 66 ------- .../Screens/Multi/Match/MatchSubScreen.cs | 24 --- 8 files changed, 44 insertions(+), 445 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs delete mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMatchInfo.cs delete mode 100644 osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs delete mode 100644 osu.Game/Screens/Multi/Match/Components/MatchPage.cs delete mode 100644 osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs deleted file mode 100644 index f014b08325..0000000000 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapPanel.cs +++ /dev/null @@ -1,41 +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 System; -using System.Collections.Generic; -using osu.Game.Beatmaps; -using osu.Game.Online.Multiplayer; -using osu.Game.Screens.Multi.Match.Components; -using osu.Framework.Graphics; -using osu.Game.Audio; -using osu.Framework.Allocation; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - [Cached(typeof(IPreviewTrackOwner))] - public class TestSceneMatchBeatmapPanel : MultiplayerTestScene, IPreviewTrackOwner - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(MatchBeatmapPanel) - }; - - [Resolved] - private PreviewTrackManager previewTrackManager { get; set; } - - public TestSceneMatchBeatmapPanel() - { - Add(new MatchBeatmapPanel - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }); - - Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = new BeatmapInfo { OnlineBeatmapID = 1763072 } } }); - Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = new BeatmapInfo { OnlineBeatmapID = 2101557 } } }); - Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = new BeatmapInfo { OnlineBeatmapID = 1973466 } } }); - Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = new BeatmapInfo { OnlineBeatmapID = 2109801 } } }); - Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = new BeatmapInfo { OnlineBeatmapID = 1922035 } } }); - } - } -} diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs index 7d7e7f85db..cf40995fc0 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs @@ -5,10 +5,10 @@ using System; using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; -using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.Multi.Match.Components; +using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { @@ -45,7 +45,8 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - Room.Type.Value = new GameTypeTimeshift(); + Room.Name.Value = "A very awesome room"; + Room.Host.Value = new User { Id = 2, Username = "peppy" }; Child = new Header(); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchInfo.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchInfo.cs deleted file mode 100644 index 6ee9ceb2dd..0000000000 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchInfo.cs +++ /dev/null @@ -1,84 +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 System; -using System.Collections.Generic; -using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Game.Beatmaps; -using osu.Game.Online.Multiplayer; -using osu.Game.Online.Multiplayer.RoomStatuses; -using osu.Game.Rulesets; -using osu.Game.Screens.Multi.Match.Components; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - [TestFixture] - public class TestSceneMatchInfo : MultiplayerTestScene - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(Info), - typeof(HeaderButton), - typeof(ReadyButton), - typeof(MatchBeatmapPanel) - }; - - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) - { - Add(new Info()); - - AddStep(@"set name", () => Room.Name.Value = @"Room Name?"); - AddStep(@"set availability", () => Room.Availability.Value = RoomAvailability.FriendsOnly); - AddStep(@"set status", () => Room.Status.Value = new RoomStatusPlaying()); - AddStep(@"set beatmap", () => - { - Room.Playlist.Clear(); - Room.Playlist.Add(new PlaylistItem - { - Beatmap = - { - Value = new BeatmapInfo - { - StarDifficulty = 2.4, - Ruleset = rulesets.GetRuleset(0), - Metadata = new BeatmapMetadata - { - Title = @"My Song", - Artist = @"VisualTests", - AuthorString = @"osu!lazer", - }, - } - } - }); - }); - - AddStep(@"change name", () => Room.Name.Value = @"Room Name!"); - AddStep(@"change availability", () => Room.Availability.Value = RoomAvailability.InviteOnly); - AddStep(@"change status", () => Room.Status.Value = new RoomStatusOpen()); - AddStep(@"null beatmap", () => Room.Playlist.Clear()); - AddStep(@"change beatmap", () => - { - Room.Playlist.Clear(); - Room.Playlist.Add(new PlaylistItem - { - Beatmap = - { - Value = new BeatmapInfo - { - StarDifficulty = 4.2, - Ruleset = rulesets.GetRuleset(3), - Metadata = new BeatmapMetadata - { - Title = @"Your Song", - Artist = @"Tester", - AuthorString = @"Someone", - }, - } - } - }); - }); - } - } -} diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index cf1eb6b6ed..ddbaab1706 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -1,39 +1,23 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; -using osu.Game.Online.Multiplayer; -using osu.Game.Overlays.SearchableList; -using osu.Game.Rulesets.Mods; -using osu.Game.Screens.Multi.Components; -using osu.Game.Screens.Play.HUD; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Users.Drawables; using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.Multi.Match.Components { public class Header : MultiplayerComposite { - public const float HEIGHT = 200; + public const float HEIGHT = 50; - public readonly BindableBool ShowBeatmapPanel = new BindableBool(); - - public MatchTabControl Tabs { get; private set; } - - public Action RequestBeatmapSelection; - - private MatchBeatmapPanel beatmapPanel; - private ModDisplay modDisplay; + private UpdateableAvatar avatar; + private LinkFlowContainer hostText; public Header() { @@ -44,128 +28,52 @@ namespace osu.Game.Screens.Multi.Match.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - BeatmapSelectButton beatmapButton; - - InternalChildren = new Drawable[] + InternalChild = new FillFlowContainer { - new Container + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Masking = true, - Children = new Drawable[] + avatar = new UpdateableAvatar { - new HeaderBackgroundSprite { RelativeSizeAxes = Axes.Both }, - new Box + Size = new Vector2(50), + Masking = true, + CornerRadius = 10, + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.7f), Color4.Black.Opacity(0.8f)), - }, - beatmapPanel = new MatchBeatmapPanel - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Margin = new MarginPadding { Right = 100 }, + new OsuSpriteText + { + Font = OsuFont.GetFont(size: 30), + Current = { BindTarget = RoomName } + }, + hostText = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold)) + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + } } } - }, - new Box - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Height = 1, - Colour = colours.Yellow - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING + OsuScreen.HORIZONTAL_OVERFLOW_PADDING }, - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = 20 }, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new BeatmapTypeInfo(), - modDisplay = new ModDisplay - { - Scale = new Vector2(0.75f), - DisplayUnrankedText = false - }, - } - }, - new Container - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.Y, - Width = 200, - Padding = new MarginPadding { Vertical = 10 }, - Child = beatmapButton = new BeatmapSelectButton - { - RelativeSizeAxes = Axes.Both, - Height = 1, - }, - }, - Tabs = new MatchTabControl - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X - }, - }, - }, + } }; - beatmapButton.Action = () => RequestBeatmapSelection?.Invoke(); - - Playlist.ItemsAdded += _ => updateMods(); - Playlist.ItemsRemoved += _ => updateMods(); - - updateMods(); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - ShowBeatmapPanel.BindValueChanged(value => beatmapPanel.FadeTo(value.NewValue ? 1 : 0, 200, Easing.OutQuint), true); - } - - private void updateMods() - { - var item = Playlist.FirstOrDefault(); - - modDisplay.Current.Value = item?.RequiredMods?.ToArray() ?? Array.Empty(); - } - - private class BeatmapSelectButton : HeaderButton - { - [Resolved(typeof(Room), nameof(Room.RoomID))] - private Bindable roomId { get; set; } - - public BeatmapSelectButton() + Host.BindValueChanged(host => { - Text = "Select beatmap"; - } + avatar.User = host.NewValue; - [BackgroundDependencyLoader] - private void load() - { - roomId.BindValueChanged(id => this.FadeTo(id.NewValue.HasValue ? 0 : 1), true); - } - } + hostText.Clear(); - private class HeaderBackgroundSprite : MultiplayerBackgroundSprite - { - protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BackgroundSprite { RelativeSizeAxes = Axes.Both }; - - private class BackgroundSprite : UpdateableBeatmapBackgroundSprite - { - protected override double TransformDuration => 200; - } + if (host.NewValue != null) + { + hostText.AddText("hosted by "); + hostText.AddUserLink(host.NewValue); + } + }, true); } } } diff --git a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs b/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs deleted file mode 100644 index c8de066caa..0000000000 --- a/osu.Game/Screens/Multi/Match/Components/MatchBeatmapPanel.cs +++ /dev/null @@ -1,67 +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 System.Linq; -using System.Threading; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; -using osu.Game.Overlays.Direct; -using osu.Game.Rulesets; - -namespace osu.Game.Screens.Multi.Match.Components -{ - public class MatchBeatmapPanel : MultiplayerComposite - { - [Resolved] - private IAPIProvider api { get; set; } - - [Resolved] - private RulesetStore rulesets { get; set; } - - private CancellationTokenSource loadCancellation; - private GetBeatmapSetRequest request; - private DirectGridPanel panel; - - public MatchBeatmapPanel() - { - AutoSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader] - private void load() - { - Playlist.ItemsAdded += _ => loadNewPanel(); - Playlist.ItemsRemoved += _ => loadNewPanel(); - - loadNewPanel(); - } - - private void loadNewPanel() - { - loadCancellation?.Cancel(); - request?.Cancel(); - - panel?.FadeOut(200); - panel?.Expire(); - panel = null; - - var beatmap = Playlist.FirstOrDefault()?.Beatmap.Value; - - if (beatmap?.OnlineBeatmapID == null) - return; - - loadCancellation = new CancellationTokenSource(); - - request = new GetBeatmapSetRequest(beatmap.OnlineBeatmapID.Value, BeatmapSetLookupType.BeatmapId); - request.Success += res => Schedule(() => - { - panel = new DirectGridPanel(res.ToBeatmapSet(rulesets)); - LoadComponentAsync(panel, AddInternal, loadCancellation.Token); - }); - - api.Queue(request); - } - } -} diff --git a/osu.Game/Screens/Multi/Match/Components/MatchPage.cs b/osu.Game/Screens/Multi/Match/Components/MatchPage.cs deleted file mode 100644 index fc98db157b..0000000000 --- a/osu.Game/Screens/Multi/Match/Components/MatchPage.cs +++ /dev/null @@ -1,28 +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.Bindables; - -namespace osu.Game.Screens.Multi.Match.Components -{ - public abstract class MatchPage - { - public abstract string Name { get; } - - public readonly BindableBool Enabled = new BindableBool(true); - - public override string ToString() => Name; - public override int GetHashCode() => GetType().GetHashCode(); - public override bool Equals(object obj) => GetType() == obj?.GetType(); - } - - public class SettingsMatchPage : MatchPage - { - public override string Name => "Settings"; - } - - public class RoomMatchPage : MatchPage - { - public override string Name => "Room"; - } -} diff --git a/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs deleted file mode 100644 index c700d7b88a..0000000000 --- a/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs +++ /dev/null @@ -1,66 +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.Bindables; -using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input.Events; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.Multiplayer; -using osuTK.Graphics; - -namespace osu.Game.Screens.Multi.Match.Components -{ - public class MatchTabControl : PageTabControl - { - [Resolved(typeof(Room), nameof(Room.RoomID))] - private Bindable roomId { get; set; } - - public MatchTabControl() - { - AddItem(new RoomMatchPage()); - AddItem(new SettingsMatchPage()); - } - - [BackgroundDependencyLoader] - private void load() - { - roomId.BindValueChanged(id => - { - if (id.NewValue.HasValue) - { - Items.ForEach(t => t.Enabled.Value = !(t is SettingsMatchPage)); - Current.Value = new RoomMatchPage(); - } - else - { - Items.ForEach(t => t.Enabled.Value = t is SettingsMatchPage); - Current.Value = new SettingsMatchPage(); - } - }, true); - } - - protected override TabItem CreateTabItem(MatchPage value) => new TabItem(value); - - private class TabItem : PageTabItem - { - private readonly IBindable enabled = new BindableBool(); - - public TabItem(MatchPage value) - : base(value) - { - enabled.BindTo(value.Enabled); - enabled.BindValueChanged(enabled => Colour = enabled.NewValue ? Color4.White : Color4.Gray, true); - } - - protected override bool OnClick(ClickEvent e) - { - if (!enabled.Value) - return true; - - return base.OnClick(e); - } - } - } -} diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 890664e99b..ed1cb987c2 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -15,7 +15,6 @@ using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Play; -using osu.Game.Screens.Select; using PlaylistItem = osu.Game.Online.Multiplayer.PlaylistItem; namespace osu.Game.Screens.Multi.Match @@ -78,17 +77,6 @@ namespace osu.Game.Screens.Multi.Match header = new Components.Header { Depth = -1, - RequestBeatmapSelection = () => - { - this.Push(new MatchSongSelect - { - Selected = item => - { - Playlist.Clear(); - Playlist.Add(item); - } - }); - } } }, new Drawable[] { info = new Info { OnStart = onStart } }, @@ -145,18 +133,6 @@ namespace osu.Game.Screens.Multi.Match }, }; - header.Tabs.Current.BindValueChanged(tab => - { - const float fade_duration = 500; - - var settingsDisplayed = tab.NewValue is SettingsMatchPage; - - header.ShowBeatmapPanel.Value = !settingsDisplayed; - settings.State.Value = settingsDisplayed ? Visibility.Visible : Visibility.Hidden; - info.FadeTo(settingsDisplayed ? 0 : 1, fade_duration, Easing.OutQuint); - bottomRow.FadeTo(settingsDisplayed ? 0 : 1, fade_duration, Easing.OutQuint); - }, true); - beatmapManager.ItemAdded += beatmapAdded; } From 73621e41fd7b4f4164d5a316ca0d13b5cf267229 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 14 Feb 2020 20:12:23 +0900 Subject: [PATCH 071/216] Forcefully hide mute notification for navigation tests --- osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs b/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs index 8d2e4a614d..70d71d0952 100644 --- a/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs +++ b/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs @@ -117,6 +117,8 @@ namespace osu.Game.Tests.Visual.Navigation { base.LoadComplete(); API.Login("Rhythm Champion", "osu!"); + + Dependencies.Get().Set(Static.MutedAudioNotificationShownOnce, true); } } From c0dba632787246a7ef98b56fcf561dc827eb885f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 20:14:25 +0900 Subject: [PATCH 072/216] Remove match info --- .../Multiplayer/TestSceneMatchHostInfo.cs | 35 ------ .../Multiplayer/TestSceneMatchParticipants.cs | 52 --------- .../Multi/Match/Components/HeaderButton.cs | 47 -------- .../Multi/Match/Components/HostInfo.cs | 61 ---------- .../Screens/Multi/Match/Components/Info.cs | 107 ------------------ .../Multi/Match/Components/Participants.cs | 77 ------------- .../Multi/Match/Components/ReadyButton.cs | 3 +- .../Screens/Multi/Match/MatchSubScreen.cs | 2 - 8 files changed, 2 insertions(+), 382 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHostInfo.cs delete mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMatchParticipants.cs delete mode 100644 osu.Game/Screens/Multi/Match/Components/HeaderButton.cs delete mode 100644 osu.Game/Screens/Multi/Match/Components/HostInfo.cs delete mode 100644 osu.Game/Screens/Multi/Match/Components/Info.cs delete mode 100644 osu.Game/Screens/Multi/Match/Components/Participants.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHostInfo.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHostInfo.cs deleted file mode 100644 index 808a45cdf0..0000000000 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHostInfo.cs +++ /dev/null @@ -1,35 +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 System; -using System.Collections.Generic; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Game.Screens.Multi.Match.Components; -using osu.Game.Users; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - public class TestSceneMatchHostInfo : OsuTestScene - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(HostInfo) - }; - - private readonly Bindable host = new Bindable(new User { Username = "SomeHost" }); - - public TestSceneMatchHostInfo() - { - HostInfo hostInfo; - - Child = hostInfo = new HostInfo - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre - }; - - hostInfo.Host.BindTo(host); - } - } -} diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchParticipants.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchParticipants.cs deleted file mode 100644 index a6f47961e9..0000000000 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchParticipants.cs +++ /dev/null @@ -1,52 +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 NUnit.Framework; -using osu.Framework.Graphics; -using osu.Game.Screens.Multi.Match.Components; -using osu.Game.Users; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - [TestFixture] - public class TestSceneMatchParticipants : MultiplayerTestScene - { - public TestSceneMatchParticipants() - { - Add(new Participants { RelativeSizeAxes = Axes.Both }); - - AddStep(@"set max to null", () => Room.MaxParticipants.Value = null); - AddStep(@"set users", () => Room.Participants.AddRange(new[] - { - new User - { - Username = @"Feppla", - Id = 4271601, - Country = new Country { FlagName = @"SE" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c2.jpg", - IsSupporter = true, - }, - new User - { - Username = @"Xilver", - Id = 3099689, - Country = new Country { FlagName = @"IL" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c2.jpg", - IsSupporter = true, - }, - new User - { - Username = @"Wucki", - Id = 5287410, - Country = new Country { FlagName = @"FI" }, - CoverUrl = @"https://assets.ppy.sh/user-profile-covers/5287410/5cfeaa9dd41cbce038ecdc9d781396ed4b0108089170bf7f50492ef8eadeb368.jpeg", - IsSupporter = true, - }, - })); - - AddStep(@"set max", () => Room.MaxParticipants.Value = 10); - AddStep(@"clear users", () => Room.Participants.Clear()); - AddStep(@"set max to null", () => Room.MaxParticipants.Value = null); - } - } -} diff --git a/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs b/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs deleted file mode 100644 index de6ece6a05..0000000000 --- a/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs +++ /dev/null @@ -1,47 +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 osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; - -namespace osu.Game.Screens.Multi.Match.Components -{ - public class HeaderButton : TriangleButton - { - [BackgroundDependencyLoader] - private void load() - { - BackgroundColour = OsuColour.FromHex(@"1187aa"); - - Triangles.ColourLight = OsuColour.FromHex(@"277b9c"); - Triangles.ColourDark = OsuColour.FromHex(@"1f6682"); - Triangles.TriangleScale = 1.5f; - - Add(new Container - { - RelativeSizeAxes = Axes.Both, - Alpha = 1f, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.15f, - Blending = BlendingParameters.Additive, - }, - }); - } - - protected override SpriteText CreateText() => new OsuSpriteText - { - Depth = -1, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Font = OsuFont.GetFont(weight: FontWeight.Light, size: 30), - }; - } -} diff --git a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs deleted file mode 100644 index 8851a96605..0000000000 --- a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs +++ /dev/null @@ -1,61 +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.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Users; -using osu.Game.Users.Drawables; -using osuTK; - -namespace osu.Game.Screens.Multi.Match.Components -{ - public class HostInfo : CompositeDrawable - { - public readonly IBindable Host = new Bindable(); - - private readonly LinkFlowContainer linkContainer; - private readonly UpdateableAvatar avatar; - - public HostInfo() - { - AutoSizeAxes = Axes.X; - Height = 50; - - InternalChild = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5, 0), - Children = new Drawable[] - { - avatar = new UpdateableAvatar { Size = new Vector2(50) }, - new FillFlowContainer - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Child = linkContainer = new LinkFlowContainer { AutoSizeAxes = Axes.Both } - } - } - }; - - Host.BindValueChanged(host => updateHost(host.NewValue)); - } - - private void updateHost(User host) - { - avatar.User = host; - - if (host != null) - { - linkContainer.AddText("hosted by"); - linkContainer.NewLine(); - linkContainer.AddUserLink(host, s => s.Font = s.Font.With(Typeface.Exo, weight: FontWeight.Bold, italics: true)); - } - } - } -} diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs deleted file mode 100644 index a320b08cc4..0000000000 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ /dev/null @@ -1,107 +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 System; -using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Overlays.SearchableList; -using osu.Game.Screens.Multi.Components; -using osuTK; - -namespace osu.Game.Screens.Multi.Match.Components -{ - public class Info : MultiplayerComposite - { - public Action OnStart; - - private ReadyButton readyButton; - - public Info() - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - } - - [BackgroundDependencyLoader] - private void load() - { - HostInfo hostInfo; - - InternalChildren = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"28242d"), - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING + OsuScreen.HORIZONTAL_OVERFLOW_PADDING }, - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 10), - Padding = new MarginPadding { Vertical = 20 }, - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new OsuSpriteText - { - Font = OsuFont.GetFont(size: 30), - Current = RoomName - }, - new RoomStatusInfo(), - } - }, - hostInfo = new HostInfo(), - }, - }, - new FillFlowContainer - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.X, - Height = 70, - Spacing = new Vector2(10, 0), - Direction = FillDirection.Horizontal, - Children = new Drawable[] - { - readyButton = new ReadyButton - { - Action = () => OnStart?.Invoke() - } - } - } - }, - }, - }; - - hostInfo.Host.BindTo(Host); - - Playlist.ItemsAdded += _ => updateBeatmap(); - Playlist.ItemsRemoved += _ => updateBeatmap(); - - updateBeatmap(); - } - - private void updateBeatmap() - { - readyButton.Beatmap.Value = Playlist.FirstOrDefault()?.Beatmap.Value; - } - } -} diff --git a/osu.Game/Screens/Multi/Match/Components/Participants.cs b/osu.Game/Screens/Multi/Match/Components/Participants.cs deleted file mode 100644 index 00d2f3e150..0000000000 --- a/osu.Game/Screens/Multi/Match/Components/Participants.cs +++ /dev/null @@ -1,77 +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 System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics.Containers; -using osu.Game.Overlays.SearchableList; -using osu.Game.Screens.Multi.Components; -using osu.Game.Users; -using osuTK; - -namespace osu.Game.Screens.Multi.Match.Components -{ - public class Participants : MultiplayerComposite - { - [BackgroundDependencyLoader] - private void load() - { - FillFlowContainer usersFlow; - - InternalChild = new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, - Children = new Drawable[] - { - new OsuScrollContainer - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = 10 }, - Children = new Drawable[] - { - new ParticipantCountDisplay - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - }, - usersFlow = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(5), - Padding = new MarginPadding { Top = 40 }, - LayoutDuration = 200, - LayoutEasing = Easing.OutQuint, - }, - }, - }, - }, - }; - - Participants.ItemsAdded += users => - { - usersFlow.AddRange(users.Select(u => - { - var panel = new UserPanel(u) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Width = 300, - }; - - panel.OnLoadComplete += d => d.FadeInFromZero(60); - - return panel; - }).ToList()); - }; - - Participants.ItemsRemoved += users => - { - usersFlow.RemoveAll(p => users.Contains(p.User)); - }; - } - } -} diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index 8ab0b8f61f..cec5b2f855 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -7,12 +7,13 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osuTK; namespace osu.Game.Screens.Multi.Match.Components { - public class ReadyButton : HeaderButton + public class ReadyButton : OsuButton { public readonly Bindable Beatmap = new Bindable(); diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index ed1cb987c2..07da707724 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -61,7 +61,6 @@ namespace osu.Game.Screens.Multi.Match private void load() { Components.Header header; - Info info; GridContainer bottomRow; MatchSettingsOverlay settings; @@ -79,7 +78,6 @@ namespace osu.Game.Screens.Multi.Match Depth = -1, } }, - new Drawable[] { info = new Info { OnStart = onStart } }, new Drawable[] { bottomRow = new GridContainer From 80fd9485a9681b5c092860be6625c7495b111f22 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 20:18:53 +0900 Subject: [PATCH 073/216] Refactor ready button to support selected playlist item --- .../Multi/Match/Components/ReadyButton.cs | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index cec5b2f855..a62572a851 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Multi.Match.Components { public class ReadyButton : OsuButton { - public readonly Bindable Beatmap = new Bindable(); + public readonly Bindable SelectedItem = new Bindable(); [Resolved(typeof(Room), nameof(Room.EndDate))] private Bindable endDate { get; set; } @@ -42,31 +42,37 @@ namespace osu.Game.Screens.Multi.Match.Components beatmaps.ItemAdded += beatmapAdded; beatmaps.ItemRemoved += beatmapRemoved; - Beatmap.BindValueChanged(b => updateBeatmap(b.NewValue), true); + SelectedItem.BindValueChanged(item => updateSelectedItem(item.NewValue), true); } - private void updateBeatmap(BeatmapInfo beatmap) + private void updateSelectedItem(PlaylistItem item) { hasBeatmap = false; - if (beatmap?.OnlineBeatmapID == null) + int? beatmapId = SelectedItem.Value?.Beatmap.Value?.OnlineBeatmapID; + if (beatmapId == null) return; - hasBeatmap = beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID) != null; + hasBeatmap = beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == beatmapId) != null; } private void beatmapAdded(BeatmapSetInfo model) { - if (model.Beatmaps.Any(b => b.OnlineBeatmapID == Beatmap.Value.OnlineBeatmapID)) + int? beatmapId = SelectedItem.Value?.Beatmap.Value?.OnlineBeatmapID; + if (beatmapId == null) + return; + + if (model.Beatmaps.Any(b => b.OnlineBeatmapID == beatmapId)) Schedule(() => hasBeatmap = true); } private void beatmapRemoved(BeatmapSetInfo model) { - if (Beatmap.Value == null) + int? beatmapId = SelectedItem.Value?.Beatmap.Value?.OnlineBeatmapID; + if (beatmapId == null) return; - if (model.OnlineBeatmapSetID == Beatmap.Value.BeatmapSet.OnlineBeatmapSetID) + if (model.Beatmaps.Any(b => b.OnlineBeatmapID == beatmapId)) Schedule(() => hasBeatmap = false); } @@ -79,7 +85,7 @@ namespace osu.Game.Screens.Multi.Match.Components private void updateEnabledState() { - if (gameBeatmap.Value == null) + if (gameBeatmap.Value == null || SelectedItem.Value == null) { Enabled.Value = false; return; @@ -95,7 +101,10 @@ namespace osu.Game.Screens.Multi.Match.Components base.Dispose(isDisposing); if (beatmaps != null) + { beatmaps.ItemAdded -= beatmapAdded; + beatmaps.ItemRemoved -= beatmapRemoved; + } } } } From c75a7742977122303c59de7bc036b7310238fec9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 20:27:37 +0900 Subject: [PATCH 074/216] Extract participants list from the room inspector --- .../Multiplayer/TestSceneParticipantsList.cs | 20 +++ .../Multi/Components/ParticipantsList.cs | 119 ++++++++++++++++++ .../Multi/Lounge/Components/RoomInspector.cs | 113 +---------------- 3 files changed, 142 insertions(+), 110 deletions(-) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs create mode 100644 osu.Game/Screens/Multi/Components/ParticipantsList.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs new file mode 100644 index 0000000000..9c4c45f94a --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs @@ -0,0 +1,20 @@ +// 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.Game.Screens.Multi.Components; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneParticipantsList : MultiplayerTestScene + { + protected override bool UseOnlineAPI => true; + + public TestSceneParticipantsList() + { + Room.RoomID.Value = 7; + + Add(new ParticipantsList { RelativeSizeAxes = Axes.Both }); + } + } +} diff --git a/osu.Game/Screens/Multi/Components/ParticipantsList.cs b/osu.Game/Screens/Multi/Components/ParticipantsList.cs new file mode 100644 index 0000000000..2ef36b2795 --- /dev/null +++ b/osu.Game/Screens/Multi/Components/ParticipantsList.cs @@ -0,0 +1,119 @@ +// Copyright (c) ppy Pty Ltd . 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Users; +using osu.Game.Users.Drawables; +using osuTK; + +namespace osu.Game.Screens.Multi.Components +{ + public class ParticipantsList : MultiplayerComposite + { + private readonly FillFlowContainer fill; + + public ParticipantsList() + { + InternalChild = new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = fill = new FillFlowContainer + { + Spacing = new Vector2(10), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Full, + } + }; + } + + [BackgroundDependencyLoader] + private void load() + { + RoomID.BindValueChanged(_ => updateParticipants(), true); + } + + [Resolved] + private IAPIProvider api { get; set; } + + private GetRoomScoresRequest request; + + private void updateParticipants() + { + var roomId = RoomID.Value ?? 0; + + request?.Cancel(); + + // nice little progressive fade + int time = 500; + + foreach (var c in fill.Children) + { + c.Delay(500 - time).FadeOut(time, Easing.Out); + time = Math.Max(20, time - 20); + c.Expire(); + } + + if (roomId == 0) return; + + request = new GetRoomScoresRequest(roomId); + request.Success += scores => Schedule(() => + { + if (roomId != RoomID.Value) + return; + + fill.Clear(); + foreach (var s in scores) + fill.Add(new UserTile(s.User)); + + fill.FadeInFromZero(1000, Easing.OutQuint); + }); + + api.Queue(request); + } + + protected override void Dispose(bool isDisposing) + { + request?.Cancel(); + base.Dispose(isDisposing); + } + + private class UserTile : CompositeDrawable, IHasTooltip + { + private readonly User user; + + public string TooltipText => user.Username; + + public UserTile(User user) + { + this.user = user; + Size = new Vector2(70f); + CornerRadius = 5f; + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"27252d"), + }, + new UpdateableAvatar + { + RelativeSizeAxes = Axes.Both, + User = user, + }, + }; + } + } + } +} diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 5030d8cb50..cb6bbf6731 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -1,25 +1,18 @@ // Copyright (c) ppy Pty Ltd . 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.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Components; -using osu.Game.Users; -using osu.Game.Users.Drawables; using osuTK; using osuTK.Graphics; @@ -160,9 +153,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components }, new Drawable[] { - new MatchParticipants + new Container { RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = 10 }, + Child = new ParticipantsList { RelativeSizeAxes = Axes.Both } } } } @@ -219,107 +214,5 @@ namespace osu.Game.Screens.Multi.Lounge.Components status.BindValueChanged(s => Text = s.NewValue.Message, true); } } - - private class MatchParticipants : MultiplayerComposite - { - private readonly FillFlowContainer fill; - - public MatchParticipants() - { - Padding = new MarginPadding { Horizontal = 10 }; - - InternalChild = new OsuScrollContainer - { - RelativeSizeAxes = Axes.Both, - Child = fill = new FillFlowContainer - { - Spacing = new Vector2(10), - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Full, - } - }; - } - - [BackgroundDependencyLoader] - private void load() - { - RoomID.BindValueChanged(_ => updateParticipants(), true); - } - - [Resolved] - private IAPIProvider api { get; set; } - - private GetRoomScoresRequest request; - - private void updateParticipants() - { - var roomId = RoomID.Value ?? 0; - - request?.Cancel(); - - // nice little progressive fade - int time = 500; - - foreach (var c in fill.Children) - { - c.Delay(500 - time).FadeOut(time, Easing.Out); - time = Math.Max(20, time - 20); - c.Expire(); - } - - if (roomId == 0) return; - - request = new GetRoomScoresRequest(roomId); - request.Success += scores => - { - if (roomId != RoomID.Value) - return; - - fill.Clear(); - foreach (var s in scores) - fill.Add(new UserTile(s.User)); - - fill.FadeInFromZero(1000, Easing.OutQuint); - }; - - api.Queue(request); - } - - protected override void Dispose(bool isDisposing) - { - request?.Cancel(); - base.Dispose(isDisposing); - } - - private class UserTile : CompositeDrawable, IHasTooltip - { - private readonly User user; - - public string TooltipText => user.Username; - - public UserTile(User user) - { - this.user = user; - Size = new Vector2(70f); - CornerRadius = 5f; - Masking = true; - - InternalChildren = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"27252d"), - }, - new UpdateableAvatar - { - RelativeSizeAxes = Axes.Both, - User = user, - }, - }; - } - } - } } } From d5496321e2cf8dfaf0c254460786d25d0bacac8b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 20:31:55 +0900 Subject: [PATCH 075/216] Implement leaderboard chat display --- .../TestSceneMatchLeaderboardChatDisplay.cs | 39 +++++++ .../Components/LeaderboardChatDisplay.cs | 100 ++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboardChatDisplay.cs create mode 100644 osu.Game/Screens/Multi/Match/Components/LeaderboardChatDisplay.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboardChatDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboardChatDisplay.cs new file mode 100644 index 0000000000..e46386b263 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboardChatDisplay.cs @@ -0,0 +1,39 @@ +// Copyright (c) ppy Pty Ltd . 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Screens.Multi.Match.Components; +using osuTK; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneMatchLeaderboardChatDisplay : MultiplayerTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(LeaderboardChatDisplay) + }; + + protected override bool UseOnlineAPI => true; + + public TestSceneMatchLeaderboardChatDisplay() + { + Room.RoomID.Value = 7; + + Add(new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(500), + Child = new LeaderboardChatDisplay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }); + } + } +} diff --git a/osu.Game/Screens/Multi/Match/Components/LeaderboardChatDisplay.cs b/osu.Game/Screens/Multi/Match/Components/LeaderboardChatDisplay.cs new file mode 100644 index 0000000000..de02b7f605 --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/LeaderboardChatDisplay.cs @@ -0,0 +1,100 @@ +// 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.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public class LeaderboardChatDisplay : MultiplayerComposite + { + private const double fade_duration = 100; + + private readonly OsuTabControl tabControl; + private readonly MatchLeaderboard leaderboard; + private readonly MatchChatDisplay chat; + + public LeaderboardChatDisplay() + { + RelativeSizeAxes = Axes.Both; + + InternalChild = new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + tabControl = new DisplayModeTabControl + { + RelativeSizeAxes = Axes.X, + Height = 24, + } + }, + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 10 }, + Children = new Drawable[] + { + leaderboard = new MatchLeaderboard { RelativeSizeAxes = Axes.Both }, + chat = new MatchChatDisplay + { + RelativeSizeAxes = Axes.Both, + Alpha = 0 + } + } + } + }, + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + tabControl.AccentColour = colours.Yellow; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + tabControl.Current.BindValueChanged(changeTab); + } + + public void RefreshScores() => leaderboard.RefreshScores(); + + private void changeTab(ValueChangedEvent mode) + { + chat.FadeTo(mode.NewValue == DisplayMode.Chat ? 1 : 0, fade_duration); + leaderboard.FadeTo(mode.NewValue == DisplayMode.Leaderboard ? 1 : 0, fade_duration); + } + + private class DisplayModeTabControl : OsuTabControl + { + protected override TabItem CreateTabItem(DisplayMode value) => base.CreateTabItem(value).With(d => + { + d.Anchor = Anchor.Centre; + d.Origin = Anchor.Centre; + }); + } + + private enum DisplayMode + { + Leaderboard, + Chat, + } + } +} From d0b7b7f53a2892571f25c0daee83e229e40420a9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 20:34:15 +0900 Subject: [PATCH 076/216] Re-layout match settings overlay --- .../Match/Components/MatchSettingsOverlay.cs | 58 +++++++++++++++---- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index 410aaed788..776de424ab 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -25,6 +25,8 @@ namespace osu.Game.Screens.Multi.Match.Components private const float transition_duration = 350; private const float field_padding = 45; + public Action EditPlaylist; + protected MatchSettings Settings { get; private set; } [BackgroundDependencyLoader] @@ -35,7 +37,8 @@ namespace osu.Game.Screens.Multi.Match.Components Child = Settings = new MatchSettings { RelativeSizeAxes = Axes.Both, - RelativePositionAxes = Axes.Y + RelativePositionAxes = Axes.Y, + EditPlaylist = () => EditPlaylist?.Invoke() }; } @@ -53,6 +56,8 @@ namespace osu.Game.Screens.Multi.Match.Components { private const float disabled_alpha = 0.2f; + public Action EditPlaylist; + public OsuTextBox NameField, MaxParticipantsField; public OsuDropdown DurationField; public RoomAvailabilityPicker AvailabilityPicker; @@ -63,6 +68,7 @@ namespace osu.Game.Screens.Multi.Match.Components private OsuSpriteText typeLabel; private ProcessingOverlay processingOverlay; + private DrawableRoomPlaylist playlist; [Resolved(CanBeNull = true)] private IRoomManager manager { get; set; } @@ -155,15 +161,6 @@ namespace osu.Game.Screens.Multi.Match.Components }, }, }, - }, - }, - new SectionContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Padding = new MarginPadding { Left = field_padding / 2 }, - Children = new[] - { new Section("Max participants") { Alpha = disabled_alpha, @@ -208,6 +205,45 @@ namespace osu.Game.Screens.Multi.Match.Components }, }, }, + new SectionContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Padding = new MarginPadding { Left = field_padding / 2 }, + Children = new[] + { + new Section("Playlist") + { + Child = new GridContainer + { + RelativeSizeAxes = Axes.X, + Height = 300, + Content = new[] + { + new Drawable[] + { + playlist = new DrawableRoomPlaylist(true, true) { RelativeSizeAxes = Axes.Both } + }, + new Drawable[] + { + new OsuButton + { + RelativeSizeAxes = Axes.X, + Height = 40, + Text = "Edit playlist", + Action = () => EditPlaylist?.Invoke() + } + } + }, + RowDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + } + } + }, + }, + }, }, } }, @@ -271,6 +307,8 @@ namespace osu.Game.Screens.Multi.Match.Components Type.BindValueChanged(type => TypePicker.Current.Value = type.NewValue, true); MaxParticipants.BindValueChanged(count => MaxParticipantsField.Text = count.NewValue?.ToString(), true); Duration.BindValueChanged(duration => DurationField.Current.Value = duration.NewValue, true); + + playlist.Items.BindTo(Playlist); } protected override void Update() From 929eb4f035d00a0d7b32b602c266685dec374afc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 20:35:52 +0900 Subject: [PATCH 077/216] Add match footer --- .../Multiplayer/TestSceneMatchSubScreen.cs | 1 - .../Screens/Multi/Match/Components/Footer.cs | 53 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Screens/Multi/Match/Components/Footer.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs index 76d950b847..61def4be1a 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs @@ -11,7 +11,6 @@ using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Screens.Multi.Match; using osu.Game.Screens.Multi.Match.Components; -using osu.Game.Screens.Select; using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer diff --git a/osu.Game/Screens/Multi/Match/Components/Footer.cs b/osu.Game/Screens/Multi/Match/Components/Footer.cs new file mode 100644 index 0000000000..93430d9131 --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/Footer.cs @@ -0,0 +1,53 @@ +// Copyright (c) ppy Pty Ltd . 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; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Multiplayer; +using osuTK; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public class Footer : CompositeDrawable + { + public const float HEIGHT = 100; + + public Action OnStart; + public readonly Bindable SelectedItem = new Bindable(); + + private readonly Drawable background; + private readonly OsuButton startButton; + + public Footer() + { + RelativeSizeAxes = Axes.X; + Height = HEIGHT; + + InternalChildren = new[] + { + background = new Box { RelativeSizeAxes = Axes.Both }, + startButton = new ReadyButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(600, 50), + SelectedItem = { BindTarget = SelectedItem }, + Action = () => OnStart?.Invoke() + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = OsuColour.FromHex(@"28242d"); + startButton.BackgroundColour = colours.Green; + } + } +} From 6d87d22a84abb31ac09aa0d311b2dc2c84616486 Mon Sep 17 00:00:00 2001 From: recapitalverb <41869184+recapitalverb@users.noreply.github.com> Date: Fri, 14 Feb 2020 18:40:58 +0700 Subject: [PATCH 078/216] Remove duplicated dependency on AudioManager --- osu.Game/Screens/Menu/IntroTriangles.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index 50cfe23481..4deaa68467 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Menu private SampleChannel welcome; [BackgroundDependencyLoader] - private void load(AudioManager audio) + private void load() { if (MenuVoice.Value && !MenuMusic.Value) welcome = audio.Samples.Get(@"welcome"); From b762e5e8a5f48ce0d098ba79d2b6e50ec5946186 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 20:42:14 +0900 Subject: [PATCH 079/216] Implement overlined components --- .../TestSceneOverlinedParticipants.cs | 28 ++++++ .../Multiplayer/TestSceneOverlinedPlaylist.cs | 39 +++++++++ .../Match/Components/OverlinedDisplay.cs | 87 +++++++++++++++++++ .../Match/Components/OverlinedParticipants.cs | 29 +++++++ .../Match/Components/OverlinedPlaylist.cs | 33 +++++++ 5 files changed, 216 insertions(+) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs create mode 100644 osu.Game/Screens/Multi/Match/Components/OverlinedDisplay.cs create mode 100644 osu.Game/Screens/Multi/Match/Components/OverlinedParticipants.cs create mode 100644 osu.Game/Screens/Multi/Match/Components/OverlinedPlaylist.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs new file mode 100644 index 0000000000..e07ebc1454 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs @@ -0,0 +1,28 @@ +// 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.Game.Screens.Multi.Match.Components; +using osuTK; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneOverlinedParticipants : MultiplayerTestScene + { + protected override bool UseOnlineAPI => true; + + public TestSceneOverlinedParticipants() + { + Room.RoomID.Value = 7; + + Add(new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(500), + Child = new OverlinedParticipants() + }); + } + } +} diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs new file mode 100644 index 0000000000..cf4897be50 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs @@ -0,0 +1,39 @@ +// 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.Game.Online.Multiplayer; +using osu.Game.Rulesets.Osu; +using osu.Game.Screens.Multi.Match.Components; +using osu.Game.Tests.Beatmaps; +using osuTK; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneOverlinedPlaylist : MultiplayerTestScene + { + protected override bool UseOnlineAPI => true; + + public TestSceneOverlinedPlaylist() + { + for (int i = 0; i < 10; i++) + { + Room.Playlist.Add(new PlaylistItem + { + ID = i, + Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, + Ruleset = { Value = new OsuRuleset().RulesetInfo } + }); + } + + Add(new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(500), + Child = new OverlinedPlaylist(false) + }); + } + } +} diff --git a/osu.Game/Screens/Multi/Match/Components/OverlinedDisplay.cs b/osu.Game/Screens/Multi/Match/Components/OverlinedDisplay.cs new file mode 100644 index 0000000000..854877bd1c --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/OverlinedDisplay.cs @@ -0,0 +1,87 @@ +// 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.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public abstract class OverlinedDisplay : MultiplayerComposite + { + protected readonly Container Content; + + protected string Details + { + set => details.Text = value; + } + + private readonly Circle line; + private readonly OsuSpriteText details; + + protected OverlinedDisplay(string title) + { + RelativeSizeAxes = Axes.Both; + + InternalChild = new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + line = new Circle + { + RelativeSizeAxes = Axes.X, + Height = 2, + Margin = new MarginPadding { Bottom = 2 } + }, + }, + new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Margin = new MarginPadding { Top = 5 }, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + new OsuSpriteText + { + Text = title, + Font = OsuFont.GetFont(size: 14) + }, + details = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) }, + } + }, + }, + new Drawable[] + { + Content = new Container + { + Margin = new MarginPadding { Top = 5 }, + RelativeSizeAxes = Axes.Both + } + } + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + line.Colour = colours.Yellow; + details.Colour = colours.Yellow; + } + } +} diff --git a/osu.Game/Screens/Multi/Match/Components/OverlinedParticipants.cs b/osu.Game/Screens/Multi/Match/Components/OverlinedParticipants.cs new file mode 100644 index 0000000000..7a4290a9a1 --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/OverlinedParticipants.cs @@ -0,0 +1,29 @@ +// 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.Game.Screens.Multi.Components; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public class OverlinedParticipants : OverlinedDisplay + { + public OverlinedParticipants() + : base("Participants") + { + Content.Add(new ParticipantsList { RelativeSizeAxes = Axes.Both }); + } + + [BackgroundDependencyLoader] + private void load() + { + ParticipantCount.BindValueChanged(_ => setParticipantCount()); + MaxParticipants.BindValueChanged(_ => setParticipantCount()); + + setParticipantCount(); + } + + private void setParticipantCount() => Details = MaxParticipants.Value != null ? $"{ParticipantCount.Value}/{MaxParticipants.Value}" : ParticipantCount.Value.ToString(); + } +} diff --git a/osu.Game/Screens/Multi/Match/Components/OverlinedPlaylist.cs b/osu.Game/Screens/Multi/Match/Components/OverlinedPlaylist.cs new file mode 100644 index 0000000000..eea85d9d64 --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/OverlinedPlaylist.cs @@ -0,0 +1,33 @@ +// 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.Bindables; +using osu.Framework.Graphics; +using osu.Game.Online.Multiplayer; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public class OverlinedPlaylist : OverlinedDisplay + { + public readonly Bindable SelectedItem = new Bindable(); + + private readonly DrawableRoomPlaylist playlist; + + public OverlinedPlaylist(bool allowSelection) + : base("Playlist") + { + Content.Add(playlist = new DrawableRoomPlaylist(false, allowSelection) + { + RelativeSizeAxes = Axes.Both, + SelectedItem = { BindTarget = SelectedItem } + }); + } + + [BackgroundDependencyLoader] + private void load() + { + playlist.Items.BindTo(Playlist); + } + } +} From 2ea8c47c83a084bf3bc67ebe527c5bebfe12dc00 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 20:44:41 +0900 Subject: [PATCH 080/216] Fix incorrect footer button size --- osu.Game/Screens/Multi/Match/Components/ReadyButton.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index a62572a851..d39217db5d 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -5,11 +5,9 @@ using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; -using osuTK; namespace osu.Game.Screens.Multi.Match.Components { @@ -30,9 +28,6 @@ namespace osu.Game.Screens.Multi.Match.Components public ReadyButton() { - RelativeSizeAxes = Axes.Y; - Size = new Vector2(200, 1); - Text = "Start"; } From b92f1ad68dc57c67b33fe8bf180419b6118c93d7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 20:48:09 +0900 Subject: [PATCH 081/216] Implement match subscreen re-design --- .../TestSceneMatchBeatmapDetailArea.cs | 4 +- .../Screens/Multi/Match/MatchSubScreen.cs | 223 ++++++++++-------- 2 files changed, 125 insertions(+), 102 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs index 09d882a265..5c7ad7616d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs @@ -24,14 +24,12 @@ namespace osu.Game.Tests.Visual.Multiplayer private RulesetStore rulesetStore { get; set; } - private MatchBeatmapDetailArea detailArea; - [SetUp] public void Setup() => Schedule(() => { Room.Playlist.Clear(); - Child = detailArea = new MatchBeatmapDetailArea + Child = new MatchBeatmapDetailArea { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 07da707724..44fccdaa13 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -5,17 +5,23 @@ using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Game.Audio; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Play; -using PlaylistItem = osu.Game.Online.Multiplayer.PlaylistItem; +using osu.Game.Screens.Select; +using osuTK.Graphics; +using Footer = osu.Game.Screens.Multi.Match.Components.Footer; namespace osu.Game.Screens.Multi.Match { @@ -31,26 +37,21 @@ namespace osu.Game.Screens.Multi.Match [Resolved(typeof(Room), nameof(Room.RoomID))] private Bindable roomId { get; set; } - [Resolved(typeof(Room), nameof(Room.Name))] - private Bindable name { get; set; } - [Resolved(typeof(Room), nameof(Room.Type))] private Bindable type { get; set; } - [Resolved(typeof(Room))] - protected BindableList Playlist { get; private set; } + [Resolved(typeof(Room), nameof(Room.Playlist))] + private BindableList playlist { get; set; } [Resolved] private BeatmapManager beatmapManager { get; set; } - [Resolved] - private PreviewTrackManager previewTrackManager { get; set; } - - [Resolved(CanBeNull = true)] - private OsuGame game { get; set; } + [Resolved(canBeNull: true)] + private Multiplayer multiplayer { get; set; } private readonly Bindable selectedItem = new Bindable(); - private MatchLeaderboard leaderboard; + private LeaderboardChatDisplay leaderboardChatDisplay; + private MatchSettingsOverlay settingsOverlay; public MatchSubScreen(Room room) { @@ -60,12 +61,14 @@ namespace osu.Game.Screens.Multi.Match [BackgroundDependencyLoader] private void load() { - Components.Header header; - GridContainer bottomRow; - MatchSettingsOverlay settings; - InternalChildren = new Drawable[] { + new HeaderBackgroundSprite + { + RelativeSizeAxes = Axes.X, + Height = 200, + Colour = ColourInfo.GradientVertical(Color4.White.Opacity(0.4f), Color4.White.Opacity(0)) + }, new GridContainer { RelativeSizeAxes = Axes.Both, @@ -73,143 +76,155 @@ namespace osu.Game.Screens.Multi.Match { new Drawable[] { - header = new Components.Header + new Container { - Depth = -1, + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding + { + Horizontal = 105, + Vertical = 20 + }, + Child = new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { new Components.Header() }, + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 65 }, + Child = new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 5 }, + Child = new OverlinedParticipants() + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = 5 }, + Child = new OverlinedPlaylist(true) // Temporarily always allow selection + { + SelectedItem = { BindTarget = selectedItem } + } + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = 5 }, + Child = leaderboardChatDisplay = new LeaderboardChatDisplay() + } + }, + } + } + } + } + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + } + } } }, new Drawable[] { - bottomRow = new GridContainer + new Footer { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] - { - leaderboard = new MatchLeaderboard - { - Padding = new MarginPadding - { - Left = 10 + HORIZONTAL_OVERFLOW_PADDING, - Right = 10, - Vertical = 10, - }, - RelativeSizeAxes = Axes.Both - }, - new Container - { - Padding = new MarginPadding - { - Left = 10, - Right = 10 + HORIZONTAL_OVERFLOW_PADDING, - Vertical = 10, - }, - RelativeSizeAxes = Axes.Both, - Child = new MatchChatDisplay - { - RelativeSizeAxes = Axes.Both - } - }, - }, - }, + OnStart = onStart, + SelectedItem = { BindTarget = selectedItem } } - }, + } }, RowDimensions = new[] { + new Dimension(), new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Distributed), } }, - new Container + settingsOverlay = new MatchSettingsOverlay { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = Components.Header.HEIGHT }, - Child = settings = new MatchSettingsOverlay { RelativeSizeAxes = Axes.Both }, - }, + EditPlaylist = () => this.Push(new MatchSongSelect()), + State = { Value = roomId.Value == null ? Visibility.Visible : Visibility.Hidden } + } }; - - beatmapManager.ItemAdded += beatmapAdded; } protected override void LoadComplete() { base.LoadComplete(); - Playlist.ItemsAdded += _ => updateSelectedItem(); - Playlist.ItemsRemoved += _ => updateSelectedItem(); + roomId.BindValueChanged(id => + { + if (id.NewValue == null) + settingsOverlay.Show(); + else + settingsOverlay.Hide(); + }, true); - updateSelectedItem(); - } + selectedItem.BindValueChanged(selectedItemChanged); + selectedItem.Value = playlist.FirstOrDefault(); - private void updateSelectedItem() - { - selectedItem.Value = Playlist.FirstOrDefault(); - currentItemChanged(); + beatmapManager.ItemAdded += beatmapAdded; } public override bool OnExiting(IScreen next) { RoomManager?.PartRoom(); Mods.Value = Array.Empty(); - previewTrackManager.StopAnyPlaying(this); return base.OnExiting(next); } - /// - /// Handles propagation of the current playlist item's content to game-wide mechanisms. - /// - private void currentItemChanged() + private void selectedItemChanged(ValueChangedEvent e) { - var item = selectedItem.Value; + updateWorkingBeatmap(); - // Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info - var localBeatmap = item?.Beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == item.Beatmap.Value.OnlineBeatmapID); + Mods.Value = e.NewValue?.RequiredMods?.ToArray() ?? Array.Empty(); - Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); - Mods.Value = item?.RequiredMods?.ToArray() ?? Array.Empty(); - - if (item?.Ruleset != null) - Ruleset.Value = item.Ruleset.Value; - - previewTrackManager.StopAnyPlaying(this); + if (e.NewValue?.Ruleset != null) + Ruleset.Value = e.NewValue.Ruleset.Value; + } + + private void updateWorkingBeatmap() + { + var beatmap = selectedItem.Value?.Beatmap.Value; + + // Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info + var localBeatmap = beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID); + + Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); } - /// - /// Handle the case where a beatmap is imported (and can be used by this match). - /// private void beatmapAdded(BeatmapSetInfo model) => Schedule(() => { if (Beatmap.Value != beatmapManager.DefaultBeatmap) return; - if (selectedItem.Value == null) - return; - - // Try to retrieve the corresponding local beatmap - var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == selectedItem.Value.Beatmap.Value.OnlineBeatmapID); - - if (localBeatmap != null) - Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); + updateWorkingBeatmap(); }); - [Resolved(canBeNull: true)] - private Multiplayer multiplayer { get; set; } - private void onStart() { - previewTrackManager.StopAnyPlaying(this); - switch (type.Value) { default: case GameTypeTimeshift _: multiplayer?.Start(() => new TimeshiftPlayer(selectedItem.Value) { - Exited = () => leaderboard.RefreshScores() + Exited = () => leaderboardChatDisplay.RefreshScores() }); break; } @@ -222,5 +237,15 @@ namespace osu.Game.Screens.Multi.Match if (beatmapManager != null) beatmapManager.ItemAdded -= beatmapAdded; } + + private class HeaderBackgroundSprite : MultiplayerBackgroundSprite + { + protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BackgroundSprite { RelativeSizeAxes = Axes.Both }; + + private class BackgroundSprite : UpdateableBeatmapBackgroundSprite + { + protected override double TransformDuration => 200; + } + } } } From 9eaf37258794cdec6c0bc6c9dedad6713551d54e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 21:17:07 +0900 Subject: [PATCH 082/216] Immediately update selected state --- osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs index b1e69e4c4f..1c35d8a53f 100644 --- a/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs @@ -76,7 +76,7 @@ namespace osu.Game.Screens.Multi { base.LoadComplete(); - SelectedItem.BindValueChanged(selected => maskingContainer.BorderThickness = selected.NewValue == Model ? 5 : 0); + SelectedItem.BindValueChanged(selected => maskingContainer.BorderThickness = selected.NewValue == Model ? 5 : 0, true); beatmap.BindValueChanged(_ => scheduleRefresh()); ruleset.BindValueChanged(_ => scheduleRefresh()); From c753cb46c50d48107fb58ebdd93f8ae4c54e542f Mon Sep 17 00:00:00 2001 From: recapitalverb <41869184+recapitalverb@users.noreply.github.com> Date: Fri, 14 Feb 2020 20:14:00 +0700 Subject: [PATCH 083/216] Use [Resolved] wherever possible --- osu.Game/Audio/PreviewTrackManager.cs | 15 +++++---------- osu.Game/Graphics/ScreenshotManager.cs | 12 +++++++----- osu.Game/Graphics/UserInterface/DownloadButton.cs | 7 +++---- .../Graphics/UserInterface/ExternalLinkButton.cs | 7 ++++--- osu.Game/Graphics/UserInterface/FocusedTextBox.cs | 7 +++---- .../Graphics/UserInterface/OsuPasswordTextBox.cs | 9 ++------- osu.Game/Online/Chat/ChannelManager.cs | 9 ++------- osu.Game/Online/Chat/ExternalLinkOpener.cs | 12 +++++++----- osu.Game/Online/DownloadTrackingComposite.cs | 7 +++---- osu.Game/Online/Leaderboards/Leaderboard.cs | 8 ++++---- osu.Game/OsuGame.cs | 7 +++---- osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 13 +++++++------ .../Overlays/AccountCreation/ScreenWarning.cs | 8 ++++---- osu.Game/Overlays/BeatmapSetOverlay.cs | 7 +++---- osu.Game/Overlays/ChatOverlay.cs | 7 +++---- osu.Game/Overlays/Direct/PlayButton.cs | 7 +++---- osu.Game/Overlays/DirectOverlay.cs | 12 ++++++------ osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 7 +++---- osu.Game/Overlays/Music/PlaylistOverlay.cs | 7 ++++--- .../Sections/Audio/AudioDevicesSettings.cs | 9 ++------- .../Settings/Sections/General/LoginSettings.cs | 15 ++++++++------- .../Settings/Sections/Graphics/LayoutSettings.cs | 8 ++++---- .../Overlays/Settings/Sections/SkinSection.cs | 7 +++---- osu.Game/Rulesets/Judgements/DrawableJudgement.cs | 7 +++---- .../Screens/Edit/Components/PlaybackControl.cs | 7 +++---- .../Screens/Edit/Components/TimeInfoContainer.cs | 9 ++------- .../Edit/Compose/Components/Timeline/Timeline.cs | 7 +++---- osu.Game/Screens/Menu/IntroTriangles.cs | 7 +++---- .../Multi/Ranking/Pages/RoomLeaderboardPage.cs | 8 ++++---- osu.Game/Screens/Play/Player.cs | 7 +++---- osu.Game/Screens/Select/BeatmapDetails.cs | 9 ++------- .../Select/Carousel/DrawableCarouselBeatmap.cs | 7 +++---- .../Select/Carousel/DrawableCarouselBeatmapSet.cs | 6 +++--- osu.Game/Skinning/SkinnableSound.cs | 9 ++------- osu.Game/Updater/SimpleUpdateManager.cs | 7 ++++--- 35 files changed, 128 insertions(+), 169 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 6f0b62543d..862be41c1a 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -19,13 +19,15 @@ namespace osu.Game.Audio { private readonly BindableDouble muteBindable = new BindableDouble(); - private AudioManager audio; + [Resolved] + private AudioManager audio { get; set; } + private PreviewTrackStore trackStore; protected TrackManagerPreviewTrack CurrentTrack; [BackgroundDependencyLoader] - private void load(AudioManager audio) + private void load() { // this is a temporary solution to get around muting ourselves. // todo: update this once we have a BackgroundTrackManager or similar. @@ -33,8 +35,6 @@ namespace osu.Game.Audio audio.AddItem(trackStore); trackStore.AddAdjustment(AdjustableProperty.Volume, audio.VolumeTrack); - - this.audio = audio; } /// @@ -90,6 +90,7 @@ namespace osu.Game.Audio public class TrackManagerPreviewTrack : PreviewTrack { + [Resolved] public IPreviewTrackOwner Owner { get; private set; } private readonly BeatmapSetInfo beatmapSetInfo; @@ -101,12 +102,6 @@ namespace osu.Game.Audio this.trackManager = trackManager; } - [BackgroundDependencyLoader] - private void load(IPreviewTrackOwner owner) - { - Owner = owner; - } - protected override Track GetTrack() => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3"); } diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index e21545688b..9804aefce8 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -35,18 +35,20 @@ namespace osu.Game.Graphics private Bindable screenshotFormat; private Bindable captureMenuCursor; - private GameHost host; + [Resolved] + private GameHost host { get; set; } + private Storage storage; - private NotificationOverlay notificationOverlay; + + [Resolved] + private NotificationOverlay notificationOverlay { get; set; } private SampleChannel shutter; [BackgroundDependencyLoader] - private void load(GameHost host, OsuConfigManager config, Storage storage, NotificationOverlay notificationOverlay, AudioManager audio) + private void load(OsuConfigManager config, Storage storage, AudioManager audio) { - this.host = host; this.storage = storage.GetStorageForDirectory(@"screenshots"); - this.notificationOverlay = notificationOverlay; screenshotFormat = config.GetBindable(OsuSetting.ScreenshotFormat); captureMenuCursor = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor); diff --git a/osu.Game/Graphics/UserInterface/DownloadButton.cs b/osu.Game/Graphics/UserInterface/DownloadButton.cs index 41b90d3802..86a5cb9aa6 100644 --- a/osu.Game/Graphics/UserInterface/DownloadButton.cs +++ b/osu.Game/Graphics/UserInterface/DownloadButton.cs @@ -19,7 +19,8 @@ namespace osu.Game.Graphics.UserInterface private readonly SpriteIcon checkmark; private readonly Box background; - private OsuColour colours; + [Resolved] + private OsuColour colours { get; set; } public DownloadButton() { @@ -49,10 +50,8 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { - this.colours = colours; - State.BindValueChanged(updateState, true); } diff --git a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs index 7225dbc66f..5a1eb53fe1 100644 --- a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs +++ b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs @@ -18,7 +18,9 @@ namespace osu.Game.Graphics.UserInterface public string Link { get; set; } private Color4 hoverColour; - private GameHost host; + + [Resolved] + private GameHost host { get; set; } public ExternalLinkButton(string link = null) { @@ -32,10 +34,9 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private void load(OsuColour colours, GameHost host) + private void load(OsuColour colours) { hoverColour = colours.Yellow; - this.host = host; } protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index e59353a480..8977f014b6 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -36,13 +36,12 @@ namespace osu.Game.Graphics.UserInterface } } - private GameHost host; + [Resolved] + private GameHost host { get; set; } [BackgroundDependencyLoader] - private void load(GameHost host) + private void load() { - this.host = host; - BackgroundUnfocused = new Color4(10, 10, 10, 255); BackgroundFocused = new Color4(10, 10, 10, 255); } diff --git a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs index e4a4b1c50e..e7699e5255 100644 --- a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs @@ -24,7 +24,8 @@ namespace osu.Game.Graphics.UserInterface private readonly CapsWarning warning; - private GameHost host; + [Resolved] + private GameHost host { get; set; } public OsuPasswordTextBox() { @@ -38,12 +39,6 @@ namespace osu.Game.Graphics.UserInterface }); } - [BackgroundDependencyLoader] - private void load(GameHost host) - { - this.host = host; - } - protected override bool OnKeyDown(KeyDownEvent e) { if (e.Key == Key.CapsLock) diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 4b5ec1cad0..2c37216fd6 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -48,7 +48,8 @@ namespace osu.Game.Online.Chat /// public IBindableList AvailableChannels => availableChannels; - private IAPIProvider api; + [Resolved] + private IAPIProvider api { get; set; } public readonly BindableBool HighPollRate = new BindableBool(); @@ -466,12 +467,6 @@ namespace osu.Game.Online.Chat api.Queue(req); } - - [BackgroundDependencyLoader] - private void load(IAPIProvider api) - { - this.api = api; - } } /// diff --git a/osu.Game/Online/Chat/ExternalLinkOpener.cs b/osu.Game/Online/Chat/ExternalLinkOpener.cs index 495f1ac0b0..da90ea6845 100644 --- a/osu.Game/Online/Chat/ExternalLinkOpener.cs +++ b/osu.Game/Online/Chat/ExternalLinkOpener.cs @@ -13,15 +13,17 @@ namespace osu.Game.Online.Chat { public class ExternalLinkOpener : Component { - private GameHost host; - private DialogOverlay dialogOverlay; + [Resolved] + private GameHost host { get; set; } + + [Resolved] + private DialogOverlay dialogOverlay { get; set; } + private Bindable externalLinkWarning; [BackgroundDependencyLoader(true)] - private void load(GameHost host, DialogOverlay dialogOverlay, OsuConfigManager config) + private void load(OsuConfigManager config) { - this.host = host; - this.dialogOverlay = dialogOverlay; externalLinkWarning = config.GetBindable(OsuSetting.ExternalLinkWarning); } diff --git a/osu.Game/Online/DownloadTrackingComposite.cs b/osu.Game/Online/DownloadTrackingComposite.cs index 9a0e112727..9eb5f36729 100644 --- a/osu.Game/Online/DownloadTrackingComposite.cs +++ b/osu.Game/Online/DownloadTrackingComposite.cs @@ -19,7 +19,8 @@ namespace osu.Game.Online { protected readonly Bindable Model = new Bindable(); - private TModelManager manager; + [Resolved] + private TModelManager manager { get; set; } /// /// Holds the current download state of the , whether is has already been downloaded, is in progress, or is not downloaded. @@ -34,10 +35,8 @@ namespace osu.Game.Online } [BackgroundDependencyLoader(true)] - private void load(TModelManager manager) + private void load() { - this.manager = manager; - Model.BindValueChanged(modelInfo => { if (modelInfo.NewValue == null) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 87c747675a..71859d3aeb 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -217,14 +217,14 @@ namespace osu.Game.Online.Leaderboards Scores = null; } - private IAPIProvider api; + [Resolved(CanBeNull = true)] + private IAPIProvider api { get; set; } private ScheduledDelegate pendingUpdateScores; - [BackgroundDependencyLoader(true)] - private void load(IAPIProvider api) + [BackgroundDependencyLoader] + private void load() { - this.api = api; api?.Register(this); } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e7fffd49b4..100730d40d 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -150,10 +150,8 @@ namespace osu.Game dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); [BackgroundDependencyLoader] - private void load(FrameworkConfigManager frameworkConfig) + private void load() { - this.frameworkConfig = frameworkConfig; - if (!Host.IsPrimaryInstance && !DebugUtils.IsDebugBuild) { Logger.Log(@"osu! does not support multiple running instances.", LoggingTarget.Runtime, LogLevel.Error); @@ -881,7 +879,8 @@ namespace osu.Game private Container topMostOverlayContent; - private FrameworkConfigManager frameworkConfig; + [Resolved] + private FrameworkConfigManager frameworkConfig { get; set; } private ScalingContainer screenContainer; diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 7067e02cd2..be3a84ca00 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -33,20 +33,21 @@ namespace osu.Game.Overlays.AccountCreation private OsuTextBox emailTextBox; private OsuPasswordTextBox passwordTextBox; - private IAPIProvider api; + [Resolved] + private IAPIProvider api { get; set; } + private ShakeContainer registerShake; private IEnumerable characterCheckText; private OsuTextBox[] textboxes; private ProcessingOverlay processingOverlay; - private GameHost host; + + [Resolved] + private GameHost host { get; set; } [BackgroundDependencyLoader] - private void load(OsuColour colours, IAPIProvider api, GameHost host) + private void load(OsuColour colours) { - this.api = api; - this.host = host; - InternalChildren = new Drawable[] { new FillFlowContainer diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index f91d2e3323..3c3c27ab6f 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -22,7 +22,9 @@ namespace osu.Game.Overlays.AccountCreation { private OsuTextFlowContainer multiAccountExplanationText; private LinkFlowContainer furtherAssistance; - private IAPIProvider api; + + [Resolved] + private IAPIProvider api { get; set; } private const string help_centre_url = "/help/wiki/Help_Centre#login"; @@ -39,10 +41,8 @@ namespace osu.Game.Overlays.AccountCreation } [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, IAPIProvider api, OsuGame game, TextureStore textures) + private void load(OsuColour colours, OsuGame game, TextureStore textures) { - this.api = api; - if (string.IsNullOrEmpty(api.ProvidedUsername)) return; diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 7624351e41..d29997f7e5 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -25,7 +25,8 @@ namespace osu.Game.Overlays public const float RIGHT_WIDTH = 275; protected readonly Header Header; - private RulesetStore rulesets; + [Resolved] + private RulesetStore rulesets { get; set; } private readonly Bindable beatmapSet = new Bindable(); @@ -90,10 +91,8 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) + private void load() { - this.rulesets = rulesets; - background.Colour = ColourProvider.Background6; } diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index f2aef0995f..bdc241a437 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -30,7 +30,8 @@ namespace osu.Game.Overlays private const float textbox_height = 60; private const float channel_selection_min_height = 0.3f; - private ChannelManager channelManager; + [Resolved] + private ChannelManager channelManager { get; set; } private Container currentChannelContainer; @@ -72,7 +73,7 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(OsuConfigManager config, OsuColour colours, ChannelManager channelManager) + private void load(OsuConfigManager config, OsuColour colours) { const float padding = 5; @@ -209,8 +210,6 @@ namespace osu.Game.Overlays chatBackground.Colour = colours.ChatBlue; - this.channelManager = channelManager; - loading.Show(); // This is a relatively expensive (and blocking) operation. diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 2a77e7ca26..10abe15177 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -85,13 +85,12 @@ namespace osu.Game.Overlays.Direct Playing.ValueChanged += playingStateChanged; } - private PreviewTrackManager previewTrackManager; + [Resolved] + private PreviewTrackManager previewTrackManager { get; set; } [BackgroundDependencyLoader] - private void load(OsuColour colour, PreviewTrackManager previewTrackManager) + private void load(OsuColour colour) { - this.previewTrackManager = previewTrackManager; - hoverColour = colour.Yellow; } diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index e4cef319fe..6cc48f09bd 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -27,7 +27,8 @@ namespace osu.Game.Overlays { private const float panel_padding = 10f; - private RulesetStore rulesets; + [Resolved] + private RulesetStore rulesets { get; set; } private readonly FillFlowContainer resultCountsContainer; private readonly OsuSpriteText resultCountsText; @@ -155,11 +156,8 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(OsuColour colours, RulesetStore rulesets, PreviewTrackManager previewTrackManager) + private void load(OsuColour colours) { - this.rulesets = rulesets; - this.previewTrackManager = previewTrackManager; - resultCountsContainer.Colour = colours.Yellow; } @@ -228,7 +226,9 @@ namespace osu.Game.Overlays private readonly Bindable currentQuery = new Bindable(string.Empty); private ScheduledDelegate queryChangedDebounce; - private PreviewTrackManager previewTrackManager; + + [Resolved] + private PreviewTrackManager previewTrackManager { get; set; } private void queueUpdateSearch(bool queryTextChanged = false) { diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index d2fcc2652a..58ca2143f9 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -66,13 +66,12 @@ namespace osu.Game.Overlays.KeyBinding CornerRadius = padding; } - private KeyBindingStore store; + [Resolved] + private KeyBindingStore store { get; set; } [BackgroundDependencyLoader] - private void load(OsuColour colours, KeyBindingStore store) + private void load(OsuColour colours) { - this.store = store; - EdgeEffect = new EdgeEffectParameters { Radius = 2, diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 7c391e27f9..8f753fd3aa 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -26,16 +26,17 @@ namespace osu.Game.Overlays.Music private readonly BindableList beatmapSets = new BindableList(); private readonly Bindable beatmap = new Bindable(); - private BeatmapManager beatmaps; + + [Resolved] + private BeatmapManager beatmaps { get; set; } private FilterControl filter; private Playlist list; [BackgroundDependencyLoader] - private void load(OsuColour colours, Bindable beatmap, BeatmapManager beatmaps) + private void load(OsuColour colours, Bindable beatmap) { this.beatmap.BindTo(beatmap); - this.beatmaps = beatmaps; Children = new Drawable[] { diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index 0612f028bc..3cc233ef73 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -14,15 +14,10 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { protected override string Header => "Devices"; - private AudioManager audio; + [Resolved] + private AudioManager audio { get; set; } private SettingsDropdown dropdown; - [BackgroundDependencyLoader] - private void load(AudioManager audio) - { - this.audio = audio; - } - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index e485aa5ea9..b41c7d5afb 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -29,7 +29,9 @@ namespace osu.Game.Overlays.Settings.Sections.General { private bool bounding = true; private LoginForm form; - private OsuColour colours; + + [Resolved] + private OsuColour colours { get; set; } private UserPanel panel; private UserDropdown dropdown; @@ -60,10 +62,8 @@ namespace osu.Game.Overlays.Settings.Sections.General } [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuColour colours, IAPIProvider api) + private void load(IAPIProvider api) { - this.colours = colours; - api?.Register(this); } @@ -201,7 +201,9 @@ namespace osu.Game.Overlays.Settings.Sections.General private TextBox username; private TextBox password; private ShakeContainer shakeSignIn; - private IAPIProvider api; + + [Resolved] + private IAPIProvider api { get; set; } public Action RequestHide; @@ -214,9 +216,8 @@ namespace osu.Game.Overlays.Settings.Sections.General } [BackgroundDependencyLoader(permitNulls: true)] - private void load(IAPIProvider api, OsuConfigManager config, AccountCreationOverlay accountCreation) + private void load(OsuConfigManager config, AccountCreationOverlay accountCreation) { - this.api = api; Direction = FillDirection.Vertical; Spacing = new Vector2(0, 5); AutoSizeAxes = Axes.Y; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index efbb08b7df..b73c8f7622 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -29,7 +29,9 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private Bindable sizeFullscreen; private readonly IBindableList windowModes = new BindableList(); - private OsuGameBase game; + [Resolved] + private OsuGameBase game { get; set; } + private SettingsDropdown resolutionDropdown; private SettingsDropdown windowModeDropdown; @@ -41,10 +43,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private const int transition_duration = 400; [BackgroundDependencyLoader] - private void load(FrameworkConfigManager config, OsuConfigManager osuConfig, OsuGameBase game, GameHost host) + private void load(FrameworkConfigManager config, OsuConfigManager osuConfig, GameHost host) { - this.game = game; - scalingMode = osuConfig.GetBindable(OsuSetting.Scaling); sizeFullscreen = config.GetBindable(FrameworkSetting.SizeFullscreen); scalingSizeX = osuConfig.GetBindable(OsuSetting.ScalingSizeX); diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index d3029d8ab9..b229014c84 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -24,13 +24,12 @@ namespace osu.Game.Overlays.Settings.Sections private readonly Bindable dropdownBindable = new Bindable { Default = SkinInfo.Default }; private readonly Bindable configBindable = new Bindable(); - private SkinManager skins; + [Resolved] + private SkinManager skins { get; set; } [BackgroundDependencyLoader] - private void load(OsuConfigManager config, SkinManager skins) + private void load(OsuConfigManager config) { - this.skins = skins; - FlowContent.Spacing = new Vector2(0, 5); Children = new Drawable[] { diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 8289ca175d..960585b968 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -23,7 +23,8 @@ namespace osu.Game.Rulesets.Judgements { private const float judgement_size = 128; - private OsuColour colours; + [Resolved] + private OsuColour colours { get; set; } protected readonly JudgementResult Result; @@ -56,10 +57,8 @@ namespace osu.Game.Rulesets.Judgements } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { - this.colours = colours; - InternalChild = JudgementBody = new Container { Anchor = Anchor.Centre, diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 66df68418a..897c6ec531 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -25,15 +25,14 @@ namespace osu.Game.Screens.Edit.Components { private IconButton playButton; - private IAdjustableClock adjustableClock; + [Resolved] + private IAdjustableClock adjustableClock { get; set; } private readonly BindableNumber tempo = new BindableDouble(1); [BackgroundDependencyLoader] - private void load(IAdjustableClock adjustableClock) + private void load() { - this.adjustableClock = adjustableClock; - Children = new Drawable[] { playButton = new IconButton diff --git a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs index 0391074b11..4bf21d240a 100644 --- a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs +++ b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs @@ -14,7 +14,8 @@ namespace osu.Game.Screens.Edit.Components { private readonly OsuSpriteText trackTimer; - private IAdjustableClock adjustableClock; + [Resolved] + private IAdjustableClock adjustableClock { get; set; } public TimeInfoContainer() { @@ -30,12 +31,6 @@ namespace osu.Game.Screens.Edit.Components }; } - [BackgroundDependencyLoader] - private void load(IAdjustableClock adjustableClock) - { - this.adjustableClock = adjustableClock; - } - protected override void Update() { base.Update(); diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 0475e68e42..ddca5e42c2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -24,7 +24,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public readonly Bindable WaveformVisible = new Bindable(); public readonly IBindable Beatmap = new Bindable(); - private IAdjustableClock adjustableClock; + [Resolved] + private IAdjustableClock adjustableClock { get; set; } public Timeline() { @@ -36,10 +37,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private WaveformGraph waveform; [BackgroundDependencyLoader] - private void load(IBindable beatmap, IAdjustableClock adjustableClock, OsuColour colours) + private void load(IBindable beatmap, OsuColour colours) { - this.adjustableClock = adjustableClock; - Add(waveform = new WaveformGraph { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index 4deaa68467..29f32406e8 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -102,13 +102,12 @@ namespace osu.Game.Screens.Menu this.background = background; } - private OsuGameBase game; + [Resolved] + private OsuGameBase game { get; set; } [BackgroundDependencyLoader] - private void load(TextureStore textures, OsuGameBase game) + private void load(TextureStore textures) { - this.game = game; - InternalChildren = new Drawable[] { triangles = new GlitchingTriangles diff --git a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs index ff5471cf4a..f8fb192b5c 100644 --- a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs +++ b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs @@ -23,7 +23,9 @@ namespace osu.Game.Screens.Multi.Ranking.Pages { public class RoomLeaderboardPage : ResultsPage { - private OsuColour colours; + [Resolved] + private OsuColour colours { get; set; } + private TextFlowContainer rankText; [Resolved(typeof(Room), nameof(Room.Name))] @@ -35,10 +37,8 @@ namespace osu.Game.Screens.Multi.Ranking.Pages } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { - this.colours = colours; - MatchLeaderboard leaderboard; Children = new Drawable[] diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 9bfdcd79fe..bd43b23a9f 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -65,7 +65,8 @@ namespace osu.Game.Screens.Play private Ruleset ruleset; - private IAPIProvider api; + [Resolved] + private IAPIProvider api { get; set; } private SampleChannel sampleRestart; @@ -118,10 +119,8 @@ namespace osu.Game.Screens.Play => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); [BackgroundDependencyLoader] - private void load(AudioManager audio, IAPIProvider api, OsuConfigManager config) + private void load(AudioManager audio, OsuConfigManager config) { - this.api = api; - Mods.Value = base.Mods.Value.Select(m => m.CreateCopy()).ToArray(); if (Beatmap.Value is DummyWorkingBeatmap) diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 577d999388..85b892336a 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -37,7 +37,8 @@ namespace osu.Game.Screens.Select private readonly FailRetryGraph failRetryGraph; private readonly DimmedLoadingLayer loading; - private IAPIProvider api; + [Resolved] + private IAPIProvider api { get; set; } private ScheduledDelegate pendingBeatmapSwitch; @@ -160,12 +161,6 @@ namespace osu.Game.Screens.Select }; } - [BackgroundDependencyLoader] - private void load(IAPIProvider api) - { - this.api = api; - } - protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index fba7a328c1..31aca11b86 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -37,7 +37,8 @@ namespace osu.Game.Screens.Select.Carousel private Triangles triangles; private StarCounter starCounter; - private BeatmapSetOverlay beatmapOverlay; + [Resolved] + private BeatmapSetOverlay beatmapOverlay { get; set; } public DrawableCarouselBeatmap(CarouselBeatmap panel) : base(panel) @@ -47,10 +48,8 @@ namespace osu.Game.Screens.Select.Carousel } [BackgroundDependencyLoader(true)] - private void load(SongSelect songSelect, BeatmapManager manager, BeatmapSetOverlay beatmapOverlay) + private void load(SongSelect songSelect, BeatmapManager manager) { - this.beatmapOverlay = beatmapOverlay; - if (songSelect != null) { startRequested = b => songSelect.FinaliseSelection(b); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 699e01bca7..db59d8a4de 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -30,7 +30,8 @@ namespace osu.Game.Screens.Select.Carousel private Action restoreHiddenRequested; private Action viewDetails; - private DialogOverlay dialogOverlay; + [Resolved] + private DialogOverlay dialogOverlay { get; set; } private readonly BeatmapSetInfo beatmapSet; public DrawableCarouselBeatmapSet(CarouselBeatmapSet set) @@ -40,10 +41,9 @@ namespace osu.Game.Screens.Select.Carousel } [BackgroundDependencyLoader(true)] - private void load(BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay) + private void load(BeatmapManager manager, BeatmapSetOverlay beatmapOverlay) { restoreHiddenRequested = s => s.Beatmaps.ForEach(manager.Restore); - dialogOverlay = overlay; if (beatmapOverlay != null) viewDetails = beatmapOverlay.FetchAndShowBeatmapSet; diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index fc6afd0b27..a78c04ecd4 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -21,7 +21,8 @@ namespace osu.Game.Skinning private SampleChannel[] channels; - private ISampleStore samples; + [Resolved] + private ISampleStore samples { get; set; } public SkinnableSound(IEnumerable hitSamples) { @@ -33,12 +34,6 @@ namespace osu.Game.Skinning this.hitSamples = new[] { hitSamples }; } - [BackgroundDependencyLoader] - private void load(ISampleStore samples) - { - this.samples = samples; - } - private bool looping; public bool Looping diff --git a/osu.Game/Updater/SimpleUpdateManager.cs b/osu.Game/Updater/SimpleUpdateManager.cs index 5412b11b33..e490ac14e9 100644 --- a/osu.Game/Updater/SimpleUpdateManager.cs +++ b/osu.Game/Updater/SimpleUpdateManager.cs @@ -20,12 +20,13 @@ namespace osu.Game.Updater public class SimpleUpdateManager : UpdateManager { private string version; - private GameHost host; + + [Resolved] + private GameHost host { get; set; } [BackgroundDependencyLoader] - private void load(OsuGameBase game, GameHost host) + private void load(OsuGameBase game) { - this.host = host; version = game.Version; if (game.IsDeployedBuild) From a7c2fd078f03bc9c1c808c54e3a5d2d8a6ae61cc Mon Sep 17 00:00:00 2001 From: recapitalverb <41869184+recapitalverb@users.noreply.github.com> Date: Fri, 14 Feb 2020 20:27:21 +0700 Subject: [PATCH 084/216] Fix remaining cases --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 6 +++--- osu.Game/Online/API/APIAccess.cs | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index a3128e36c4..8a0d981e49 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -150,12 +150,12 @@ namespace osu.Game.Beatmaps.Drawables }; } - private OsuColour colours; + [Resolved] + private OsuColour colours { get; set; } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { - this.colours = colours; background.Colour = colours.Gray3; } diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 23c931d161..ab87607112 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -9,6 +9,7 @@ using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json.Linq; +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.ExceptionExtensions; using osu.Framework.Graphics; @@ -21,7 +22,9 @@ namespace osu.Game.Online.API { public class APIAccess : Component, IAPIProvider { - private readonly OsuConfigManager config; + [Resolved] + private OsuConfigManager config { get; set; } + private readonly OAuth authentication; public string Endpoint => @"https://osu.ppy.sh"; From 10798aeab3ec493cec17daab1746e23a609c8cc2 Mon Sep 17 00:00:00 2001 From: recapitalverb <41869184+recapitalverb@users.noreply.github.com> Date: Fri, 14 Feb 2020 20:30:27 +0700 Subject: [PATCH 085/216] Fix code formatting --- osu.Game/Overlays/DirectOverlay.cs | 2 +- .../Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs | 1 + osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 6cc48f09bd..a6f8b65a0d 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -226,7 +226,7 @@ namespace osu.Game.Overlays private readonly Bindable currentQuery = new Bindable(string.Empty); private ScheduledDelegate queryChangedDebounce; - + [Resolved] private PreviewTrackManager previewTrackManager { get; set; } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index 3cc233ef73..3da64e0de4 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -16,6 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio [Resolved] private AudioManager audio { get; set; } + private SettingsDropdown dropdown; protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index db59d8a4de..bf7329b305 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -32,6 +32,7 @@ namespace osu.Game.Screens.Select.Carousel [Resolved] private DialogOverlay dialogOverlay { get; set; } + private readonly BeatmapSetInfo beatmapSet; public DrawableCarouselBeatmapSet(CarouselBeatmapSet set) From c46d8287164a88c70703598c169531684a89e596 Mon Sep 17 00:00:00 2001 From: recapitalverb <41869184+recapitalverb@users.noreply.github.com> Date: Fri, 14 Feb 2020 20:59:51 +0700 Subject: [PATCH 086/216] Preserve permitNulls --- osu.Game/Online/Chat/ExternalLinkOpener.cs | 4 ++-- osu.Game/Online/DownloadTrackingComposite.cs | 2 +- osu.Game/Overlays/AccountCreation/ScreenWarning.cs | 2 +- osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs | 2 +- .../Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Online/Chat/ExternalLinkOpener.cs b/osu.Game/Online/Chat/ExternalLinkOpener.cs index da90ea6845..a5958d38cb 100644 --- a/osu.Game/Online/Chat/ExternalLinkOpener.cs +++ b/osu.Game/Online/Chat/ExternalLinkOpener.cs @@ -13,10 +13,10 @@ namespace osu.Game.Online.Chat { public class ExternalLinkOpener : Component { - [Resolved] + [Resolved(CanBeNull = true)] private GameHost host { get; set; } - [Resolved] + [Resolved(CanBeNull = true)] private DialogOverlay dialogOverlay { get; set; } private Bindable externalLinkWarning; diff --git a/osu.Game/Online/DownloadTrackingComposite.cs b/osu.Game/Online/DownloadTrackingComposite.cs index 9eb5f36729..6e7ef99c6d 100644 --- a/osu.Game/Online/DownloadTrackingComposite.cs +++ b/osu.Game/Online/DownloadTrackingComposite.cs @@ -19,7 +19,7 @@ namespace osu.Game.Online { protected readonly Bindable Model = new Bindable(); - [Resolved] + [Resolved(CanBeNull = true)] private TModelManager manager { get; set; } /// diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index 3c3c27ab6f..5375476c9e 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.AccountCreation private OsuTextFlowContainer multiAccountExplanationText; private LinkFlowContainer furtherAssistance; - [Resolved] + [Resolved(CanBeNull = true)] private IAPIProvider api { get; set; } private const string help_centre_url = "/help/wiki/Help_Centre#login"; diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index 31aca11b86..d9eeec9f85 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -37,7 +37,7 @@ namespace osu.Game.Screens.Select.Carousel private Triangles triangles; private StarCounter starCounter; - [Resolved] + [Resolved(CanBeNull = true)] private BeatmapSetOverlay beatmapOverlay { get; set; } public DrawableCarouselBeatmap(CarouselBeatmap panel) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index bf7329b305..997f2382fc 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -30,7 +30,7 @@ namespace osu.Game.Screens.Select.Carousel private Action restoreHiddenRequested; private Action viewDetails; - [Resolved] + [Resolved(CanBeNull = true)] private DialogOverlay dialogOverlay { get; set; } private readonly BeatmapSetInfo beatmapSet; From 61d539dc6794b1108aeab5e065a322f7e7b53795 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 23:39:39 +0900 Subject: [PATCH 087/216] Fix first playlist item not getting selected --- .../Multiplayer/TestSceneMatchSubScreen.cs | 99 +++++++++++++------ .../Screens/Multi/Match/MatchSubScreen.cs | 21 ++-- 2 files changed, 81 insertions(+), 39 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs index 61def4be1a..7f79e306ad 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs @@ -3,19 +3,28 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Screens; +using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; +using osu.Game.Screens.Multi; using osu.Game.Screens.Multi.Match; using osu.Game.Screens.Multi.Match.Components; +using osu.Game.Tests.Beatmaps; using osu.Game.Users; +using osuTK.Input; +using Header = osu.Game.Screens.Multi.Match.Components.Header; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMatchSubScreen : ScreenTestScene + public class TestSceneMatchSubScreen : MultiplayerTestScene { protected override bool UseOnlineAPI => true; @@ -27,8 +36,8 @@ namespace osu.Game.Tests.Visual.Multiplayer typeof(Footer) }; - [Cached] - private readonly Bindable currentRoom = new Bindable(); + [Cached(typeof(IRoomManager))] + private readonly TestRoomManager roomManager = new TestRoomManager(); [Resolved] private BeatmapManager beatmaps { get; set; } @@ -36,51 +45,77 @@ namespace osu.Game.Tests.Visual.Multiplayer [Resolved] private RulesetStore rulesets { get; set; } - public TestSceneMatchSubScreen() + private TestMatchSubScreen match; + + [SetUp] + public void Setup() => Schedule(() => { - currentRoom.Value = new Room(); + Room.CopyFrom(new Room()); + }); + + [SetUpSteps] + public void SetupSteps() + { + AddStep("load match", () => LoadScreen(match = new TestMatchSubScreen(Room))); + AddUntilStep("wait for load", () => match.IsCurrentScreen()); } [Test] - public void TestShowRoom() + public void TestPlaylistItemSelectedOnCreate() { - AddStep(@"show", () => + AddStep("set room properties", () => { - currentRoom.Value.RoomID.Value = 1; - currentRoom.Value.Availability.Value = RoomAvailability.Public; - currentRoom.Value.Duration.Value = TimeSpan.FromHours(24); - currentRoom.Value.Host.Value = new User { Username = "peppy", Id = 2 }; - currentRoom.Value.Name.Value = "super secret room"; - currentRoom.Value.Participants.AddRange(new[] + Room.Name.Value = "my awesome room"; + Room.Host.Value = new User { Id = 2, Username = "peppy" }; + Room.Playlist.Add(new PlaylistItem { - new User { Username = "peppy", Id = 2 }, - new User { Username = "smoogipoo", Id = 1040328 } + Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, + Ruleset = { Value = new OsuRuleset().RulesetInfo } }); - currentRoom.Value.Playlist.Add(new PlaylistItem - { - Beatmap = { Value = beatmaps.GetAllUsableBeatmapSets()[0].Beatmaps[0] }, - Ruleset = { Value = rulesets.GetRuleset(2) }, - }); - - LoadScreen(new MatchSubScreen(currentRoom.Value)); }); + + AddStep("move mouse to create button", () => + { + var footer = match.ChildrenOfType