diff --git a/osu.Game.Tests/Visual/RankedPlay/TestSceneRankedPlayUserDisplay.cs b/osu.Game.Tests/Visual/RankedPlay/TestSceneRankedPlayUserDisplay.cs index f7cc9885c79a..de784157e9b4 100644 --- a/osu.Game.Tests/Visual/RankedPlay/TestSceneRankedPlayUserDisplay.cs +++ b/osu.Game.Tests/Visual/RankedPlay/TestSceneRankedPlayUserDisplay.cs @@ -4,6 +4,8 @@ using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Utils; +using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay; using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Components; using osu.Game.Tests.Visual.Multiplayer; @@ -20,11 +22,19 @@ public partial class TestSceneRankedPlayUserDisplay : MultiplayerTestScene Value = 1_000_000, }; + public TestSceneRankedPlayUserDisplay() + { + AddSliderStep("health", 0, 1_000_000, 1_000_000, value => health.Value = value); + } + public override void SetUpSteps() { base.SetUpSteps(); - AddStep("add display", () => Child = new RankedPlayUserDisplay(2, Anchor.BottomLeft, RankedPlayColourScheme.Blue) + AddStep("join room", () => JoinRoom(CreateDefaultRoom(MatchType.RankedPlay))); + WaitForJoined(); + + AddStep("add display", () => Child = new RankedPlayUserDisplay(1001, Anchor.BottomLeft, RankedPlayColourScheme.Blue) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -36,7 +46,7 @@ public override void SetUpSteps() [Test] public void TesUserDisplay() { - AddStep("blue color scheme", () => Child = new RankedPlayUserDisplay(2, Anchor.BottomLeft, RankedPlayColourScheme.Blue) + AddStep("blue color scheme", () => Child = new RankedPlayUserDisplay(1001, Anchor.BottomLeft, RankedPlayColourScheme.Blue) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -44,15 +54,30 @@ public void TesUserDisplay() Health = { BindTarget = health } }); - AddStep("red color scheme", () => Child = new RankedPlayUserDisplay(2, Anchor.BottomLeft, RankedPlayColourScheme.Red) + AddStep("red color scheme", () => Child = new RankedPlayUserDisplay(1001, Anchor.BottomLeft, RankedPlayColourScheme.Red) { Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(256, 72), Health = { BindTarget = health } }); + } - AddSliderStep("health", 0, 1_000_000, 1_000_000, value => health.Value = value); + [Test] + public void TestBeatmapState() + { + float progress = 0; + + AddStep("set unavailable", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.NotDownloaded())); + AddStep("set downloading", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(progress = 0))); + AddUntilStep("increment progress", () => + { + progress += RNG.NextSingle(0.1f); + MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(progress)); + return progress >= 1; + }); + AddStep("set to importing", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Importing())); + AddStep("set to available", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.LocallyAvailable())); } } } diff --git a/osu.Game/Screens/OnlinePlay/Matchmaking/RankedPlay/Components/RankedPlayUserDisplay.cs b/osu.Game/Screens/OnlinePlay/Matchmaking/RankedPlay/Components/RankedPlayUserDisplay.cs index 0195c47945f4..aa5b303aad49 100644 --- a/osu.Game/Screens/OnlinePlay/Matchmaking/RankedPlay/Components/RankedPlayUserDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Matchmaking/RankedPlay/Components/RankedPlayUserDisplay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; @@ -17,7 +18,10 @@ using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Sprites; +using osu.Game.Online; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Multiplayer; +using osu.Game.Online.Rooms; using osu.Game.Users.Drawables; using osuTK; using osuTK.Graphics; @@ -42,6 +46,13 @@ public partial class RankedPlayUserDisplay : CompositeDrawable private BufferedContainer grayScaleContainer = null!; + private OsuSpriteText beatmapState = null!; + + private BeatmapAvailability availability = BeatmapAvailability.Unknown(); + + [Resolved] + private MultiplayerClient client { get; set; } = null!; + [Resolved] private RankedPlayCornerPiece? cornerPiece { get; set; } @@ -61,6 +72,10 @@ private void load() ? -OsuGame.SHEAR : OsuGame.SHEAR; + var beatmapStateAnchor = (contentAnchor & Anchor.x0) != 0 + ? Anchor.CentreLeft + : Anchor.CentreRight; + InternalChildren = [ new CircularContainer @@ -103,15 +118,33 @@ private void load() Anchor = contentAnchor, Origin = contentAnchor, }, - new OsuSpriteText + new FillFlowContainer { - Name = "Username", - Text = user.Username, + Name = "Username/beatmap state container", + AutoSizeAxes = Axes.Both, Anchor = contentAnchor, Origin = contentAnchor, + Direction = FillDirection.Horizontal, Padding = new MarginPadding { Horizontal = 4, Vertical = 6 }, - Font = OsuFont.GetFont(size: 24, weight: FontWeight.SemiBold), - UseFullGlyphHeight = false, + Spacing = new Vector2(5, 0), + Children = + [ + new OsuSpriteText + { + Name = "Username", + Text = user.Username, + Anchor = contentAnchor, + Origin = contentAnchor, + Font = OsuFont.GetFont(size: 24, weight: FontWeight.SemiBold), + UseFullGlyphHeight = false, + }, + beatmapState = new OsuSpriteText + { + Anchor = beatmapStateAnchor, + Origin = beatmapStateAnchor, + Font = OsuFont.Torus.With(size: 12, weight: FontWeight.SemiBold), + }, + ], }, ] } @@ -129,6 +162,46 @@ protected override void LoadComplete() grayScaleContainer.GrayscaleTo(e.NewValue <= 0 ? 1 : 0, 300); cornerPiece?.OnHealthChanged(e.NewValue); }); + + client.RoomUpdated += onRoomUpdated; + } + + private void onRoomUpdated() + { + var user = client.Room?.Users.SingleOrDefault(u => u.UserID == userId); + + if (user == null || availability == user.BeatmapAvailability) + return; + + availability = user.BeatmapAvailability; + + if (availability.State is DownloadState.NotDownloaded or DownloadState.Downloading or DownloadState.Importing) + beatmapState.FadeIn(50); + else + beatmapState.FadeOut(50); + + switch (availability.State) + { + case DownloadState.NotDownloaded: + beatmapState.Text = "Missing Beatmap"; + break; + + case DownloadState.Downloading: + double progress = Math.Clamp(availability.DownloadProgress ?? 0, 0, 1); + beatmapState.Text = $"Downloading... ({progress:P0})"; + break; + + case DownloadState.Importing: + beatmapState.Text = "Importing..."; + break; + } + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + client.RoomUpdated -= onRoomUpdated; } public partial class HealthBar : CompositeDrawable