1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-18 11:43:22 +08:00

Display user style in participant panel

This commit is contained in:
Dan Balasescu 2024-12-25 23:30:24 +09:00
parent 0093af8f55
commit c3aa9d6f8a
No known key found for this signature in database
2 changed files with 128 additions and 4 deletions

View File

@ -308,6 +308,33 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("set state: locally available", () => MultiplayerClient.ChangeUserBeatmapAvailability(0, BeatmapAvailability.LocallyAvailable()));
}
[Test]
public void TestUserWithStyle()
{
AddStep("add users", () =>
{
MultiplayerClient.AddUser(new APIUser
{
Id = 0,
Username = "User 0",
RulesetsStatistics = new Dictionary<string, UserStatistics>
{
{
Ruleset.Value.ShortName,
new UserStatistics { GlobalRank = RNG.Next(1, 100000), }
}
},
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
});
MultiplayerClient.ChangeUserStyle(0, 259, 2);
});
AddStep("set beatmap locally available", () => MultiplayerClient.ChangeUserBeatmapAvailability(0, BeatmapAvailability.LocallyAvailable()));
AddStep("change user style to beatmap: 258, ruleset: 1", () => MultiplayerClient.ChangeUserStyle(0, 258, 1));
AddStep("change user style to beatmap: null, ruleset: null", () => MultiplayerClient.ChangeUserStyle(0, null, null));
}
[Test]
public void TestModOverlap()
{

View File

@ -4,6 +4,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Extensions.ObjectExtensions;
@ -14,6 +16,9 @@ using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Logging;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
@ -47,6 +52,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
private SpriteIcon crown = null!;
private OsuSpriteText userRankText = null!;
private StyleDisplayIcon userStyleDisplay = null!;
private ModDisplay userModsDisplay = null!;
private StateDisplay userStateDisplay = null!;
@ -149,16 +155,20 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
}
}
},
new Container
new FillFlowContainer
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
AutoSizeAxes = Axes.Both,
Margin = new MarginPadding { Right = 70 },
Child = userModsDisplay = new ModDisplay
Children = new Drawable[]
{
Scale = new Vector2(0.5f),
ExpansionMode = ExpansionMode.AlwaysContracted,
userStyleDisplay = new StyleDisplayIcon(),
userModsDisplay = new ModDisplay
{
Scale = new Vector2(0.5f),
ExpansionMode = ExpansionMode.AlwaysContracted,
}
}
},
userStateDisplay = new StateDisplay
@ -208,9 +218,20 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
userStateDisplay.UpdateStatus(User.State, User.BeatmapAvailability);
if ((User.BeatmapAvailability.State == DownloadState.LocallyAvailable) && (User.State != MultiplayerUserState.Spectating))
{
userModsDisplay.FadeIn(fade_time);
userStyleDisplay.FadeIn(fade_time);
}
else
{
userModsDisplay.FadeOut(fade_time);
userStyleDisplay.FadeOut(fade_time);
}
if (User.BeatmapId == null && User.RulesetId == null)
userStyleDisplay.Style = null;
else
userStyleDisplay.Style = (User.BeatmapId ?? currentItem?.BeatmapID ?? 0, User.RulesetId ?? currentItem?.RulesetID ?? 0);
kickButton.Alpha = client.IsHost && !User.Equals(client.LocalUser) ? 1 : 0;
crown.Alpha = client.Room.Host?.Equals(User) == true ? 1 : 0;
@ -284,5 +305,81 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
IconHoverColour = colours.Red;
}
}
private partial class StyleDisplayIcon : CompositeComponent
{
[Resolved]
private BeatmapLookupCache beatmapLookupCache { get; set; } = null!;
[Resolved]
private RulesetStore rulesets { get; set; } = null!;
public StyleDisplayIcon()
{
AutoSizeAxes = Axes.Both;
}
private (int beatmap, int ruleset)? style;
public (int beatmap, int ruleset)? Style
{
get => style;
set
{
if (style == value)
return;
style = value;
Scheduler.Add(refresh);
}
}
private CancellationTokenSource? cancellationSource;
private void refresh()
{
cancellationSource?.Cancel();
cancellationSource?.Dispose();
cancellationSource = null;
if (Style == null)
{
ClearInternal();
return;
}
cancellationSource = new CancellationTokenSource();
CancellationToken token = cancellationSource.Token;
int localBeatmap = Style.Value.beatmap;
int localRuleset = Style.Value.ruleset;
Task.Run(async () =>
{
try
{
var beatmap = await beatmapLookupCache.GetBeatmapAsync(localBeatmap, token).ConfigureAwait(false);
if (beatmap == null)
return;
Schedule(() =>
{
if (token.IsCancellationRequested)
return;
InternalChild = new DifficultyIcon(beatmap, rulesets.GetRuleset(localRuleset))
{
Size = new Vector2(20),
TooltipType = DifficultyIconTooltipType.Extended,
};
});
}
catch (Exception e)
{
Logger.Log($"Error while populating participant style icon {e}");
}
}, token);
}
}
}
}