Leaderboard design updates

This commit is contained in:
Dean Herbert
2018-12-27 15:30:02 +09:00
parent 1e71c5c9c4
commit 67e200e1b2
11 changed files with 118 additions and 57 deletions

View File

@ -19,13 +19,13 @@ using osu.Game.Users;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
public class TestCaseMultiResults : OsuTestCase public class TestCaseMatchResults : OsuTestCase
{ {
public override IReadOnlyList<Type> RequiredTypes => new[] public override IReadOnlyList<Type> RequiredTypes => new[]
{ {
typeof(MatchResults), typeof(MatchResults),
typeof(RoomLeaderboardPageInfo), typeof(RoomLeaderboardPageInfo),
typeof(RoomRankingResultsPage) typeof(RoomLeaderboardPage)
}; };
[Resolved] [Resolved]
@ -49,7 +49,11 @@ namespace osu.Game.Tests.Visual
private readonly Room room; private readonly Room room;
public TestMatchResults(ScoreInfo score) public TestMatchResults(ScoreInfo score)
: this(score, new Room()) : this(score, new Room
{
RoomID = { Value = 1 },
Name = { Value = "an awesome room" }
})
{ {
} }
@ -76,12 +80,12 @@ namespace osu.Game.Tests.Visual
this.room = room; this.room = room;
} }
public override ResultsPage CreatePage() => new TestRoomRankingResultsPage(score, beatmap, room); public override ResultsPage CreatePage() => new TestRoomLeaderboardPage(score, beatmap, room);
} }
private class TestRoomRankingResultsPage : RoomRankingResultsPage private class TestRoomLeaderboardPage : RoomLeaderboardPage
{ {
public TestRoomRankingResultsPage(ScoreInfo score, WorkingBeatmap beatmap, Room room) public TestRoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap, Room room)
: base(score, beatmap, room) : base(score, beatmap, room)
{ {
} }
@ -89,7 +93,7 @@ namespace osu.Game.Tests.Visual
protected override MatchLeaderboard CreateLeaderboard(Room room) => new TestMatchLeaderboard(room); protected override MatchLeaderboard CreateLeaderboard(Room room) => new TestMatchLeaderboard(room);
} }
private class TestMatchLeaderboard : MatchLeaderboard private class TestMatchLeaderboard : RoomLeaderboardPage.ResultsMatchLeaderboard
{ {
public TestMatchLeaderboard(Room room) public TestMatchLeaderboard(Room room)
: base(room) : base(room)

View File

@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual
typeof(Results), typeof(Results),
typeof(ResultsPage), typeof(ResultsPage),
typeof(ScoreResultsPage), typeof(ScoreResultsPage),
typeof(RankingResultsPage) typeof(LocalLeaderboardPage)
}; };
[BackgroundDependencyLoader] [BackgroundDependencyLoader]

View File

@ -18,7 +18,7 @@ using osuTK.Graphics;
namespace osu.Game.Online.Leaderboards namespace osu.Game.Online.Leaderboards
{ {
public abstract class Leaderboard<TScope, ScoreInfo> : Container public abstract class Leaderboard<TScope, ScoreInfo> : Container, IOnlineComponent
{ {
private const double fade_duration = 300; private const double fade_duration = 300;
@ -55,14 +55,8 @@ namespace osu.Game.Online.Leaderboards
// ensure placeholder is hidden when displaying scores // ensure placeholder is hidden when displaying scores
PlaceholderState = PlaceholderState.Successful; PlaceholderState = PlaceholderState.Successful;
var flow = scrollFlow = new FillFlowContainer<LeaderboardScore> scrollFlow = CreateScoreFlow();
{ scrollFlow.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1));
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(0f, 5f),
Padding = new MarginPadding { Top = 10, Bottom = 5 },
ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1))
};
// schedule because we may not be loaded yet (LoadComponentAsync complains). // schedule because we may not be loaded yet (LoadComponentAsync complains).
showScoresDelegate?.Cancel(); showScoresDelegate?.Cancel();
@ -71,12 +65,12 @@ namespace osu.Game.Online.Leaderboards
else else
showScores(); showScores();
void showScores() => LoadComponentAsync(flow, _ => void showScores() => LoadComponentAsync(scrollFlow, _ =>
{ {
scrollContainer.Add(flow); scrollContainer.Add(scrollFlow);
int i = 0; int i = 0;
foreach (var s in flow.Children) foreach (var s in scrollFlow.Children)
{ {
using (s.BeginDelayedSequence(i++ * 50, true)) using (s.BeginDelayedSequence(i++ * 50, true))
s.Show(); s.Show();
@ -87,6 +81,16 @@ namespace osu.Game.Online.Leaderboards
} }
} }
protected virtual FillFlowContainer<LeaderboardScore> CreateScoreFlow()
=> new FillFlowContainer<LeaderboardScore>
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(0f, 5f),
Padding = new MarginPadding { Top = 10, Bottom = 5 },
};
private TScope scope; private TScope scope;
public TScope Scope public TScope Scope
@ -175,26 +179,22 @@ namespace osu.Game.Online.Leaderboards
private void load(APIAccess api) private void load(APIAccess api)
{ {
this.api = api; this.api = api;
api?.Register(this);
if (api != null)
api.OnStateChange += handleApiStateChange;
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
{ {
base.Dispose(isDisposing); base.Dispose(isDisposing);
api?.Unregister(this);
if (api != null)
api.OnStateChange -= handleApiStateChange;
} }
public void RefreshScores() => UpdateScores(); public void RefreshScores() => UpdateScores();
private APIRequest getScoresRequest; private APIRequest getScoresRequest;
private void handleApiStateChange(APIState oldState, APIState newState) public void APIStateChanged(APIAccess api, APIState state)
{ {
if (newState == APIState.Online) if (state == APIState.Online)
UpdateScores(); UpdateScores();
} }
@ -265,14 +265,18 @@ namespace osu.Game.Online.Leaderboards
currentPlaceholder = placeholder; currentPlaceholder = placeholder;
} }
protected virtual bool FadeBottom => true;
protected virtual bool FadeTop => true;
protected override void UpdateAfterChildren() protected override void UpdateAfterChildren()
{ {
base.UpdateAfterChildren(); base.UpdateAfterChildren();
var fadeStart = scrollContainer.Current + scrollContainer.DrawHeight; var fadeBottom = scrollContainer.Current + scrollContainer.DrawHeight;
var fadeTop = scrollContainer.Current + LeaderboardScore.HEIGHT;
if (!scrollContainer.IsScrolledToEnd()) if (!scrollContainer.IsScrolledToEnd())
fadeStart -= LeaderboardScore.HEIGHT; fadeBottom -= LeaderboardScore.HEIGHT;
if (scrollFlow == null) if (scrollFlow == null)
return; return;
@ -282,15 +286,23 @@ namespace osu.Game.Online.Leaderboards
var topY = c.ToSpaceOfOtherDrawable(Vector2.Zero, scrollFlow).Y; var topY = c.ToSpaceOfOtherDrawable(Vector2.Zero, scrollFlow).Y;
var bottomY = topY + LeaderboardScore.HEIGHT; var bottomY = topY + LeaderboardScore.HEIGHT;
if (bottomY < fadeStart) bool requireTopFade = FadeTop && topY <= fadeTop;
bool requireBottomFade = FadeBottom && bottomY >= fadeBottom;
if (!requireTopFade && !requireBottomFade)
c.Colour = Color4.White; c.Colour = Color4.White;
else if (topY > fadeStart + LeaderboardScore.HEIGHT) else if (topY > fadeBottom + LeaderboardScore.HEIGHT || bottomY < fadeTop - LeaderboardScore.HEIGHT)
c.Colour = Color4.Transparent; c.Colour = Color4.Transparent;
else else
{ {
c.Colour = ColourInfo.GradientVertical( if (bottomY - fadeBottom > 0 && FadeBottom)
Color4.White.Opacity(Math.Min(1 - (topY - fadeStart) / LeaderboardScore.HEIGHT, 1)), c.Colour = ColourInfo.GradientVertical(
Color4.White.Opacity(Math.Min(1 - (bottomY - fadeStart) / LeaderboardScore.HEIGHT, 1))); Color4.White.Opacity(Math.Min(1 - (topY - fadeBottom) / LeaderboardScore.HEIGHT, 1)),
Color4.White.Opacity(Math.Min(1 - (bottomY - fadeBottom) / LeaderboardScore.HEIGHT, 1)));
else if (FadeTop)
c.Colour = ColourInfo.GradientVertical(
Color4.White.Opacity(Math.Min(1 - (fadeTop - topY) / LeaderboardScore.HEIGHT, 1)),
Color4.White.Opacity(Math.Min(1 - (fadeTop - bottomY) / LeaderboardScore.HEIGHT, 1)));
} }
} }
} }

View File

@ -73,8 +73,8 @@ namespace osu.Game.Online.Leaderboards
{ {
new OsuSpriteText new OsuSpriteText
{ {
Anchor = Anchor.CentreLeft, Anchor = Anchor.Centre,
Origin = Anchor.CentreLeft, Origin = Anchor.Centre,
Font = @"Exo2.0-MediumItalic", Font = @"Exo2.0-MediumItalic",
TextSize = 22, TextSize = 22,
// ReSharper disable once ImpureMethodCallOnReadonlyValueField // ReSharper disable once ImpureMethodCallOnReadonlyValueField

View File

@ -23,7 +23,7 @@ namespace osu.Game.Screens.Multi.Ranking
protected override IEnumerable<IResultPageInfo> CreateResultPages() => new IResultPageInfo[] protected override IEnumerable<IResultPageInfo> CreateResultPages() => new IResultPageInfo[]
{ {
new ScoreOverviewPageInfo(Score, Beatmap), new ScoreOverviewPageInfo(Score, Beatmap),
new BeatmapLeaderboardPageInfo(Score, Beatmap), new LocalLeaderboardPageInfo(Score, Beatmap),
new RoomLeaderboardPageInfo(Score, Beatmap, room), new RoomLeaderboardPageInfo(Score, Beatmap, room),
}; };
} }

View File

@ -13,6 +13,7 @@ using osu.Framework.Lists;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Leaderboards;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Match.Components;
@ -20,7 +21,7 @@ using osu.Game.Screens.Ranking;
namespace osu.Game.Screens.Multi.Ranking.Pages namespace osu.Game.Screens.Multi.Ranking.Pages
{ {
public class RoomRankingResultsPage : ResultsPage public class RoomLeaderboardPage : ResultsPage
{ {
private readonly Room room; private readonly Room room;
@ -28,7 +29,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
private TextFlowContainer rankText; private TextFlowContainer rankText;
public RoomRankingResultsPage(ScoreInfo score, WorkingBeatmap beatmap, Room room) public RoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap, Room room)
: base(score, beatmap) : base(score, beatmap)
{ {
this.room = room; this.room = room;
@ -45,13 +46,13 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
{ {
new Box new Box
{ {
Colour = colours.GrayE, Colour = colours.Gray6,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
}, },
new BufferedContainer new BufferedContainer
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
BackgroundColour = colours.GrayE, BackgroundColour = colours.Gray6,
Child = leaderboard = CreateLeaderboard(room) Child = leaderboard = CreateLeaderboard(room)
}, },
rankText = new TextFlowContainer rankText = new TextFlowContainer
@ -61,7 +62,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Width = 0.5f, Width = 0.5f,
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
Y = 75, Y = 50,
TextAnchor = Anchor.TopCentre TextAnchor = Anchor.TopCentre
}, },
}; };
@ -70,14 +71,20 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
leaderboard.Anchor = Anchor.Centre; leaderboard.Anchor = Anchor.Centre;
leaderboard.RelativeSizeAxes = Axes.Both; leaderboard.RelativeSizeAxes = Axes.Both;
leaderboard.Height = 0.8f; leaderboard.Height = 0.8f;
leaderboard.Y = 95; leaderboard.Y = 55;
leaderboard.ScoresLoaded = scoresLoaded; leaderboard.ScoresLoaded = scoresLoaded;
} }
private void scoresLoaded(IEnumerable<APIRoomScoreInfo> scores) private void scoresLoaded(IEnumerable<APIRoomScoreInfo> scores)
{ {
Action<SpriteText> gray = s => s.Colour = colours.Gray8; Action<SpriteText> gray = s => s.Colour = colours.GrayC;
Action<SpriteText> white = s =>
{
s.TextSize *= 1.4f;
s.Colour = colours.GrayF;
};
rankText.AddText(room.Name + "\n", white);
rankText.AddText("You are placed ", gray); rankText.AddText("You are placed ", gray);
int index = scores.IndexOf(new APIRoomScoreInfo { User = Score.User }, new FuncEqualityComparer<APIRoomScoreInfo>((s1, s2) => s1.User.Id.Equals(s2.User.Id))); int index = scores.IndexOf(new APIRoomScoreInfo { User = Score.User }, new FuncEqualityComparer<APIRoomScoreInfo>((s1, s2) => s1.User.Id.Equals(s2.User.Id)));
@ -91,6 +98,42 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
rankText.AddText("in the room!", gray); rankText.AddText("in the room!", gray);
} }
protected virtual MatchLeaderboard CreateLeaderboard(Room room) => new MatchLeaderboard(room); protected virtual MatchLeaderboard CreateLeaderboard(Room room) => new ResultsMatchLeaderboard(room);
public class ResultsMatchLeaderboard : MatchLeaderboard
{
public ResultsMatchLeaderboard(Room room)
: base(room)
{
}
protected override LeaderboardScore CreateDrawableScore(APIRoomScoreInfo model, int index)
=> new ResultsMatchLeaderboardScore(model, index);
protected override FillFlowContainer<LeaderboardScore> CreateScoreFlow()
{
var flow = base.CreateScoreFlow();
flow.Padding = new MarginPadding
{
Top = LeaderboardScore.HEIGHT * 2,
Bottom = LeaderboardScore.HEIGHT * 3,
};
return flow;
}
private class ResultsMatchLeaderboardScore : MatchLeaderboardScore
{
public ResultsMatchLeaderboardScore(APIRoomScoreInfo score, int rank)
: base(score, rank)
{
}
[BackgroundDependencyLoader]
private void load()
{
}
}
}
} }
} }

View File

@ -23,10 +23,10 @@ namespace osu.Game.Screens.Multi.Ranking.Types
this.room = room; this.room = room;
} }
public FontAwesome Icon => FontAwesome.fa_list; public FontAwesome Icon => FontAwesome.fa_users;
public string Name => "Room Leaderboard"; public string Name => "Room Leaderboard";
public virtual ResultsPage CreatePage() => new RoomRankingResultsPage(score, beatmap, room); public virtual ResultsPage CreatePage() => new RoomLeaderboardPage(score, beatmap, room);
} }
} }

View File

@ -18,7 +18,7 @@ namespace osu.Game.Screens.Play
protected override IEnumerable<IResultPageInfo> CreateResultPages() => new IResultPageInfo[] protected override IEnumerable<IResultPageInfo> CreateResultPages() => new IResultPageInfo[]
{ {
new ScoreOverviewPageInfo(Score, Beatmap), new ScoreOverviewPageInfo(Score, Beatmap),
new BeatmapLeaderboardPageInfo(Score, Beatmap) new LocalLeaderboardPageInfo(Score, Beatmap)
}; };
} }
} }

View File

@ -12,9 +12,9 @@ using osuTK;
namespace osu.Game.Screens.Ranking.Pages namespace osu.Game.Screens.Ranking.Pages
{ {
public class RankingResultsPage : ResultsPage public class LocalLeaderboardPage : ResultsPage
{ {
public RankingResultsPage(ScoreInfo score, WorkingBeatmap beatmap = null) public LocalLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap = null)
: base(score, beatmap) : base(score, beatmap)
{ {
} }
@ -26,7 +26,7 @@ namespace osu.Game.Screens.Ranking.Pages
{ {
new Box new Box
{ {
Colour = colours.GrayE, Colour = colours.Gray6,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
}, },
new BeatmapLeaderboard new BeatmapLeaderboard

View File

@ -8,21 +8,21 @@ using osu.Game.Screens.Ranking.Pages;
namespace osu.Game.Screens.Ranking.Types namespace osu.Game.Screens.Ranking.Types
{ {
public class BeatmapLeaderboardPageInfo : IResultPageInfo public class LocalLeaderboardPageInfo : IResultPageInfo
{ {
private readonly ScoreInfo score; private readonly ScoreInfo score;
private readonly WorkingBeatmap beatmap; private readonly WorkingBeatmap beatmap;
public BeatmapLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap) public LocalLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap)
{ {
this.score = score; this.score = score;
this.beatmap = beatmap; this.beatmap = beatmap;
} }
public FontAwesome Icon => FontAwesome.fa_list; public FontAwesome Icon => FontAwesome.fa_user;
public string Name => @"Beatmap Leaderboard"; public string Name => @"Local Leaderboard";
public ResultsPage CreatePage() => new RankingResultsPage(score, beatmap); public ResultsPage CreatePage() => new LocalLeaderboardPage(score, beatmap);
} }
} }

View File

@ -36,6 +36,8 @@ namespace osu.Game.Screens.Select.Leaderboards
} }
} }
protected override bool FadeTop => false;
[Resolved] [Resolved]
private ScoreManager scoreManager { get; set; } private ScoreManager scoreManager { get; set; }