diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs index ff15e1d2dc..ca61672ef9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs @@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay playerScore.Value = 1222333; }); - AddStep("add local player", () => createLeaderboardScore(playerScore, "You", true)); + AddStep("add local player", () => createLeaderboardScore(playerScore, new User { Username = "You", Id = 3 }, true)); AddSliderStep("set player score", 50, 5000000, 1222333, v => playerScore.Value = v); } @@ -49,8 +49,8 @@ namespace osu.Game.Tests.Visual.Gameplay var player2Score = new BindableDouble(1234567); var player3Score = new BindableDouble(1111111); - AddStep("add player 2", () => createLeaderboardScore(player2Score, "Player 2")); - AddStep("add player 3", () => createLeaderboardScore(player3Score, "Player 3")); + AddStep("add player 2", () => createLeaderboardScore(player2Score, new User { Username = "Player 2" })); + AddStep("add player 3", () => createLeaderboardScore(player3Score, new User { Username = "Player 3" })); AddAssert("is player 2 position #1", () => leaderboard.CheckPositionByUsername("Player 2", 1)); AddAssert("is player position #2", () => leaderboard.CheckPositionByUsername("You", 2)); @@ -71,12 +71,23 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestRandomScores() { int playerNumber = 1; - AddRepeatStep("add player with random score", () => createLeaderboardScore(new BindableDouble(RNG.Next(0, 5_000_000)), $"Player {playerNumber++}"), 10); + AddRepeatStep("add player with random score", () => createRandomScore(new User { Username = $"Player {playerNumber++}" }), 10); } - private void createLeaderboardScore(BindableDouble score, string username, bool isTracked = false) + [Test] + public void TestExistingUsers() { - var leaderboardScore = leaderboard.AddPlayer(new User { Username = username }, isTracked); + AddStep("add peppy", () => createRandomScore(new User { Username = "peppy", Id = 2 })); + AddStep("add smoogipoo", () => createRandomScore(new User { Username = "smoogipoo", Id = 1040328 })); + AddStep("add flyte", () => createRandomScore(new User { Username = "flyte", Id = 3103765 })); + AddStep("add frenzibyte", () => createRandomScore(new User { Username = "frenzibyte", Id = 14210502 })); + } + + private void createRandomScore(User user) => createLeaderboardScore(new BindableDouble(RNG.Next(0, 5_000_000)), user); + + private void createLeaderboardScore(BindableDouble score, User user, bool isTracked = false) + { + var leaderboardScore = leaderboard.AddPlayer(user, isTracked); leaderboardScore.TotalScore.BindTo(score); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs index cdad37a9ad..9baaa42c83 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs @@ -4,7 +4,6 @@ using System; using NUnit.Framework; using osu.Framework.Graphics; -using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.RoomStatuses; using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Users; @@ -14,10 +13,8 @@ namespace osu.Game.Tests.Visual.Multiplayer public class TestSceneLoungeRoomInfo : MultiplayerTestScene { [SetUp] - public void Setup() => Schedule(() => + public new void Setup() => Schedule(() => { - Room = new Room(); - Child = new RoomInfo { Anchor = Anchor.Centre, diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs index 01cd26fbe5..6b1d90e06e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs @@ -24,10 +24,8 @@ namespace osu.Game.Tests.Visual.Multiplayer private RulesetStore rulesetStore { get; set; } [SetUp] - public void Setup() => Schedule(() => + public new void Setup() => Schedule(() => { - Room = new Room(); - Child = new MatchBeatmapDetailArea { Anchor = Anchor.Centre, diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs index e5943105b7..ec5292e51e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchHeader.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets.Osu; @@ -14,7 +15,12 @@ namespace osu.Game.Tests.Visual.Multiplayer { public TestSceneMatchHeader() { - Room = new Room(); + Child = new Header(); + } + + [SetUp] + public new void Setup() => Schedule(() => + { Room.Playlist.Add(new PlaylistItem { Beatmap = @@ -41,8 +47,6 @@ namespace osu.Game.Tests.Visual.Multiplayer Room.Name.Value = "A very awesome room"; Room.Host.Value = new User { Id = 2, Username = "peppy" }; - - Child = new Header(); - } + }); } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs index c24c6c4ba3..a72f71d79c 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs @@ -3,10 +3,10 @@ using System.Collections.Generic; using Newtonsoft.Json; +using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Online.API; -using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Users; using osuTK; @@ -19,8 +19,6 @@ namespace osu.Game.Tests.Visual.Multiplayer public TestSceneMatchLeaderboard() { - Room = new Room { RoomID = { Value = 3 } }; - Add(new MatchLeaderboard { Origin = Anchor.Centre, @@ -40,6 +38,12 @@ namespace osu.Game.Tests.Visual.Multiplayer api.Queue(req); } + [SetUp] + public new void Setup() => Schedule(() => + { + Room.RoomID.Value = 3; + }); + private class GetRoomScoresRequest : APIRequest> { protected override string Target => "rooms/3/leaderboard"; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs index 07ff56b5c3..cbe8cc6137 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSettingsOverlay.cs @@ -23,10 +23,8 @@ namespace osu.Game.Tests.Visual.Multiplayer private TestRoomSettings settings; [SetUp] - public void Setup() => Schedule(() => + public new void Setup() => Schedule(() => { - Room = new Room(); - settings = new TestRoomSettings { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs index 55b8902d7b..4742fd0d84 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs @@ -14,7 +14,6 @@ using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Utils; using osu.Game.Beatmaps; -using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; @@ -94,12 +93,6 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for present", () => songSelect.IsCurrentScreen()); } - [SetUp] - public void Setup() => Schedule(() => - { - Room = new Room(); - }); - [Test] public void TestItemAddedIfEmptyOnStart() { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs index 2e22317539..65e9893851 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSubScreen.cs @@ -45,12 +45,6 @@ namespace osu.Game.Tests.Visual.Multiplayer manager.Import(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait(); } - [SetUp] - public void Setup() => Schedule(() => - { - Room = new Room(); - }); - [SetUpSteps] public void SetupSteps() { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs deleted file mode 100644 index b6bfa7c93a..0000000000 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using NUnit.Framework; -using osu.Framework.Graphics; -using osu.Game.Online.Multiplayer; -using osu.Game.Screens.Multi.Components; -using osuTK; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - public class TestSceneOverlinedParticipants : MultiplayerTestScene - { - protected override bool UseOnlineAPI => true; - - [SetUp] - public void Setup() => Schedule(() => - { - Room = new Room { RoomID = { Value = 7 } }; - }); - - [Test] - public void TestHorizontalLayout() - { - AddStep("create component", () => - { - Child = new ParticipantsDisplay(Direction.Horizontal) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Width = 500, - }; - }); - } - - [Test] - public void TestVerticalLayout() - { - AddStep("create component", () => - { - Child = new ParticipantsDisplay(Direction.Vertical) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(500) - }; - }); - } - } -} diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs deleted file mode 100644 index 14984988cb..0000000000 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics; -using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets.Osu; -using osu.Game.Screens.Multi; -using osu.Game.Tests.Beatmaps; -using osuTK; - -namespace osu.Game.Tests.Visual.Multiplayer -{ - public class TestSceneOverlinedPlaylist : MultiplayerTestScene - { - protected override bool UseOnlineAPI => true; - - public TestSceneOverlinedPlaylist() - { - Room = new Room { RoomID = { Value = 7 } }; - - for (int i = 0; i < 10; i++) - { - Room.Playlist.Add(new PlaylistItem - { - ID = i, - Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, - Ruleset = { Value = new OsuRuleset().RulesetInfo } - }); - } - - Add(new DrawableRoomPlaylist(false, false) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(500), - }); - } - } -} diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs index f71c5fc5d2..7bbec7d30e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs @@ -3,24 +3,55 @@ using NUnit.Framework; using osu.Framework.Graphics; -using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Components; +using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneParticipantsList : MultiplayerTestScene { - protected override bool UseOnlineAPI => true; - [SetUp] - public void Setup() => Schedule(() => + public new void Setup() => Schedule(() => { - Room = new Room { RoomID = { Value = 7 } }; + Room.RoomID.Value = 7; + + for (int i = 0; i < 50; i++) + { + Room.RecentParticipants.Add(new User + { + Username = "peppy", + Id = 2 + }); + } }); - public TestSceneParticipantsList() + [Test] + public void TestHorizontalLayout() { - Add(new ParticipantsList { RelativeSizeAxes = Axes.Both }); + AddStep("create component", () => + { + Child = new ParticipantsDisplay(Direction.Horizontal) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 0.2f, + }; + }); + } + + [Test] + public void TestVerticalLayout() + { + AddStep("create component", () => + { + Child = new ParticipantsDisplay(Direction.Vertical) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 0.2f, + Height = 0.2f, + }; + }); } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomStatus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomStatus.cs index 1925e0ef4f..c1dfb94464 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomStatus.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRoomStatus.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.Multiplayer; @@ -22,18 +23,21 @@ namespace osu.Game.Tests.Visual.Multiplayer new DrawableRoom(new Room { Name = { Value = "Room 1" }, - Status = { Value = new RoomStatusOpen() } - }), + Status = { Value = new RoomStatusOpen() }, + EndDate = { Value = DateTimeOffset.Now.AddDays(1) } + }) { MatchingFilter = true }, new DrawableRoom(new Room { Name = { Value = "Room 2" }, - Status = { Value = new RoomStatusPlaying() } - }), + Status = { Value = new RoomStatusPlaying() }, + EndDate = { Value = DateTimeOffset.Now.AddDays(1) } + }) { MatchingFilter = true }, new DrawableRoom(new Room { Name = { Value = "Room 3" }, - Status = { Value = new RoomStatusEnded() } - }), + Status = { Value = new RoomStatusEnded() }, + EndDate = { Value = DateTimeOffset.Now } + }) { MatchingFilter = true }, } }; } diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index dcd0cb435a..d8207aa8f4 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -24,8 +24,8 @@ using osu.Game.Scoring; using osu.Game.Users.Drawables; using osuTK; using osuTK.Graphics; -using Humanizer; using osu.Game.Online.API; +using osu.Game.Utils; namespace osu.Game.Online.Leaderboards { @@ -358,7 +358,7 @@ namespace osu.Game.Online.Leaderboards Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 20, italics: true), - Text = rank == null ? "-" : rank.Value.ToMetric(decimals: rank < 100000 ? 1 : 0), + Text = rank == null ? "-" : rank.Value.FormatRank() }; } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index 347d9e3ba7..2f4721f63e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -92,6 +92,7 @@ namespace osu.Game.Screens.Edit.Compose.Components } } + private Container dragHandles; private FillFlowContainer buttons; public const float BORDER_RADIUS = 3; @@ -151,6 +152,12 @@ namespace osu.Game.Screens.Edit.Compose.Components }, } }, + dragHandles = new Container + { + RelativeSizeAxes = Axes.Both, + // ensures that the centres of all drag handles line up with the middle of the selection box border. + Padding = new MarginPadding(BORDER_RADIUS / 2) + }, buttons = new FillFlowContainer { Y = 20, @@ -232,7 +239,7 @@ namespace osu.Game.Screens.Edit.Compose.Components }); } - private void addDragHandle(Anchor anchor) => AddInternal(new SelectionBoxDragHandle + private void addDragHandle(Anchor anchor) => dragHandles.Add(new SelectionBoxDragHandle { Anchor = anchor, HandleDrag = e => OnScale?.Invoke(e.Delta, anchor), diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs index aa668cc4c8..cab1cbd3f1 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs @@ -24,6 +24,14 @@ namespace osu.Game.Screens.Play.HUD LayoutEasing = Easing.OutQuint; } + /// + /// Adds a player to the leaderboard. + /// + /// The player. + /// + /// Whether the player should be tracked on the leaderboard. + /// Set to true for the local player or a player whose replay is currently being played. + /// public ILeaderboardScore AddPlayer(User user, bool isTracked) { var drawable = new GameplayLeaderboardScore(user, isTracked) @@ -40,9 +48,9 @@ namespace osu.Game.Screens.Play.HUD return drawable; } - public override void Add(GameplayLeaderboardScore drawable) + public sealed override void Add(GameplayLeaderboardScore drawable) { - throw new InvalidOperationException($"Use {nameof(AddPlayer)} instead."); + throw new NotSupportedException($"Use {nameof(AddPlayer)} instead."); } private void sort() diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs index 0b58cf76a2..b93db09f71 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using Humanizer; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -11,6 +10,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Users; +using osu.Game.Users.Drawables; using osu.Game.Utils; using osuTK; using osuTK.Graphics; @@ -19,9 +19,9 @@ namespace osu.Game.Screens.Play.HUD { public class GameplayLeaderboardScore : CompositeDrawable, ILeaderboardScore { - public const float EXTENDED_WIDTH = 235f; + public const float EXTENDED_WIDTH = 255f; - private const float regular_width = 215f; + private const float regular_width = 235f; public const float PANEL_HEIGHT = 35f; @@ -48,7 +48,7 @@ namespace osu.Game.Screens.Play.HUD scorePosition = value; if (scorePosition.HasValue) - positionText.Text = $"#{scorePosition.Value.ToMetric(decimals: scorePosition < 100000 ? 1 : 0)}"; + positionText.Text = $"#{scorePosition.Value.FormatRank()}"; positionText.FadeTo(scorePosition.HasValue ? 1 : 0); updateColour(); @@ -75,61 +75,8 @@ namespace osu.Game.Screens.Play.HUD Size = new Vector2(EXTENDED_WIDTH, PANEL_HEIGHT); } - protected override void LoadComplete() - { - base.LoadComplete(); - - updateColour(); - FinishTransforms(true); - } - - private const double transition_duration = 500; - - private void updateColour() - { - if (scorePosition == 1) - { - mainFillContainer.ResizeWidthTo(EXTENDED_WIDTH, transition_duration, Easing.OutElastic); - panelColour = Color4Extensions.FromHex("7fcc33"); - textColour = Color4.White; - } - else if (trackedPlayer) - { - mainFillContainer.ResizeWidthTo(EXTENDED_WIDTH, transition_duration, Easing.OutElastic); - panelColour = Color4Extensions.FromHex("ffd966"); - textColour = Color4Extensions.FromHex("2e576b"); - } - else - { - mainFillContainer.ResizeWidthTo(regular_width, transition_duration, Easing.OutElastic); - panelColour = Color4Extensions.FromHex("3399cc"); - textColour = Color4.White; - } - } - - private Color4 panelColour - { - set - { - mainFillContainer.FadeColour(value, transition_duration, Easing.OutQuint); - centralFill.FadeColour(value, transition_duration, Easing.OutQuint); - } - } - - private Color4 textColour - { - set - { - scoreText.FadeColour(value, 200, Easing.OutQuint); - accuracyText.FadeColour(value, 200, Easing.OutQuint); - comboText.FadeColour(value, 200, Easing.OutQuint); - usernameText.FadeColour(value, 200, Easing.OutQuint); - positionText.FadeColour(value, 200, Easing.OutQuint); - } - } - [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours) { InternalChildren = new Drawable[] { @@ -195,19 +142,51 @@ namespace osu.Game.Screens.Play.HUD }, } }, - usernameText = new OsuSpriteText + new FillFlowContainer { Padding = new MarginPadding { Left = SHEAR_WIDTH }, - RelativeSizeAxes = Axes.X, - Width = 0.8f, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Colour = Color4.White, - Font = OsuFont.Torus.With(size: 14, weight: FontWeight.SemiBold), - Text = User.Username, - Truncate = true, - Shadow = false, - } + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(4f, 0f), + Children = new Drawable[] + { + new CircularContainer + { + Masking = true, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Size = new Vector2(25f), + Children = new Drawable[] + { + new Box + { + Name = "Placeholder while avatar loads", + Alpha = 0.3f, + RelativeSizeAxes = Axes.Both, + Colour = colours.Gray4, + }, + new UpdateableAvatar(User) + { + RelativeSizeAxes = Axes.Both, + }, + } + }, + usernameText = new OsuSpriteText + { + RelativeSizeAxes = Axes.X, + Width = 0.8f, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Colour = Color4.White, + Font = OsuFont.Torus.With(size: 14, weight: FontWeight.SemiBold), + Text = User.Username, + Truncate = true, + Shadow = false, + } + } + }, } }, new Container @@ -252,5 +231,60 @@ namespace osu.Game.Screens.Play.HUD Accuracy.BindValueChanged(v => accuracyText.Text = v.NewValue.FormatAccuracy(), true); Combo.BindValueChanged(v => comboText.Text = $"{v.NewValue}x", true); } + + protected override void LoadComplete() + { + base.LoadComplete(); + + updateColour(); + FinishTransforms(true); + } + + private const double panel_transition_duration = 500; + + private void updateColour() + { + if (scorePosition == 1) + { + mainFillContainer.ResizeWidthTo(EXTENDED_WIDTH, panel_transition_duration, Easing.OutElastic); + panelColour = Color4Extensions.FromHex("7fcc33"); + textColour = Color4.White; + } + else if (trackedPlayer) + { + mainFillContainer.ResizeWidthTo(EXTENDED_WIDTH, panel_transition_duration, Easing.OutElastic); + panelColour = Color4Extensions.FromHex("ffd966"); + textColour = Color4Extensions.FromHex("2e576b"); + } + else + { + mainFillContainer.ResizeWidthTo(regular_width, panel_transition_duration, Easing.OutElastic); + panelColour = Color4Extensions.FromHex("3399cc"); + textColour = Color4.White; + } + } + + private Color4 panelColour + { + set + { + mainFillContainer.FadeColour(value, panel_transition_duration, Easing.OutQuint); + centralFill.FadeColour(value, panel_transition_duration, Easing.OutQuint); + } + } + + private const double text_transition_duration = 200; + + private Color4 textColour + { + set + { + scoreText.FadeColour(value, text_transition_duration, Easing.OutQuint); + accuracyText.FadeColour(value, text_transition_duration, Easing.OutQuint); + comboText.FadeColour(value, text_transition_duration, Easing.OutQuint); + usernameText.FadeColour(value, text_transition_duration, Easing.OutQuint); + positionText.FadeColour(value, text_transition_duration, Easing.OutQuint); + } + } } } diff --git a/osu.Game/Tests/Visual/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/MultiplayerTestScene.cs index 4d073f16f4..6f24e00a92 100644 --- a/osu.Game/Tests/Visual/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/MultiplayerTestScene.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Online.Multiplayer; @@ -12,11 +13,7 @@ namespace osu.Game.Tests.Visual [Cached] private readonly Bindable currentRoom = new Bindable(); - protected Room Room - { - get => currentRoom.Value; - set => currentRoom.Value = value; - } + protected Room Room => currentRoom.Value; private CachedModelDependencyContainer dependencies; @@ -26,5 +23,11 @@ namespace osu.Game.Tests.Visual dependencies.Model.BindTo(currentRoom); return dependencies; } + + [SetUp] + public void Setup() => Schedule(() => + { + currentRoom.Value = new Room(); + }); } } diff --git a/osu.Game/Utils/FormatUtils.cs b/osu.Game/Utils/FormatUtils.cs index f2ab99f4b7..2578d8d835 100644 --- a/osu.Game/Utils/FormatUtils.cs +++ b/osu.Game/Utils/FormatUtils.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using Humanizer; + namespace osu.Game.Utils { public static class FormatUtils @@ -18,5 +20,11 @@ namespace osu.Game.Utils /// The accuracy to be formatted /// formatted accuracy in percentage public static string FormatAccuracy(this decimal accuracy) => $"{accuracy:0.00}%"; + + /// + /// Formats the supplied rank/leaderboard position in a consistent, simplified way. + /// + /// The rank/position to be formatted. + public static string FormatRank(this int rank) => rank.ToMetric(decimals: rank < 100_000 ? 1 : 0); } }