Merge branch 'master' into spectator-driven-leaderboard

This commit is contained in:
Dean Herbert 2020-12-20 01:13:59 +09:00 committed by GitHub
commit b3bff281ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 220 additions and 215 deletions

View File

@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay
playerScore.Value = 1222333; 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); 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 player2Score = new BindableDouble(1234567);
var player3Score = new BindableDouble(1111111); var player3Score = new BindableDouble(1111111);
AddStep("add player 2", () => createLeaderboardScore(player2Score, "Player 2")); AddStep("add player 2", () => createLeaderboardScore(player2Score, new User { Username = "Player 2" }));
AddStep("add player 3", () => createLeaderboardScore(player3Score, "Player 3")); 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 2 position #1", () => leaderboard.CheckPositionByUsername("Player 2", 1));
AddAssert("is player position #2", () => leaderboard.CheckPositionByUsername("You", 2)); AddAssert("is player position #2", () => leaderboard.CheckPositionByUsername("You", 2));
@ -71,12 +71,23 @@ namespace osu.Game.Tests.Visual.Gameplay
public void TestRandomScores() public void TestRandomScores()
{ {
int playerNumber = 1; 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); leaderboardScore.TotalScore.BindTo(score);
} }

View File

@ -4,7 +4,6 @@
using System; using System;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.RoomStatuses; using osu.Game.Online.Multiplayer.RoomStatuses;
using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Screens.Multi.Lounge.Components;
using osu.Game.Users; using osu.Game.Users;
@ -14,10 +13,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
public class TestSceneLoungeRoomInfo : MultiplayerTestScene public class TestSceneLoungeRoomInfo : MultiplayerTestScene
{ {
[SetUp] [SetUp]
public void Setup() => Schedule(() => public new void Setup() => Schedule(() =>
{ {
Room = new Room();
Child = new RoomInfo Child = new RoomInfo
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,

View File

@ -24,10 +24,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
private RulesetStore rulesetStore { get; set; } private RulesetStore rulesetStore { get; set; }
[SetUp] [SetUp]
public void Setup() => Schedule(() => public new void Setup() => Schedule(() =>
{ {
Room = new Room();
Child = new MatchBeatmapDetailArea Child = new MatchBeatmapDetailArea
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
@ -14,7 +15,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
{ {
public TestSceneMatchHeader() public TestSceneMatchHeader()
{ {
Room = new Room(); Child = new Header();
}
[SetUp]
public new void Setup() => Schedule(() =>
{
Room.Playlist.Add(new PlaylistItem Room.Playlist.Add(new PlaylistItem
{ {
Beatmap = Beatmap =
@ -41,8 +47,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
Room.Name.Value = "A very awesome room"; Room.Name.Value = "A very awesome room";
Room.Host.Value = new User { Id = 2, Username = "peppy" }; Room.Host.Value = new User { Id = 2, Username = "peppy" };
});
Child = new Header();
}
} }
} }

View File

@ -3,10 +3,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json; using Newtonsoft.Json;
using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.Multiplayer;
using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Match.Components;
using osu.Game.Users; using osu.Game.Users;
using osuTK; using osuTK;
@ -19,8 +19,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
public TestSceneMatchLeaderboard() public TestSceneMatchLeaderboard()
{ {
Room = new Room { RoomID = { Value = 3 } };
Add(new MatchLeaderboard Add(new MatchLeaderboard
{ {
Origin = Anchor.Centre, Origin = Anchor.Centre,
@ -40,6 +38,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
api.Queue(req); api.Queue(req);
} }
[SetUp]
public new void Setup() => Schedule(() =>
{
Room.RoomID.Value = 3;
});
private class GetRoomScoresRequest : APIRequest<List<RoomScore>> private class GetRoomScoresRequest : APIRequest<List<RoomScore>>
{ {
protected override string Target => "rooms/3/leaderboard"; protected override string Target => "rooms/3/leaderboard";

View File

@ -23,10 +23,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
private TestRoomSettings settings; private TestRoomSettings settings;
[SetUp] [SetUp]
public void Setup() => Schedule(() => public new void Setup() => Schedule(() =>
{ {
Room = new Room();
settings = new TestRoomSettings settings = new TestRoomSettings
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,

View File

@ -14,7 +14,6 @@ using osu.Framework.Platform;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Framework.Utils; using osu.Framework.Utils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Online.Multiplayer;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
@ -94,12 +93,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("wait for present", () => songSelect.IsCurrentScreen()); AddUntilStep("wait for present", () => songSelect.IsCurrentScreen());
} }
[SetUp]
public void Setup() => Schedule(() =>
{
Room = new Room();
});
[Test] [Test]
public void TestItemAddedIfEmptyOnStart() public void TestItemAddedIfEmptyOnStart()
{ {

View File

@ -45,12 +45,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
manager.Import(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait(); manager.Import(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait();
} }
[SetUp]
public void Setup() => Schedule(() =>
{
Room = new Room();
});
[SetUpSteps] [SetUpSteps]
public void SetupSteps() public void SetupSteps()
{ {

View File

@ -1,50 +0,0 @@
// 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 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)
};
});
}
}
}

View File

@ -1,39 +0,0 @@
// 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.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),
});
}
}
}

View File

@ -3,24 +3,55 @@
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Online.Multiplayer;
using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Multi.Components;
using osu.Game.Users;
namespace osu.Game.Tests.Visual.Multiplayer namespace osu.Game.Tests.Visual.Multiplayer
{ {
public class TestSceneParticipantsList : MultiplayerTestScene public class TestSceneParticipantsList : MultiplayerTestScene
{ {
protected override bool UseOnlineAPI => true;
[SetUp] [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,
};
});
} }
} }
} }

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
@ -22,18 +23,21 @@ namespace osu.Game.Tests.Visual.Multiplayer
new DrawableRoom(new Room new DrawableRoom(new Room
{ {
Name = { Value = "Room 1" }, Name = { Value = "Room 1" },
Status = { Value = new RoomStatusOpen() } Status = { Value = new RoomStatusOpen() },
}), EndDate = { Value = DateTimeOffset.Now.AddDays(1) }
}) { MatchingFilter = true },
new DrawableRoom(new Room new DrawableRoom(new Room
{ {
Name = { Value = "Room 2" }, Name = { Value = "Room 2" },
Status = { Value = new RoomStatusPlaying() } Status = { Value = new RoomStatusPlaying() },
}), EndDate = { Value = DateTimeOffset.Now.AddDays(1) }
}) { MatchingFilter = true },
new DrawableRoom(new Room new DrawableRoom(new Room
{ {
Name = { Value = "Room 3" }, Name = { Value = "Room 3" },
Status = { Value = new RoomStatusEnded() } Status = { Value = new RoomStatusEnded() },
}), EndDate = { Value = DateTimeOffset.Now }
}) { MatchingFilter = true },
} }
}; };
} }

View File

@ -24,8 +24,8 @@ using osu.Game.Scoring;
using osu.Game.Users.Drawables; using osu.Game.Users.Drawables;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using Humanizer;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Utils;
namespace osu.Game.Online.Leaderboards namespace osu.Game.Online.Leaderboards
{ {
@ -358,7 +358,7 @@ namespace osu.Game.Online.Leaderboards
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Font = OsuFont.GetFont(size: 20, italics: true), Font = OsuFont.GetFont(size: 20, italics: true),
Text = rank == null ? "-" : rank.Value.ToMetric(decimals: rank < 100000 ? 1 : 0), Text = rank == null ? "-" : rank.Value.FormatRank()
}; };
} }

View File

@ -92,6 +92,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
} }
} }
private Container dragHandles;
private FillFlowContainer buttons; private FillFlowContainer buttons;
public const float BORDER_RADIUS = 3; 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 buttons = new FillFlowContainer
{ {
Y = 20, 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, Anchor = anchor,
HandleDrag = e => OnScale?.Invoke(e.Delta, anchor), HandleDrag = e => OnScale?.Invoke(e.Delta, anchor),

View File

@ -24,6 +24,14 @@ namespace osu.Game.Screens.Play.HUD
LayoutEasing = Easing.OutQuint; LayoutEasing = Easing.OutQuint;
} }
/// <summary>
/// Adds a player to the leaderboard.
/// </summary>
/// <param name="user">The player.</param>
/// <param name="isTracked">
/// Whether the player should be tracked on the leaderboard.
/// Set to <c>true</c> for the local player or a player whose replay is currently being played.
/// </param>
public ILeaderboardScore AddPlayer(User user, bool isTracked) public ILeaderboardScore AddPlayer(User user, bool isTracked)
{ {
var drawable = new GameplayLeaderboardScore(user, isTracked) var drawable = new GameplayLeaderboardScore(user, isTracked)
@ -40,9 +48,9 @@ namespace osu.Game.Screens.Play.HUD
return drawable; 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() private void sort()

View File

@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using Humanizer;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
@ -11,6 +10,7 @@ using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Users; using osu.Game.Users;
using osu.Game.Users.Drawables;
using osu.Game.Utils; using osu.Game.Utils;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
@ -19,9 +19,9 @@ namespace osu.Game.Screens.Play.HUD
{ {
public class GameplayLeaderboardScore : CompositeDrawable, ILeaderboardScore 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; public const float PANEL_HEIGHT = 35f;
@ -48,7 +48,7 @@ namespace osu.Game.Screens.Play.HUD
scorePosition = value; scorePosition = value;
if (scorePosition.HasValue) if (scorePosition.HasValue)
positionText.Text = $"#{scorePosition.Value.ToMetric(decimals: scorePosition < 100000 ? 1 : 0)}"; positionText.Text = $"#{scorePosition.Value.FormatRank()}";
positionText.FadeTo(scorePosition.HasValue ? 1 : 0); positionText.FadeTo(scorePosition.HasValue ? 1 : 0);
updateColour(); updateColour();
@ -75,61 +75,8 @@ namespace osu.Game.Screens.Play.HUD
Size = new Vector2(EXTENDED_WIDTH, PANEL_HEIGHT); 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] [BackgroundDependencyLoader]
private void load() private void load(OsuColour colours)
{ {
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
@ -195,19 +142,51 @@ namespace osu.Game.Screens.Play.HUD
}, },
} }
}, },
usernameText = new OsuSpriteText new FillFlowContainer
{ {
Padding = new MarginPadding { Left = SHEAR_WIDTH }, Padding = new MarginPadding { Left = SHEAR_WIDTH },
RelativeSizeAxes = Axes.X,
Width = 0.8f,
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft, Origin = Anchor.CentreLeft,
Colour = Color4.White, RelativeSizeAxes = Axes.Both,
Font = OsuFont.Torus.With(size: 14, weight: FontWeight.SemiBold), Direction = FillDirection.Horizontal,
Text = User.Username, Spacing = new Vector2(4f, 0f),
Truncate = true, Children = new Drawable[]
Shadow = false, {
} 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 new Container
@ -252,5 +231,60 @@ namespace osu.Game.Screens.Play.HUD
Accuracy.BindValueChanged(v => accuracyText.Text = v.NewValue.FormatAccuracy(), true); Accuracy.BindValueChanged(v => accuracyText.Text = v.NewValue.FormatAccuracy(), true);
Combo.BindValueChanged(v => comboText.Text = $"{v.NewValue}x", 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);
}
}
} }
} }

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
@ -12,11 +13,7 @@ namespace osu.Game.Tests.Visual
[Cached] [Cached]
private readonly Bindable<Room> currentRoom = new Bindable<Room>(); private readonly Bindable<Room> currentRoom = new Bindable<Room>();
protected Room Room protected Room Room => currentRoom.Value;
{
get => currentRoom.Value;
set => currentRoom.Value = value;
}
private CachedModelDependencyContainer<Room> dependencies; private CachedModelDependencyContainer<Room> dependencies;
@ -26,5 +23,11 @@ namespace osu.Game.Tests.Visual
dependencies.Model.BindTo(currentRoom); dependencies.Model.BindTo(currentRoom);
return dependencies; return dependencies;
} }
[SetUp]
public void Setup() => Schedule(() =>
{
currentRoom.Value = new Room();
});
} }
} }

View File

@ -1,6 +1,8 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using Humanizer;
namespace osu.Game.Utils namespace osu.Game.Utils
{ {
public static class FormatUtils public static class FormatUtils
@ -18,5 +20,11 @@ namespace osu.Game.Utils
/// <param name="accuracy">The accuracy to be formatted</param> /// <param name="accuracy">The accuracy to be formatted</param>
/// <returns>formatted accuracy in percentage</returns> /// <returns>formatted accuracy in percentage</returns>
public static string FormatAccuracy(this decimal accuracy) => $"{accuracy:0.00}%"; public static string FormatAccuracy(this decimal accuracy) => $"{accuracy:0.00}%";
/// <summary>
/// Formats the supplied rank/leaderboard position in a consistent, simplified way.
/// </summary>
/// <param name="rank">The rank/position to be formatted.</param>
public static string FormatRank(this int rank) => rank.ToMetric(decimals: rank < 100_000 ? 1 : 0);
} }
} }