mirror of
https://github.com/ppy/osu.git
synced 2025-02-15 23:42:55 +08:00
Merge branch 'master' into footer-v2-integration
This commit is contained in:
commit
9a88281ab0
@ -0,0 +1,142 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.OnlinePlay.DailyChallenge;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.DailyChallenge
|
||||
{
|
||||
public partial class TestSceneDailyChallengeLeaderboard : OsuTestScene
|
||||
{
|
||||
private DummyAPIAccess dummyAPI => (DummyAPIAccess)API;
|
||||
|
||||
[Cached]
|
||||
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Plum);
|
||||
|
||||
[Test]
|
||||
public void TestBasicBehaviour()
|
||||
{
|
||||
DailyChallengeLeaderboard leaderboard = null!;
|
||||
|
||||
AddStep("set up response without user best", () =>
|
||||
{
|
||||
dummyAPI.HandleRequest = req =>
|
||||
{
|
||||
if (req is IndexPlaylistScoresRequest indexRequest)
|
||||
{
|
||||
indexRequest.TriggerSuccess(createResponse(50, false));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
});
|
||||
AddStep("create leaderboard", () => Child = leaderboard = new DailyChallengeLeaderboard(new Room { RoomID = { Value = 1 } }, new PlaylistItem(Beatmap.Value.BeatmapInfo))
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(0.8f),
|
||||
});
|
||||
|
||||
AddStep("set up response with user best", () =>
|
||||
{
|
||||
dummyAPI.HandleRequest = req =>
|
||||
{
|
||||
if (req is IndexPlaylistScoresRequest indexRequest)
|
||||
{
|
||||
indexRequest.TriggerSuccess(createResponse(50, true));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
});
|
||||
AddStep("force refetch", () => leaderboard.RefetchScores());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLoadingBehaviour()
|
||||
{
|
||||
IndexPlaylistScoresRequest pendingRequest = null!;
|
||||
DailyChallengeLeaderboard leaderboard = null!;
|
||||
|
||||
AddStep("set up requests handler", () =>
|
||||
{
|
||||
dummyAPI.HandleRequest = req =>
|
||||
{
|
||||
if (req is IndexPlaylistScoresRequest indexRequest)
|
||||
{
|
||||
pendingRequest = indexRequest;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
});
|
||||
AddStep("create leaderboard", () => Child = leaderboard = new DailyChallengeLeaderboard(new Room { RoomID = { Value = 1 } }, new PlaylistItem(Beatmap.Value.BeatmapInfo))
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(0.8f),
|
||||
});
|
||||
AddStep("complete load", () => pendingRequest.TriggerSuccess(createResponse(3, true)));
|
||||
AddStep("force refetch", () => leaderboard.RefetchScores());
|
||||
AddStep("complete load", () => pendingRequest.TriggerSuccess(createResponse(4, true)));
|
||||
}
|
||||
|
||||
private IndexedMultiplayerScores createResponse(int scoreCount, bool returnUserBest)
|
||||
{
|
||||
var result = new IndexedMultiplayerScores();
|
||||
|
||||
for (int i = 0; i < scoreCount; ++i)
|
||||
{
|
||||
result.Scores.Add(new MultiplayerScore
|
||||
{
|
||||
ID = i,
|
||||
Accuracy = 1 - (float)i / (2 * scoreCount),
|
||||
Position = i + 1,
|
||||
EndedAt = DateTimeOffset.Now,
|
||||
Passed = true,
|
||||
Rank = (ScoreRank)RNG.Next((int)ScoreRank.D, (int)ScoreRank.XH),
|
||||
MaxCombo = 1000 - i,
|
||||
TotalScore = (long)(1_000_000 * (1 - (float)i / (2 * scoreCount))),
|
||||
User = new APIUser { Username = $"user {i}" },
|
||||
Statistics = new Dictionary<HitResult, int>()
|
||||
});
|
||||
}
|
||||
|
||||
if (returnUserBest)
|
||||
{
|
||||
result.UserScore = new MultiplayerScore
|
||||
{
|
||||
ID = 99999,
|
||||
Accuracy = 0.91,
|
||||
Position = 4,
|
||||
EndedAt = DateTimeOffset.Now,
|
||||
Passed = true,
|
||||
Rank = ScoreRank.A,
|
||||
MaxCombo = 100,
|
||||
TotalScore = 800000,
|
||||
User = dummyAPI.LocalUser.Value,
|
||||
Statistics = new Dictionary<HitResult, int>()
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@ -413,7 +413,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
};
|
||||
}
|
||||
|
||||
private partial class TestResultsScreen : PlaylistsResultsScreen
|
||||
private partial class TestResultsScreen : PlaylistItemUserResultsScreen
|
||||
{
|
||||
public new LoadingSpinner LeftSpinner => base.LeftSpinner;
|
||||
public new LoadingSpinner CentreSpinner => base.CentreSpinner;
|
||||
|
@ -50,35 +50,73 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
});
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
[Test]
|
||||
public void TestSheared()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
AddStep("create content", () =>
|
||||
{
|
||||
fillFlow = new FillFlowContainer
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Width = relativeWidth,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Spacing = new Vector2(0f, 2f),
|
||||
Shear = new Vector2(OsuGame.SHEAR, 0)
|
||||
},
|
||||
drawWidthText = new OsuSpriteText(),
|
||||
};
|
||||
fillFlow = new FillFlowContainer
|
||||
{
|
||||
Width = relativeWidth,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Spacing = new Vector2(0f, 2f),
|
||||
Shear = new Vector2(OsuGame.SHEAR, 0)
|
||||
},
|
||||
drawWidthText = new OsuSpriteText(),
|
||||
};
|
||||
|
||||
foreach (var scoreInfo in getTestScores())
|
||||
foreach (var scoreInfo in getTestScores())
|
||||
{
|
||||
fillFlow.Add(new LeaderboardScoreV2(scoreInfo)
|
||||
{
|
||||
Rank = scoreInfo.Position,
|
||||
IsPersonalBest = scoreInfo.User.Id == 2,
|
||||
Shear = Vector2.Zero,
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var score in fillFlow.Children)
|
||||
score.Show();
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNonSheared()
|
||||
{
|
||||
AddStep("create content", () =>
|
||||
{
|
||||
fillFlow.Add(new LeaderboardScoreV2(scoreInfo, scoreInfo.Position, scoreInfo.User.Id == 2)
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Shear = Vector2.Zero,
|
||||
});
|
||||
}
|
||||
fillFlow = new FillFlowContainer
|
||||
{
|
||||
Width = relativeWidth,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Spacing = new Vector2(0f, 2f),
|
||||
},
|
||||
drawWidthText = new OsuSpriteText(),
|
||||
};
|
||||
|
||||
foreach (var score in fillFlow.Children)
|
||||
score.Show();
|
||||
});
|
||||
foreach (var scoreInfo in getTestScores())
|
||||
{
|
||||
fillFlow.Add(new LeaderboardScoreV2(scoreInfo)
|
||||
{
|
||||
Rank = scoreInfo.Position,
|
||||
IsPersonalBest = scoreInfo.User.Id == 2,
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var score in fillFlow.Children)
|
||||
score.Show();
|
||||
});
|
||||
}
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
|
23
osu.Game/Online/Rooms/ShowPlaylistScoreRequest.cs
Normal file
23
osu.Game/Online/Rooms/ShowPlaylistScoreRequest.cs
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Online.API;
|
||||
|
||||
namespace osu.Game.Online.Rooms
|
||||
{
|
||||
public class ShowPlaylistScoreRequest : APIRequest<MultiplayerScore>
|
||||
{
|
||||
private readonly long roomId;
|
||||
private readonly long playlistItemId;
|
||||
private readonly long scoreId;
|
||||
|
||||
public ShowPlaylistScoreRequest(long roomId, long playlistItemId, long scoreId)
|
||||
{
|
||||
this.roomId = roomId;
|
||||
this.playlistItemId = playlistItemId;
|
||||
this.scoreId = scoreId;
|
||||
}
|
||||
|
||||
protected override string Target => $@"rooms/{roomId}/playlist/{playlistItemId}/scores/{scoreId}";
|
||||
}
|
||||
}
|
@ -29,6 +29,11 @@ namespace osu.Game.Overlays.Mods
|
||||
/// </summary>
|
||||
protected ShearedOverlayHeader Header { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The overlay's footer.
|
||||
/// </summary>
|
||||
protected Container Footer { get; private set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private ScreenFooter? footer { get; set; }
|
||||
|
||||
@ -43,6 +48,11 @@ namespace osu.Game.Overlays.Mods
|
||||
/// </summary>
|
||||
protected Container MainAreaContent { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// A container for content that is to be displayed inside the footer.
|
||||
/// </summary>
|
||||
protected Container FooterContent { get; private set; } = null!;
|
||||
|
||||
protected override bool StartHidden => true;
|
||||
|
||||
protected override bool BlockNonPositionalInput => true;
|
||||
@ -125,7 +135,7 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
if (footer != null)
|
||||
{
|
||||
footer.SetOverlayContent(this);
|
||||
footer.SetActiveOverlayContainer(this);
|
||||
|
||||
if (footer.State.Value == Visibility.Hidden)
|
||||
{
|
||||
@ -146,7 +156,7 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
if (footer != null)
|
||||
{
|
||||
footer.ClearOverlayContent();
|
||||
footer.ClearActiveOverlayContainer();
|
||||
|
||||
if (hideFooterOnPopOut)
|
||||
{
|
||||
|
@ -142,7 +142,7 @@ namespace osu.Game.Screens.Footer
|
||||
temporarilyHiddenButtons.Clear();
|
||||
overlays.Clear();
|
||||
|
||||
ClearOverlayContent();
|
||||
ClearActiveOverlayContainer();
|
||||
|
||||
var oldButtons = buttonsFlow.ToArray();
|
||||
|
||||
@ -189,7 +189,7 @@ namespace osu.Game.Screens.Footer
|
||||
private Container? contentContainer;
|
||||
private readonly List<ScreenFooterButton> temporarilyHiddenButtons = new List<ScreenFooterButton>();
|
||||
|
||||
public void SetOverlayContent(ShearedOverlayContainer overlay)
|
||||
public void SetActiveOverlayContainer(ShearedOverlayContainer overlay)
|
||||
{
|
||||
if (contentContainer != null)
|
||||
{
|
||||
@ -234,7 +234,7 @@ namespace osu.Game.Screens.Footer
|
||||
content.Show();
|
||||
}
|
||||
|
||||
public void ClearOverlayContent()
|
||||
public void ClearActiveOverlayContainer()
|
||||
{
|
||||
if (contentContainer == null)
|
||||
return;
|
||||
|
@ -9,7 +9,6 @@ using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Extensions.LocalisationExtensions;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
@ -50,7 +49,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
private readonly Bindable<IReadOnlyList<Mod>> userMods = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
|
||||
|
||||
private OnlinePlayScreenWaveContainer waves = null!;
|
||||
private MatchLeaderboard leaderboard = null!;
|
||||
private DailyChallengeLeaderboard leaderboard = null!;
|
||||
private RoomModSelectOverlay userModsSelectOverlay = null!;
|
||||
private Sample? sampleStart;
|
||||
private IDisposable? userModsSelectOverlayRegistration;
|
||||
@ -161,7 +160,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4Extensions.FromHex(@"3e3a44") // Temporary.
|
||||
Colour = colourProvider.Background4,
|
||||
},
|
||||
new GridContainer
|
||||
{
|
||||
@ -209,28 +208,17 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
feed = new DailyChallengeEventFeed
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
PresentScore = presentScore
|
||||
}
|
||||
],
|
||||
},
|
||||
},
|
||||
null,
|
||||
// Middle column (leaderboard)
|
||||
new GridContainer
|
||||
leaderboard = new DailyChallengeLeaderboard(room, playlistItem)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Content = new[]
|
||||
{
|
||||
new Drawable[]
|
||||
{
|
||||
new SectionHeader("Leaderboard")
|
||||
},
|
||||
[leaderboard = new MatchLeaderboard { RelativeSizeAxes = Axes.Both }],
|
||||
},
|
||||
RowDimensions = new[]
|
||||
{
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
new Dimension(),
|
||||
}
|
||||
PresentScore = presentScore,
|
||||
},
|
||||
// Spacer
|
||||
null,
|
||||
@ -272,7 +260,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4Extensions.FromHex(@"28242d") // Temporary.
|
||||
Colour = colourProvider.Background5,
|
||||
},
|
||||
footerButtons = new FillFlowContainer
|
||||
{
|
||||
@ -326,6 +314,12 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
metadataClient.MultiplayerRoomScoreSet += onRoomScoreSet;
|
||||
}
|
||||
|
||||
private void presentScore(long id)
|
||||
{
|
||||
if (this.IsCurrentScreen())
|
||||
this.Push(new PlaylistItemScoreResultsScreen(room.RoomID.Value!.Value, playlistItem, id));
|
||||
}
|
||||
|
||||
private void onRoomScoreSet(MultiplayerRoomScoreSetEvent e)
|
||||
{
|
||||
if (e.RoomID != room.RoomID.Value || e.PlaylistItemID != playlistItem.ID)
|
||||
@ -347,6 +341,9 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
{
|
||||
breakdown.AddNewScore(ev);
|
||||
feed.AddNewScore(ev);
|
||||
|
||||
if (e.NewRank <= 50)
|
||||
Schedule(() => leaderboard.RefetchScores());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
@ -19,6 +20,8 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
{
|
||||
private DailyChallengeEventFeedFlow flow = null!;
|
||||
|
||||
public Action<long>? PresentScore { get; init; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
@ -48,6 +51,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
PresentScore = PresentScore,
|
||||
};
|
||||
flow.Add(row);
|
||||
row.Delay(15000).Then().FadeOut(300, Easing.OutQuint).Expire();
|
||||
@ -78,6 +82,8 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
{
|
||||
private readonly NewScoreEvent newScore;
|
||||
|
||||
public Action<long>? PresentScore { get; init; }
|
||||
|
||||
public NewScoreEventRow(NewScoreEvent newScore)
|
||||
{
|
||||
this.newScore = newScore;
|
||||
@ -115,7 +121,7 @@ namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
|
||||
text.AddUserLink(newScore.User);
|
||||
text.AddText(" got ");
|
||||
text.AddLink($"{newScore.TotalScore:N0} points", () => { }); // TODO: present the score here
|
||||
text.AddLink($"{newScore.TotalScore:N0} points", () => PresentScore?.Invoke(newScore.ScoreID));
|
||||
|
||||
if (newScore.NewRank != null)
|
||||
text.AddText($" and achieved rank #{newScore.NewRank.Value:N0}");
|
||||
|
@ -0,0 +1,175 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.SelectV2.Leaderboards;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.DailyChallenge
|
||||
{
|
||||
public partial class DailyChallengeLeaderboard : CompositeDrawable
|
||||
{
|
||||
public Action<long>? PresentScore { get; init; }
|
||||
|
||||
private readonly Room room;
|
||||
private readonly PlaylistItem playlistItem;
|
||||
|
||||
private FillFlowContainer<LeaderboardScoreV2> scoreFlow = null!;
|
||||
private Container userBestContainer = null!;
|
||||
private SectionHeader userBestHeader = null!;
|
||||
private LoadingLayer loadingLayer = null!;
|
||||
|
||||
private CancellationTokenSource? cancellationTokenSource;
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private ScoreManager scoreManager { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private RulesetStore rulesets { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private IBindable<WorkingBeatmap> beatmap { get; set; } = null!;
|
||||
|
||||
public DailyChallengeLeaderboard(Room room, PlaylistItem playlistItem)
|
||||
{
|
||||
this.room = room;
|
||||
this.playlistItem = playlistItem;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChild = new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RowDimensions =
|
||||
[
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
new Dimension(),
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
new Dimension(GridSizeMode.AutoSize)
|
||||
],
|
||||
Content = new[]
|
||||
{
|
||||
new Drawable[] { new SectionHeader("Leaderboard") },
|
||||
new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = scoreFlow = new FillFlowContainer<LeaderboardScoreV2>
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Padding = new MarginPadding { Right = 20, },
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(5),
|
||||
Scale = new Vector2(0.8f),
|
||||
Width = 1 / 0.8f,
|
||||
}
|
||||
},
|
||||
loadingLayer = new LoadingLayer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
new Drawable[] { userBestHeader = new SectionHeader("Personal best") { Alpha = 0, } },
|
||||
new Drawable[]
|
||||
{
|
||||
userBestContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Padding = new MarginPadding { Right = 20, },
|
||||
Scale = new Vector2(0.8f),
|
||||
Width = 1 / 0.8f,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
RefetchScores();
|
||||
}
|
||||
|
||||
public void RefetchScores()
|
||||
{
|
||||
var request = new IndexPlaylistScoresRequest(room.RoomID.Value!.Value, playlistItem.ID);
|
||||
|
||||
request.Success += req =>
|
||||
{
|
||||
var best = req.Scores.Select(s => s.CreateScoreInfo(scoreManager, rulesets, playlistItem, beatmap.Value.BeatmapInfo)).ToArray();
|
||||
var userBest = req.UserScore?.CreateScoreInfo(scoreManager, rulesets, playlistItem, beatmap.Value.BeatmapInfo);
|
||||
|
||||
cancellationTokenSource?.Cancel();
|
||||
cancellationTokenSource = null;
|
||||
cancellationTokenSource ??= new CancellationTokenSource();
|
||||
|
||||
if (best.Length == 0)
|
||||
{
|
||||
scoreFlow.Clear();
|
||||
loadingLayer.Hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadComponentsAsync(best.Select(s => new LeaderboardScoreV2(s, sheared: false)
|
||||
{
|
||||
Rank = s.Position,
|
||||
IsPersonalBest = s.UserID == api.LocalUser.Value.Id,
|
||||
Action = () => PresentScore?.Invoke(s.OnlineID),
|
||||
}), loaded =>
|
||||
{
|
||||
scoreFlow.Clear();
|
||||
scoreFlow.AddRange(loaded);
|
||||
scoreFlow.FadeTo(1, 400, Easing.OutQuint);
|
||||
loadingLayer.Hide();
|
||||
}, cancellationTokenSource.Token);
|
||||
}
|
||||
|
||||
userBestContainer.Clear();
|
||||
|
||||
if (userBest != null)
|
||||
{
|
||||
userBestContainer.Add(new LeaderboardScoreV2(userBest, sheared: false)
|
||||
{
|
||||
Rank = userBest.Position,
|
||||
IsPersonalBest = true,
|
||||
Action = () => PresentScore?.Invoke(userBest.OnlineID),
|
||||
});
|
||||
}
|
||||
|
||||
userBestHeader.FadeTo(userBest == null ? 0 : 1);
|
||||
};
|
||||
|
||||
loadingLayer.Show();
|
||||
scoreFlow.FadeTo(0.5f, 400, Easing.OutQuint);
|
||||
api.Queue(request);
|
||||
}
|
||||
}
|
||||
}
|
@ -80,6 +80,9 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
[Resolved(canBeNull: true)]
|
||||
protected OnlinePlayScreen ParentScreen { get; private set; }
|
||||
|
||||
[Resolved]
|
||||
private PreviewTrackManager previewTrackManager { get; set; } = null!;
|
||||
|
||||
[Cached]
|
||||
private readonly OnlinePlayBeatmapAvailabilityTracker beatmapAvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker();
|
||||
|
||||
@ -483,6 +486,8 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
{
|
||||
UserModsSelectOverlay.Hide();
|
||||
endHandlingTrack();
|
||||
|
||||
previewTrackManager.StopAnyPlaying(this);
|
||||
}
|
||||
|
||||
private void endHandlingTrack()
|
||||
|
@ -7,7 +7,7 @@ using osu.Game.Screens.OnlinePlay.Playlists;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
{
|
||||
public partial class MultiplayerResultsScreen : PlaylistsResultsScreen
|
||||
public partial class MultiplayerResultsScreen : PlaylistItemUserResultsScreen
|
||||
{
|
||||
public MultiplayerResultsScreen(ScoreInfo score, long roomId, PlaylistItem playlistItem)
|
||||
: base(score, roomId, playlistItem)
|
||||
|
@ -17,10 +17,10 @@ using osu.Game.Screens.Ranking;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
{
|
||||
public partial class PlaylistsResultsScreen : ResultsScreen
|
||||
public abstract partial class PlaylistItemResultsScreen : ResultsScreen
|
||||
{
|
||||
private readonly long roomId;
|
||||
private readonly PlaylistItem playlistItem;
|
||||
protected readonly long RoomId;
|
||||
protected readonly PlaylistItem PlaylistItem;
|
||||
|
||||
protected LoadingSpinner LeftSpinner { get; private set; } = null!;
|
||||
protected LoadingSpinner CentreSpinner { get; private set; } = null!;
|
||||
@ -30,19 +30,19 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
private MultiplayerScores? lowerScores;
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; } = null!;
|
||||
protected IAPIProvider API { get; private set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private ScoreManager scoreManager { get; set; } = null!;
|
||||
protected ScoreManager ScoreManager { get; private set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private RulesetStore rulesets { get; set; } = null!;
|
||||
protected RulesetStore Rulesets { get; private set; } = null!;
|
||||
|
||||
public PlaylistsResultsScreen(ScoreInfo? score, long roomId, PlaylistItem playlistItem)
|
||||
protected PlaylistItemResultsScreen(ScoreInfo? score, long roomId, PlaylistItem playlistItem)
|
||||
: base(score)
|
||||
{
|
||||
this.roomId = roomId;
|
||||
this.playlistItem = playlistItem;
|
||||
RoomId = roomId;
|
||||
PlaylistItem = playlistItem;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -74,13 +74,15 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
});
|
||||
}
|
||||
|
||||
protected override APIRequest FetchScores(Action<IEnumerable<ScoreInfo>> scoresCallback)
|
||||
protected abstract APIRequest<MultiplayerScore> CreateScoreRequest();
|
||||
|
||||
protected sealed override APIRequest FetchScores(Action<IEnumerable<ScoreInfo>> scoresCallback)
|
||||
{
|
||||
// This performs two requests:
|
||||
// 1. A request to show the user's score (and scores around).
|
||||
// 1. A request to show the relevant score (and scores around).
|
||||
// 2. If that fails, a request to index the room starting from the highest score.
|
||||
|
||||
var userScoreReq = new ShowPlaylistUserScoreRequest(roomId, playlistItem.ID, api.LocalUser.Value.Id);
|
||||
var userScoreReq = CreateScoreRequest();
|
||||
|
||||
userScoreReq.Success += userScore =>
|
||||
{
|
||||
@ -111,11 +113,15 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
setPositions(lowerScores, userScore.Position.Value, 1);
|
||||
}
|
||||
|
||||
performSuccessCallback(scoresCallback, allScores);
|
||||
Schedule(() =>
|
||||
{
|
||||
PerformSuccessCallback(scoresCallback, allScores);
|
||||
hideLoadingSpinners();
|
||||
});
|
||||
};
|
||||
|
||||
// On failure, fallback to a normal index.
|
||||
userScoreReq.Failure += _ => api.Queue(createIndexRequest(scoresCallback));
|
||||
userScoreReq.Failure += _ => API.Queue(createIndexRequest(scoresCallback));
|
||||
|
||||
return userScoreReq;
|
||||
}
|
||||
@ -147,8 +153,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
private APIRequest createIndexRequest(Action<IEnumerable<ScoreInfo>> scoresCallback, MultiplayerScores? pivot = null)
|
||||
{
|
||||
var indexReq = pivot != null
|
||||
? new IndexPlaylistScoresRequest(roomId, playlistItem.ID, pivot.Cursor, pivot.Params)
|
||||
: new IndexPlaylistScoresRequest(roomId, playlistItem.ID);
|
||||
? new IndexPlaylistScoresRequest(RoomId, PlaylistItem.ID, pivot.Cursor, pivot.Params)
|
||||
: new IndexPlaylistScoresRequest(RoomId, PlaylistItem.ID);
|
||||
|
||||
indexReq.Success += r =>
|
||||
{
|
||||
@ -163,7 +169,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
setPositions(r, pivot, -1);
|
||||
}
|
||||
|
||||
performSuccessCallback(scoresCallback, r.Scores, r);
|
||||
Schedule(() =>
|
||||
{
|
||||
PerformSuccessCallback(scoresCallback, r.Scores, r);
|
||||
hideLoadingSpinners(r);
|
||||
});
|
||||
};
|
||||
|
||||
indexReq.Failure += _ => hideLoadingSpinners(pivot);
|
||||
@ -177,26 +187,15 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
/// <param name="callback">The callback to invoke with the final <see cref="ScoreInfo"/>s.</param>
|
||||
/// <param name="scores">The <see cref="MultiplayerScore"/>s that were retrieved from <see cref="APIRequest"/>s.</param>
|
||||
/// <param name="pivot">An optional pivot around which the scores were retrieved.</param>
|
||||
private void performSuccessCallback(Action<IEnumerable<ScoreInfo>> callback, List<MultiplayerScore> scores, MultiplayerScores? pivot = null) => Schedule(() =>
|
||||
protected virtual ScoreInfo[] PerformSuccessCallback(Action<IEnumerable<ScoreInfo>> callback, List<MultiplayerScore> scores, MultiplayerScores? pivot = null)
|
||||
{
|
||||
var scoreInfos = scores.Select(s => s.CreateScoreInfo(scoreManager, rulesets, playlistItem, Beatmap.Value.BeatmapInfo)).OrderByTotalScore().ToArray();
|
||||
var scoreInfos = scores.Select(s => s.CreateScoreInfo(ScoreManager, Rulesets, PlaylistItem, Beatmap.Value.BeatmapInfo)).OrderByTotalScore().ToArray();
|
||||
|
||||
// Select a score if we don't already have one selected.
|
||||
// Note: This is done before the callback so that the panel list centres on the selected score before panels are added (eliminating initial scroll).
|
||||
if (SelectedScore.Value == null)
|
||||
{
|
||||
Schedule(() =>
|
||||
{
|
||||
// Prefer selecting the local user's score, or otherwise default to the first visible score.
|
||||
SelectedScore.Value = scoreInfos.FirstOrDefault(s => s.User.OnlineID == api.LocalUser.Value.Id) ?? scoreInfos.FirstOrDefault();
|
||||
});
|
||||
}
|
||||
// Invoke callback to add the scores.
|
||||
callback.Invoke(scoreInfos);
|
||||
|
||||
// Invoke callback to add the scores. Exclude the user's current score which was added previously.
|
||||
callback.Invoke(scoreInfos.Where(s => s.OnlineID != Score?.OnlineID));
|
||||
|
||||
hideLoadingSpinners(pivot);
|
||||
});
|
||||
return scoreInfos;
|
||||
}
|
||||
|
||||
private void hideLoadingSpinners(MultiplayerScores? pivot = null)
|
||||
{
|
@ -0,0 +1,37 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Scoring;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
{
|
||||
/// <summary>
|
||||
/// Shows a selected arbitrary score for a playlist item, with scores around included.
|
||||
/// </summary>
|
||||
public partial class PlaylistItemScoreResultsScreen : PlaylistItemResultsScreen
|
||||
{
|
||||
private readonly long scoreId;
|
||||
|
||||
public PlaylistItemScoreResultsScreen(long roomId, PlaylistItem playlistItem, long scoreId)
|
||||
: base(null, roomId, playlistItem)
|
||||
{
|
||||
this.scoreId = scoreId;
|
||||
}
|
||||
|
||||
protected override APIRequest<MultiplayerScore> CreateScoreRequest() => new ShowPlaylistScoreRequest(RoomId, PlaylistItem.ID, scoreId);
|
||||
|
||||
protected override ScoreInfo[] PerformSuccessCallback(Action<IEnumerable<ScoreInfo>> callback, List<MultiplayerScore> scores, MultiplayerScores? pivot = null)
|
||||
{
|
||||
var scoreInfos = base.PerformSuccessCallback(callback, scores, pivot);
|
||||
|
||||
Schedule(() => SelectedScore.Value = scoreInfos.SingleOrDefault(score => score.OnlineID == scoreId));
|
||||
|
||||
return scoreInfos;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Scoring;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
{
|
||||
/// <summary>
|
||||
/// Shows the user's best score for a given playlist item, with scores around included.
|
||||
/// </summary>
|
||||
public partial class PlaylistItemUserResultsScreen : PlaylistItemResultsScreen
|
||||
{
|
||||
public PlaylistItemUserResultsScreen(ScoreInfo? score, long roomId, PlaylistItem playlistItem)
|
||||
: base(score, roomId, playlistItem)
|
||||
{
|
||||
}
|
||||
|
||||
protected override APIRequest<MultiplayerScore> CreateScoreRequest() => new ShowPlaylistUserScoreRequest(RoomId, PlaylistItem.ID, API.LocalUser.Value.Id);
|
||||
|
||||
protected override ScoreInfo[] PerformSuccessCallback(Action<IEnumerable<ScoreInfo>> callback, List<MultiplayerScore> scores, MultiplayerScores? pivot = null)
|
||||
{
|
||||
var scoreInfos = scores.Select(s => s.CreateScoreInfo(ScoreManager, Rulesets, PlaylistItem, Beatmap.Value.BeatmapInfo)).OrderByTotalScore().ToArray();
|
||||
|
||||
// Select a score if we don't already have one selected.
|
||||
// Note: This is done before the callback so that the panel list centres on the selected score before panels are added (eliminating initial scroll).
|
||||
if (SelectedScore.Value == null)
|
||||
{
|
||||
Schedule(() =>
|
||||
{
|
||||
// Prefer selecting the local user's score, or otherwise default to the first visible score.
|
||||
SelectedScore.Value = scoreInfos.FirstOrDefault(s => s.User.OnlineID == API.LocalUser.Value.Id) ?? scoreInfos.FirstOrDefault();
|
||||
});
|
||||
}
|
||||
|
||||
// Invoke callback to add the scores. Exclude the user's current score which was added previously.
|
||||
callback.Invoke(scoreInfos.Where(s => s.OnlineID != Score?.OnlineID));
|
||||
|
||||
return scoreInfos;
|
||||
}
|
||||
}
|
||||
}
|
@ -58,7 +58,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
protected override ResultsScreen CreateResults(ScoreInfo score)
|
||||
{
|
||||
Debug.Assert(Room.RoomID.Value != null);
|
||||
return new PlaylistsResultsScreen(score, Room.RoomID.Value.Value, PlaylistItem)
|
||||
return new PlaylistItemUserResultsScreen(score, Room.RoomID.Value.Value, PlaylistItem)
|
||||
{
|
||||
AllowRetry = true,
|
||||
ShowUserStatistics = true,
|
||||
|
@ -114,7 +114,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||
RequestResults = item =>
|
||||
{
|
||||
Debug.Assert(RoomId.Value != null);
|
||||
ParentScreen?.Push(new PlaylistsResultsScreen(null, RoomId.Value.Value, item));
|
||||
ParentScreen?.Push(new PlaylistItemUserResultsScreen(null, RoomId.Value.Value, item));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -43,6 +43,9 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
{
|
||||
public partial class LeaderboardScoreV2 : OsuClickableContainer, IHasContextMenu, IHasCustomTooltip<ScoreInfo>
|
||||
{
|
||||
public int? Rank { get; init; }
|
||||
public bool IsPersonalBest { get; init; }
|
||||
|
||||
private const float expanded_right_content_width = 210;
|
||||
private const float grade_width = 40;
|
||||
private const float username_min_width = 125;
|
||||
@ -52,15 +55,12 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
private const float rank_label_visibility_width_cutoff = rank_label_width + height + username_min_width + statistics_regular_min_width + expanded_right_content_width;
|
||||
|
||||
private readonly ScoreInfo score;
|
||||
private readonly bool sheared;
|
||||
|
||||
private const int height = 60;
|
||||
private const int corner_radius = 10;
|
||||
private const int transition_duration = 200;
|
||||
|
||||
private readonly int? rank;
|
||||
|
||||
private readonly bool isPersonalBest;
|
||||
|
||||
private Colour4 foregroundColour;
|
||||
private Colour4 backgroundColour;
|
||||
private ColourInfo totalScoreBackgroundGradient;
|
||||
@ -104,13 +104,12 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
public ITooltip<ScoreInfo> GetCustomTooltip() => new LeaderboardScoreTooltip();
|
||||
public virtual ScoreInfo TooltipContent => score;
|
||||
|
||||
public LeaderboardScoreV2(ScoreInfo score, int? rank, bool isPersonalBest = false)
|
||||
public LeaderboardScoreV2(ScoreInfo score, bool sheared = true)
|
||||
{
|
||||
this.score = score;
|
||||
this.rank = rank;
|
||||
this.isPersonalBest = isPersonalBest;
|
||||
this.sheared = sheared;
|
||||
|
||||
Shear = new Vector2(OsuGame.SHEAR, 0);
|
||||
Shear = new Vector2(sheared ? OsuGame.SHEAR : 0, 0);
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = height;
|
||||
}
|
||||
@ -120,8 +119,8 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
{
|
||||
var user = score.User;
|
||||
|
||||
foregroundColour = isPersonalBest ? colourProvider.Background1 : colourProvider.Background5;
|
||||
backgroundColour = isPersonalBest ? colourProvider.Background2 : colourProvider.Background4;
|
||||
foregroundColour = IsPersonalBest ? colourProvider.Background1 : colourProvider.Background5;
|
||||
backgroundColour = IsPersonalBest ? colourProvider.Background2 : colourProvider.Background4;
|
||||
totalScoreBackgroundGradient = ColourInfo.GradientHorizontal(backgroundColour.Opacity(0), backgroundColour);
|
||||
|
||||
statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s, score)
|
||||
@ -159,7 +158,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
{
|
||||
AutoSizeAxes = Axes.X,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Child = rankLabel = new RankLabel(rank)
|
||||
Child = rankLabel = new RankLabel(Rank, sheared)
|
||||
{
|
||||
Width = rank_label_width,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
@ -243,7 +242,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
User = score.User,
|
||||
Shear = new Vector2(-OsuGame.SHEAR, 0),
|
||||
Shear = new Vector2(sheared ? -OsuGame.SHEAR : 0, 0),
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Colour = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0.5f), Colour4.FromHex(@"222A27").Opacity(1)),
|
||||
@ -274,7 +273,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Scale = new Vector2(1.1f),
|
||||
Shear = new Vector2(-OsuGame.SHEAR, 0),
|
||||
Shear = new Vector2(sheared ? -OsuGame.SHEAR : 0, 0),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
})
|
||||
{
|
||||
@ -292,7 +291,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Colour4.Black.Opacity(0.5f),
|
||||
},
|
||||
new RankLabel(rank)
|
||||
new RankLabel(Rank, sheared)
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
@ -314,7 +313,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
{
|
||||
flagBadgeAndDateContainer = new FillFlowContainer
|
||||
{
|
||||
Shear = new Vector2(-OsuGame.SHEAR, 0),
|
||||
Shear = new Vector2(sheared ? -OsuGame.SHEAR : 0, 0),
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(5),
|
||||
AutoSizeAxes = Axes.Both,
|
||||
@ -338,7 +337,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
nameLabel = new TruncatingSpriteText
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Shear = new Vector2(-OsuGame.SHEAR, 0),
|
||||
Shear = new Vector2(sheared ? -OsuGame.SHEAR : 0, 0),
|
||||
Text = user.Username,
|
||||
Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold)
|
||||
}
|
||||
@ -354,7 +353,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
Name = @"Statistics container",
|
||||
Padding = new MarginPadding { Right = 40 },
|
||||
Spacing = new Vector2(25, 0),
|
||||
Shear = new Vector2(-OsuGame.SHEAR, 0),
|
||||
Shear = new Vector2(sheared ? -OsuGame.SHEAR : 0, 0),
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
@ -412,7 +411,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
},
|
||||
RankContainer = new Container
|
||||
{
|
||||
Shear = new Vector2(-OsuGame.SHEAR, 0),
|
||||
Shear = new Vector2(sheared ? -OsuGame.SHEAR : 0, 0),
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
@ -470,7 +469,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
UseFullGlyphHeight = false,
|
||||
Shear = new Vector2(-OsuGame.SHEAR, 0),
|
||||
Shear = new Vector2(sheared ? -OsuGame.SHEAR : 0, 0),
|
||||
Current = scoreManager.GetBindableTotalScoreString(score),
|
||||
Font = OsuFont.GetFont(size: 30, weight: FontWeight.Light),
|
||||
},
|
||||
@ -478,7 +477,7 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
Shear = new Vector2(-OsuGame.SHEAR, 0),
|
||||
Shear = new Vector2(sheared ? -OsuGame.SHEAR : 0, 0),
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(2f, 0f),
|
||||
@ -656,14 +655,14 @@ namespace osu.Game.Screens.SelectV2.Leaderboards
|
||||
|
||||
private partial class RankLabel : Container, IHasTooltip
|
||||
{
|
||||
public RankLabel(int? rank)
|
||||
public RankLabel(int? rank, bool sheared)
|
||||
{
|
||||
if (rank >= 1000)
|
||||
TooltipText = $"#{rank:N0}";
|
||||
|
||||
Child = new OsuSpriteText
|
||||
{
|
||||
Shear = new Vector2(-OsuGame.SHEAR, 0),
|
||||
Shear = new Vector2(sheared ? -OsuGame.SHEAR : 0, 0),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold, italics: true),
|
||||
|
@ -99,6 +99,54 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
});
|
||||
return true;
|
||||
|
||||
case IndexPlaylistScoresRequest roomLeaderboardRequest:
|
||||
roomLeaderboardRequest.TriggerSuccess(new IndexedMultiplayerScores
|
||||
{
|
||||
Scores =
|
||||
{
|
||||
new MultiplayerScore
|
||||
{
|
||||
ID = currentScoreId++,
|
||||
Accuracy = 1,
|
||||
Position = 1,
|
||||
EndedAt = DateTimeOffset.Now,
|
||||
Passed = true,
|
||||
Rank = ScoreRank.S,
|
||||
MaxCombo = 1000,
|
||||
TotalScore = 1000000,
|
||||
User = new APIUser { Username = "best user" },
|
||||
Statistics = new Dictionary<HitResult, int>()
|
||||
},
|
||||
new MultiplayerScore
|
||||
{
|
||||
ID = currentScoreId++,
|
||||
Accuracy = 0.7,
|
||||
Position = 2,
|
||||
EndedAt = DateTimeOffset.Now,
|
||||
Passed = true,
|
||||
Rank = ScoreRank.B,
|
||||
MaxCombo = 100,
|
||||
TotalScore = 200000,
|
||||
User = new APIUser { Username = "worst user" },
|
||||
Statistics = new Dictionary<HitResult, int>()
|
||||
},
|
||||
},
|
||||
UserScore = new MultiplayerScore
|
||||
{
|
||||
ID = currentScoreId++,
|
||||
Accuracy = 0.91,
|
||||
Position = 4,
|
||||
EndedAt = DateTimeOffset.Now,
|
||||
Passed = true,
|
||||
Rank = ScoreRank.A,
|
||||
MaxCombo = 100,
|
||||
TotalScore = 800000,
|
||||
User = localUser,
|
||||
Statistics = new Dictionary<HitResult, int>()
|
||||
},
|
||||
});
|
||||
return true;
|
||||
|
||||
case PartRoomRequest partRoomRequest:
|
||||
partRoomRequest.TriggerSuccess();
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user