From 26bb3715fecd3ca4e3f43e77ad7fc6075e7f4f1f Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Fri, 22 Dec 2017 22:41:18 +0900 Subject: [PATCH 1/3] Improve state and feel of leaderboard placeholders Closes #1721. --- .../Select/Leaderboards/Leaderboard.cs | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs index b3f2649ab6..4b5eefe5b6 100644 --- a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Select.Leaderboards { public class Leaderboard : Container { - private const double fade_duration = 200; + private const double fade_duration = 300; private readonly ScrollContainer scrollContainer; private readonly Container placeholderContainer; @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Select.Leaderboards { scores = value; - scrollFlow?.FadeOut(fade_duration).Expire(); + scrollFlow?.FadeOut(fade_duration, Easing.OutQuint).Expire(); scrollFlow = null; loading.Hide(); @@ -90,6 +90,7 @@ namespace osu.Game.Screens.Select.Leaderboards } private LeaderboardScope scope; + public LeaderboardScope Scope { get { return scope; } @@ -103,6 +104,7 @@ namespace osu.Game.Screens.Select.Leaderboards } private PlaceholderState placeholderState; + protected PlaceholderState PlaceholderState { get { return placeholderState; } @@ -118,19 +120,18 @@ namespace osu.Game.Screens.Select.Leaderboards OnRetry = updateScores, }); break; - + case PlaceholderState.Unavailable: + replacePlaceholder(new MessagePlaceholder(@"Leaderboards are not available for this beatmap!")); + break; case PlaceholderState.NoScores: replacePlaceholder(new MessagePlaceholder(@"No records yet!")); break; - case PlaceholderState.NotLoggedIn: replacePlaceholder(new MessagePlaceholder(@"Please login to view online leaderboards!")); break; - case PlaceholderState.NotSupporter: replacePlaceholder(new MessagePlaceholder(@"Please invest in a supporter tag to view this leaderboard!")); break; - default: replacePlaceholder(null); break; @@ -150,10 +151,7 @@ namespace osu.Game.Screens.Select.Leaderboards loading = new LoadingAnimation(), placeholderContainer = new Container { - Alpha = 0, - AutoSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both }, }; } @@ -229,15 +227,15 @@ namespace osu.Game.Screens.Select.Leaderboards return; } - if (api?.IsLoggedIn != true) + if (Beatmap?.OnlineBeatmapID == null) { - PlaceholderState = PlaceholderState.NotLoggedIn; + PlaceholderState = PlaceholderState.Unavailable; return; } - if (Beatmap?.OnlineBeatmapID == null) + if (api?.IsLoggedIn != true) { - PlaceholderState = PlaceholderState.NetworkFailure; + PlaceholderState = PlaceholderState.NotLoggedIn; return; } @@ -272,23 +270,22 @@ namespace osu.Game.Screens.Select.Leaderboards private void replacePlaceholder(Placeholder placeholder) { - if (placeholder == null) - { - placeholderContainer.FadeOutFromOne(fade_duration, Easing.OutQuint); - placeholderContainer.Clear(true); + var existingPlaceholder = placeholderContainer.Children.LastOrDefault() as Placeholder; + + if (placeholder != null && placeholder.Equals(existingPlaceholder)) return; - } - var existingPlaceholder = placeholderContainer.Children.FirstOrDefault() as Placeholder; + existingPlaceholder?.FadeOut(150, Easing.OutQuint).Expire(); - if (placeholder.Equals(existingPlaceholder)) + if (placeholder == null) return; Scores = null; - placeholderContainer.Clear(true); - placeholderContainer.Child = placeholder; - placeholderContainer.FadeInFromZero(fade_duration, Easing.OutQuint); + placeholderContainer.Add(placeholder); + + placeholder.ScaleTo(0.8f).Then().ScaleTo(1, fade_duration * 3, Easing.OutQuint); + placeholder.FadeInFromZero(fade_duration, Easing.OutQuint); } protected override void Update() @@ -322,6 +319,12 @@ namespace osu.Game.Screens.Select.Leaderboards private abstract class Placeholder : FillFlowContainer, IEquatable<Placeholder> { + protected Placeholder() + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + } + public virtual bool Equals(Placeholder other) => GetType() == other?.GetType(); } @@ -429,6 +432,7 @@ namespace osu.Game.Screens.Select.Leaderboards Successful, Retrieving, NetworkFailure, + Unavailable, NoScores, NotLoggedIn, NotSupporter, From bdda1570d1540148ee31f16107897fbb3359ef11 Mon Sep 17 00:00:00 2001 From: Dean Herbert <pe@ppy.sh> Date: Fri, 22 Dec 2017 22:44:18 +0900 Subject: [PATCH 2/3] Move Placeholder classes to own files --- .../Select/Leaderboards/Leaderboard.cs | 106 ------------------ .../Select/Leaderboards/MessagePlaceholder.cs | 38 +++++++ .../Select/Leaderboards/Placeholder.cs | 20 ++++ .../RetrievalFailurePlaceholder.cs | 77 +++++++++++++ osu.Game/osu.Game.csproj | 3 + 5 files changed, 138 insertions(+), 106 deletions(-) create mode 100644 osu.Game/Screens/Select/Leaderboards/MessagePlaceholder.cs create mode 100644 osu.Game/Screens/Select/Leaderboards/Placeholder.cs create mode 100644 osu.Game/Screens/Select/Leaderboards/RetrievalFailurePlaceholder.cs diff --git a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs index 4b5eefe5b6..c15a179e8c 100644 --- a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs @@ -19,11 +19,8 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests; using System.Linq; using osu.Framework.Configuration; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics; using osu.Framework.Logging; using osu.Game.Rulesets; -using osu.Framework.Input; namespace osu.Game.Screens.Select.Leaderboards { @@ -157,9 +154,7 @@ namespace osu.Game.Screens.Select.Leaderboards } private APIAccess api; - private BeatmapInfo beatmap; - private OsuGame osuGame; private ScheduledDelegate pendingBeatmapSwitch; @@ -316,107 +311,6 @@ namespace osu.Game.Screens.Select.Leaderboards } } } - - private abstract class Placeholder : FillFlowContainer, IEquatable<Placeholder> - { - protected Placeholder() - { - Anchor = Anchor.Centre; - Origin = Anchor.Centre; - } - - public virtual bool Equals(Placeholder other) => GetType() == other?.GetType(); - } - - private class MessagePlaceholder : Placeholder - { - private readonly string message; - - public MessagePlaceholder(string message) - { - Direction = FillDirection.Horizontal; - AutoSizeAxes = Axes.Both; - Children = new Drawable[] - { - new SpriteIcon - { - Icon = FontAwesome.fa_exclamation_circle, - Size = new Vector2(26), - Margin = new MarginPadding { Right = 10 }, - }, - new OsuSpriteText - { - Text = this.message = message, - TextSize = 22, - }, - }; - } - - public override bool Equals(Placeholder other) => (other as MessagePlaceholder)?.message == message; - } - - private class RetrievalFailurePlaceholder : Placeholder - { - public Action OnRetry; - - public RetrievalFailurePlaceholder() - { - Direction = FillDirection.Horizontal; - AutoSizeAxes = Axes.Both; - Children = new Drawable[] - { - new RetryButton - { - Action = () => OnRetry?.Invoke(), - Margin = new MarginPadding { Right = 10 }, - }, - new OsuSpriteText - { - Anchor = Anchor.TopLeft, - Text = @"Couldn't retrieve scores!", - TextSize = 22, - }, - }; - } - - private class RetryButton : OsuHoverContainer - { - private readonly SpriteIcon icon; - - public Action Action; - - public RetryButton() - { - Height = 26; - Width = 26; - Child = new OsuClickableContainer - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Action = () => Action?.Invoke(), - Child = icon = new SpriteIcon - { - Icon = FontAwesome.fa_refresh, - Size = new Vector2(26), - Shadow = true, - }, - }; - } - - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) - { - icon.ScaleTo(0.8f, 4000, Easing.OutQuint); - return base.OnMouseDown(state, args); - } - - protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) - { - icon.ScaleTo(1, 1000, Easing.OutElastic); - return base.OnMouseUp(state, args); - } - } - } } public enum LeaderboardScope diff --git a/osu.Game/Screens/Select/Leaderboards/MessagePlaceholder.cs b/osu.Game/Screens/Select/Leaderboards/MessagePlaceholder.cs new file mode 100644 index 0000000000..4f94087d30 --- /dev/null +++ b/osu.Game/Screens/Select/Leaderboards/MessagePlaceholder.cs @@ -0,0 +1,38 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using OpenTK; + +namespace osu.Game.Screens.Select.Leaderboards +{ + public class MessagePlaceholder : Placeholder + { + private readonly string message; + + public MessagePlaceholder(string message) + { + Direction = FillDirection.Horizontal; + AutoSizeAxes = Axes.Both; + Children = new Drawable[] + { + new SpriteIcon + { + Icon = FontAwesome.fa_exclamation_circle, + Size = new Vector2(26), + Margin = new MarginPadding { Right = 10 }, + }, + new OsuSpriteText + { + Text = this.message = message, + TextSize = 22, + }, + }; + } + + public override bool Equals(Placeholder other) => (other as MessagePlaceholder)?.message == message; + } +} diff --git a/osu.Game/Screens/Select/Leaderboards/Placeholder.cs b/osu.Game/Screens/Select/Leaderboards/Placeholder.cs new file mode 100644 index 0000000000..8427259106 --- /dev/null +++ b/osu.Game/Screens/Select/Leaderboards/Placeholder.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Screens.Select.Leaderboards +{ + public abstract class Placeholder : FillFlowContainer, IEquatable<Placeholder> + { + protected Placeholder() + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + } + + public virtual bool Equals(Placeholder other) => GetType() == other?.GetType(); + } +} diff --git a/osu.Game/Screens/Select/Leaderboards/RetrievalFailurePlaceholder.cs b/osu.Game/Screens/Select/Leaderboards/RetrievalFailurePlaceholder.cs new file mode 100644 index 0000000000..7563c08c8b --- /dev/null +++ b/osu.Game/Screens/Select/Leaderboards/RetrievalFailurePlaceholder.cs @@ -0,0 +1,77 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using OpenTK; + +namespace osu.Game.Screens.Select.Leaderboards +{ + public class RetrievalFailurePlaceholder : Placeholder + { + public Action OnRetry; + + public RetrievalFailurePlaceholder() + { + Direction = FillDirection.Horizontal; + AutoSizeAxes = Axes.Both; + Children = new Drawable[] + { + new RetryButton + { + Action = () => OnRetry?.Invoke(), + Margin = new MarginPadding { Right = 10 }, + }, + new OsuSpriteText + { + Anchor = Anchor.TopLeft, + Text = @"Couldn't retrieve scores!", + TextSize = 22, + }, + }; + } + + public class RetryButton : OsuHoverContainer + { + private readonly SpriteIcon icon; + + public Action Action; + + public RetryButton() + { + Height = 26; + Width = 26; + Child = new OsuClickableContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Action = () => Action?.Invoke(), + Child = icon = new SpriteIcon + { + Icon = FontAwesome.fa_refresh, + Size = new Vector2(26), + Shadow = true, + }, + }; + } + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + icon.ScaleTo(0.8f, 4000, Easing.OutQuint); + return base.OnMouseDown(state, args); + } + + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) + { + icon.ScaleTo(1, 1000, Easing.OutElastic); + return base.OnMouseUp(state, args); + } + } + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 1004d9dc95..1c78ba379e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -781,6 +781,9 @@ <Compile Include="Screens\Select\Leaderboards\DrawableRank.cs" /> <Compile Include="Screens\Select\Leaderboards\Leaderboard.cs" /> <Compile Include="Screens\Select\Leaderboards\LeaderboardScore.cs" /> + <Compile Include="Screens\Select\Leaderboards\MessagePlaceholder.cs" /> + <Compile Include="Screens\Select\Leaderboards\Placeholder.cs" /> + <Compile Include="Screens\Select\Leaderboards\RetrievalFailurePlaceholder.cs" /> <Compile Include="Screens\Select\MatchSongSelect.cs" /> <Compile Include="Screens\Select\Options\BeatmapOptionsButton.cs" /> <Compile Include="Screens\Select\Options\BeatmapOptionsOverlay.cs" /> From 1f44e98f9cc823760897cf15d83f937890df21a1 Mon Sep 17 00:00:00 2001 From: smoogipoo <smoogipoo@smgi.me> Date: Sat, 23 Dec 2017 20:17:12 +0900 Subject: [PATCH 3/3] Add unavailable state to testcase --- osu.Game.Tests/Visual/TestCaseLeaderboard.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs b/osu.Game.Tests/Visual/TestCaseLeaderboard.cs index 30a442594c..a01dbb7a6b 100644 --- a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs +++ b/osu.Game.Tests/Visual/TestCaseLeaderboard.cs @@ -36,6 +36,7 @@ namespace osu.Game.Tests.Visual AddStep(@"Network failure", () => leaderboard.SetRetrievalState(PlaceholderState.NetworkFailure)); AddStep(@"No supporter", () => leaderboard.SetRetrievalState(PlaceholderState.NotSupporter)); AddStep(@"Not logged in", () => leaderboard.SetRetrievalState(PlaceholderState.NotLoggedIn)); + AddStep(@"Unavailable", () => leaderboard.SetRetrievalState(PlaceholderState.Unavailable)); AddStep(@"Real beatmap", realBeatmap); }