Merge pull request #1728 from peppy/fix-leaderboard-placeholder

Improve state and feel of leaderboard placeholders
This commit is contained in:
Dan Balasescu 2017-12-23 20:27:11 +09:00 committed by GitHub
commit ea90c0cf40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 161 additions and 124 deletions

View File

@ -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);
}

View File

@ -19,17 +19,14 @@ 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
{
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 +48,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 +87,7 @@ namespace osu.Game.Screens.Select.Leaderboards
}
private LeaderboardScope scope;
public LeaderboardScope Scope
{
get { return scope; }
@ -103,6 +101,7 @@ namespace osu.Game.Screens.Select.Leaderboards
}
private PlaceholderState placeholderState;
protected PlaceholderState PlaceholderState
{
get { return placeholderState; }
@ -118,19 +117,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,18 +148,13 @@ 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
},
};
}
private APIAccess api;
private BeatmapInfo beatmap;
private OsuGame osuGame;
private ScheduledDelegate pendingBeatmapSwitch;
@ -229,15 +222,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 +265,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()
@ -319,101 +311,6 @@ namespace osu.Game.Screens.Select.Leaderboards
}
}
}
private abstract class Placeholder : FillFlowContainer, IEquatable<Placeholder>
{
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
@ -429,6 +326,7 @@ namespace osu.Game.Screens.Select.Leaderboards
Successful,
Retrieving,
NetworkFailure,
Unavailable,
NoScores,
NotLoggedIn,
NotSupporter,

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}
}
}

View File

@ -785,6 +785,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" />