1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 10:52:53 +08:00

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
{
public class TestCaseMultiResults : OsuTestCase
public class TestCaseMatchResults : OsuTestCase
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(MatchResults),
typeof(RoomLeaderboardPageInfo),
typeof(RoomRankingResultsPage)
typeof(RoomLeaderboardPage)
};
[Resolved]
@ -49,7 +49,11 @@ namespace osu.Game.Tests.Visual
private readonly Room room;
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;
}
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)
{
}
@ -89,7 +93,7 @@ namespace osu.Game.Tests.Visual
protected override MatchLeaderboard CreateLeaderboard(Room room) => new TestMatchLeaderboard(room);
}
private class TestMatchLeaderboard : MatchLeaderboard
private class TestMatchLeaderboard : RoomLeaderboardPage.ResultsMatchLeaderboard
{
public TestMatchLeaderboard(Room room)
: base(room)

View File

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

View File

@ -18,7 +18,7 @@ using osuTK.Graphics;
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;
@ -55,14 +55,8 @@ namespace osu.Game.Online.Leaderboards
// ensure placeholder is hidden when displaying scores
PlaceholderState = PlaceholderState.Successful;
var flow = scrollFlow = new FillFlowContainer<LeaderboardScore>
{
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))
};
scrollFlow = CreateScoreFlow();
scrollFlow.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1));
// schedule because we may not be loaded yet (LoadComponentAsync complains).
showScoresDelegate?.Cancel();
@ -71,12 +65,12 @@ namespace osu.Game.Online.Leaderboards
else
showScores();
void showScores() => LoadComponentAsync(flow, _ =>
void showScores() => LoadComponentAsync(scrollFlow, _ =>
{
scrollContainer.Add(flow);
scrollContainer.Add(scrollFlow);
int i = 0;
foreach (var s in flow.Children)
foreach (var s in scrollFlow.Children)
{
using (s.BeginDelayedSequence(i++ * 50, true))
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;
public TScope Scope
@ -175,26 +179,22 @@ namespace osu.Game.Online.Leaderboards
private void load(APIAccess api)
{
this.api = api;
if (api != null)
api.OnStateChange += handleApiStateChange;
api?.Register(this);
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (api != null)
api.OnStateChange -= handleApiStateChange;
api?.Unregister(this);
}
public void RefreshScores() => UpdateScores();
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();
}
@ -265,14 +265,18 @@ namespace osu.Game.Online.Leaderboards
currentPlaceholder = placeholder;
}
protected virtual bool FadeBottom => true;
protected virtual bool FadeTop => true;
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
var fadeStart = scrollContainer.Current + scrollContainer.DrawHeight;
var fadeBottom = scrollContainer.Current + scrollContainer.DrawHeight;
var fadeTop = scrollContainer.Current + LeaderboardScore.HEIGHT;
if (!scrollContainer.IsScrolledToEnd())
fadeStart -= LeaderboardScore.HEIGHT;
fadeBottom -= LeaderboardScore.HEIGHT;
if (scrollFlow == null)
return;
@ -282,15 +286,23 @@ namespace osu.Game.Online.Leaderboards
var topY = c.ToSpaceOfOtherDrawable(Vector2.Zero, scrollFlow).Y;
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;
else if (topY > fadeStart + LeaderboardScore.HEIGHT)
else if (topY > fadeBottom + LeaderboardScore.HEIGHT || bottomY < fadeTop - LeaderboardScore.HEIGHT)
c.Colour = Color4.Transparent;
else
{
if (bottomY - fadeBottom > 0 && FadeBottom)
c.Colour = ColourInfo.GradientVertical(
Color4.White.Opacity(Math.Min(1 - (topY - fadeStart) / LeaderboardScore.HEIGHT, 1)),
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
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Font = @"Exo2.0-MediumItalic",
TextSize = 22,
// ReSharper disable once ImpureMethodCallOnReadonlyValueField

View File

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

View File

@ -13,6 +13,7 @@ using osu.Framework.Lists;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Leaderboards;
using osu.Game.Online.Multiplayer;
using osu.Game.Scoring;
using osu.Game.Screens.Multi.Match.Components;
@ -20,7 +21,7 @@ using osu.Game.Screens.Ranking;
namespace osu.Game.Screens.Multi.Ranking.Pages
{
public class RoomRankingResultsPage : ResultsPage
public class RoomLeaderboardPage : ResultsPage
{
private readonly Room room;
@ -28,7 +29,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
private TextFlowContainer rankText;
public RoomRankingResultsPage(ScoreInfo score, WorkingBeatmap beatmap, Room room)
public RoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap, Room room)
: base(score, beatmap)
{
this.room = room;
@ -45,13 +46,13 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
{
new Box
{
Colour = colours.GrayE,
Colour = colours.Gray6,
RelativeSizeAxes = Axes.Both,
},
new BufferedContainer
{
RelativeSizeAxes = Axes.Both,
BackgroundColour = colours.GrayE,
BackgroundColour = colours.Gray6,
Child = leaderboard = CreateLeaderboard(room)
},
rankText = new TextFlowContainer
@ -61,7 +62,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
RelativeSizeAxes = Axes.X,
Width = 0.5f,
AutoSizeAxes = Axes.Y,
Y = 75,
Y = 50,
TextAnchor = Anchor.TopCentre
},
};
@ -70,14 +71,20 @@ namespace osu.Game.Screens.Multi.Ranking.Pages
leaderboard.Anchor = Anchor.Centre;
leaderboard.RelativeSizeAxes = Axes.Both;
leaderboard.Height = 0.8f;
leaderboard.Y = 95;
leaderboard.Y = 55;
leaderboard.ScoresLoaded = scoresLoaded;
}
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);
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);
}
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;
}
public FontAwesome Icon => FontAwesome.fa_list;
public FontAwesome Icon => FontAwesome.fa_users;
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[]
{
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
{
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)
{
}
@ -26,7 +26,7 @@ namespace osu.Game.Screens.Ranking.Pages
{
new Box
{
Colour = colours.GrayE,
Colour = colours.Gray6,
RelativeSizeAxes = Axes.Both,
},
new BeatmapLeaderboard

View File

@ -8,21 +8,21 @@ using osu.Game.Screens.Ranking.Pages;
namespace osu.Game.Screens.Ranking.Types
{
public class BeatmapLeaderboardPageInfo : IResultPageInfo
public class LocalLeaderboardPageInfo : IResultPageInfo
{
private readonly ScoreInfo score;
private readonly WorkingBeatmap beatmap;
public BeatmapLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap)
public LocalLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap)
{
this.score = score;
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]
private ScoreManager scoreManager { get; set; }