1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-06 21:12:55 +08:00

Optimise leaderboard display

Adds async loading support and cleans up the code quite a bit in the process.
This commit is contained in:
Dean Herbert 2017-11-16 21:29:07 +09:00
parent f6bdfa9876
commit 6c40cf08cc
3 changed files with 87 additions and 107 deletions

View File

@ -7,7 +7,7 @@ using OpenTK.Input;
namespace osu.Game.Graphics.Containers namespace osu.Game.Graphics.Containers
{ {
internal class OsuScrollContainer : ScrollContainer public class OsuScrollContainer : ScrollContainer
{ {
/// <summary> /// <summary>
/// Allows controlling the scroll bar from any position in the container using the right mouse button. /// Allows controlling the scroll bar from any position in the container using the right mouse button.

View File

@ -17,19 +17,21 @@ using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests;
using System.Linq;
namespace osu.Game.Screens.Select.Leaderboards namespace osu.Game.Screens.Select.Leaderboards
{ {
public class Leaderboard : Container public class Leaderboard : Container
{ {
private readonly ScrollContainer scrollContainer; private readonly ScrollContainer scrollContainer;
private readonly FillFlowContainer<LeaderboardScore> scrollFlow; private FillFlowContainer<LeaderboardScore> scrollFlow;
public Action<Score> ScoreSelected; public Action<Score> ScoreSelected;
private readonly LoadingAnimation loading; private readonly LoadingAnimation loading;
private IEnumerable<Score> scores; private IEnumerable<Score> scores;
public IEnumerable<Score> Scores public IEnumerable<Score> Scores
{ {
get { return scores; } get { return scores; }
@ -41,33 +43,43 @@ namespace osu.Game.Screens.Select.Leaderboards
int i = 150; int i = 150;
if (scores == null) if (scores == null)
{ {
foreach (var c in scrollFlow.Children) if (scrollFlow != null)
c.FadeOut(i += 10); {
foreach (var c in scrollFlow.Children)
c.FadeOut(i += 10);
foreach (var c in scrollFlow.Children) foreach (var c in scrollFlow.Children)
c.LifetimeEnd = Time.Current + i; c.LifetimeEnd = Time.Current + i;
}
return; return;
} }
scrollFlow.Clear(); // schedule because we may not be loaded yet (LoadComponentAsync complains).
Schedule(() =>
i = 0;
foreach (var s in scores)
{ {
var ls = new LeaderboardScore(s, 1 + i) LoadComponentAsync(new FillFlowContainer<LeaderboardScore>
{ {
AlwaysPresent = true, RelativeSizeAxes = Axes.X,
Action = () => ScoreSelected?.Invoke(s), AutoSizeAxes = Axes.Y,
State = Visibility.Hidden, Spacing = new Vector2(0f, 5f),
}; Padding = new MarginPadding { Top = 10, Bottom = 5 },
scrollFlow.Add(ls); ChildrenEnumerable = scores.Select(s => new LeaderboardScore(s, 1 + i) { Action = () => ScoreSelected?.Invoke(s) })
}, f =>
{
scrollFlow?.Expire();
scrollContainer.Add(scrollFlow = f);
using (BeginDelayedSequence(i++ * 50, true)) i = 0;
ls.Show(); foreach (var s in f.Children)
} {
using (s.BeginDelayedSequence(i++ * 50, true))
s.Show();
}
scrollContainer.ScrollTo(0f, false); scrollContainer.ScrollTo(0f, false);
});
});
} }
} }
@ -79,16 +91,6 @@ namespace osu.Game.Screens.Select.Leaderboards
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
ScrollbarVisible = false, ScrollbarVisible = false,
Children = new Drawable[]
{
scrollFlow = new FillFlowContainer<LeaderboardScore>
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(0f, 5f),
Padding = new MarginPadding { Top = 10, Bottom = 5 },
},
},
}, },
loading = new LoadingAnimation() loading = new LoadingAnimation()
}; };
@ -152,6 +154,8 @@ namespace osu.Game.Screens.Select.Leaderboards
if (!scrollContainer.IsScrolledToEnd()) if (!scrollContainer.IsScrolledToEnd())
fadeStart -= LeaderboardScore.HEIGHT; fadeStart -= LeaderboardScore.HEIGHT;
if (scrollFlow == null) return;
foreach (var c in scrollFlow.Children) foreach (var c in scrollFlow.Children)
{ {
var topY = c.ToSpaceOfOtherDrawable(Vector2.Zero, scrollFlow).Y; var topY = c.ToSpaceOfOtherDrawable(Vector2.Zero, scrollFlow).Y;

View File

@ -2,9 +2,10 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
using System.Linq;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -13,14 +14,13 @@ using osu.Framework.Input;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Screens.Select.Leaderboards namespace osu.Game.Screens.Select.Leaderboards
{ {
public class LeaderboardScore : OsuClickableContainer, IStateful<Visibility> public class LeaderboardScore : OsuClickableContainer
{ {
public static readonly float HEIGHT = 60; public static readonly float HEIGHT = 60;
@ -34,72 +34,16 @@ namespace osu.Game.Screens.Select.Leaderboards
private const float background_alpha = 0.25f; private const float background_alpha = 0.25f;
private const float rank_width = 30; private const float rank_width = 30;
private readonly Box background; private Box background;
private readonly Container content; private Container content;
private readonly Container avatar; private Container avatar;
private readonly DrawableRank scoreRank; private DrawableRank scoreRank;
private readonly OsuSpriteText nameLabel; private OsuSpriteText nameLabel;
private readonly GlowingSpriteText scoreLabel; private GlowingSpriteText scoreLabel;
private readonly ScoreComponentLabel maxCombo; private ScoreComponentLabel maxCombo;
private readonly ScoreComponentLabel accuracy; private ScoreComponentLabel accuracy;
private readonly Container flagBadgeContainer; private Container flagBadgeContainer;
private readonly FillFlowContainer<ModIcon> modsContainer; private FillFlowContainer<ModIcon> modsContainer;
private Visibility state;
public Visibility State
{
get { return state; }
set
{
if (state == value)
return;
state = value;
switch (state)
{
case Visibility.Hidden:
foreach (var d in new Drawable[] { avatar, nameLabel, scoreLabel, scoreRank, flagBadgeContainer, maxCombo, accuracy, modsContainer })
d.FadeOut();
Alpha = 0;
content.MoveToY(75);
avatar.MoveToX(75);
nameLabel.MoveToX(150);
break;
case Visibility.Visible:
this.FadeIn(200);
content.MoveToY(0, 800, Easing.OutQuint);
using (BeginDelayedSequence(100, true))
{
avatar.FadeIn(300, Easing.OutQuint);
nameLabel.FadeIn(350, Easing.OutQuint);
avatar.MoveToX(0, 300, Easing.OutQuint);
nameLabel.MoveToX(0, 350, Easing.OutQuint);
using (BeginDelayedSequence(250, true))
{
scoreLabel.FadeIn(200);
scoreRank.FadeIn(200);
using (BeginDelayedSequence(50, true))
{
var drawables = new Drawable[] { flagBadgeContainer, maxCombo, accuracy, modsContainer, };
for (int i = 0; i < drawables.Length; i++)
drawables[i].FadeIn(100 + i * 50);
}
}
}
break;
}
StateChanged?.Invoke(State);
}
}
public LeaderboardScore(Score score, int rank) public LeaderboardScore(Score score, int rank)
{ {
@ -108,7 +52,11 @@ namespace osu.Game.Screens.Select.Leaderboards
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Height = HEIGHT; Height = HEIGHT;
}
[BackgroundDependencyLoader]
private void load()
{
Children = new Drawable[] Children = new Drawable[]
{ {
new Container new Container
@ -255,23 +203,51 @@ namespace osu.Game.Screens.Select.Leaderboards
Origin = Anchor.BottomRight, Origin = Anchor.BottomRight,
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal, Direction = FillDirection.Horizontal,
ChildrenEnumerable = Score.Mods.Select(mod => new ModIcon(mod) { Scale = new Vector2(0.375f) })
}, },
}, },
}, },
}, },
}, },
}; };
foreach (Mod mod in Score.Mods)
{
modsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.375f) });
}
} }
public void ToggleVisibility() => State = State == Visibility.Visible ? Visibility.Hidden : Visibility.Visible; public override void Show()
{
foreach (var d in new Drawable[] { avatar, nameLabel, scoreLabel, scoreRank, flagBadgeContainer, maxCombo, accuracy, modsContainer })
d.FadeOut();
public override void Hide() => State = Visibility.Hidden; Alpha = 0;
public override void Show() => State = Visibility.Visible;
content.MoveToY(75);
avatar.MoveToX(75);
nameLabel.MoveToX(150);
this.FadeIn(200);
content.MoveToY(0, 800, Easing.OutQuint);
using (BeginDelayedSequence(100, true))
{
avatar.FadeIn(300, Easing.OutQuint);
nameLabel.FadeIn(350, Easing.OutQuint);
avatar.MoveToX(0, 300, Easing.OutQuint);
nameLabel.MoveToX(0, 350, Easing.OutQuint);
using (BeginDelayedSequence(250, true))
{
scoreLabel.FadeIn(200);
scoreRank.FadeIn(200);
using (BeginDelayedSequence(50, true))
{
var drawables = new Drawable[] { flagBadgeContainer, maxCombo, accuracy, modsContainer, };
for (int i = 0; i < drawables.Length; i++)
drawables[i].FadeIn(100 + i * 50);
}
}
}
}
protected override bool OnHover(InputState state) protected override bool OnHover(InputState state)
{ {