1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-12 10:57:27 +08:00
osu-lazer/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs
Salman Ahmed 98b420ee6f Remove no longer correct crown fade animation
Since the host is pinned to the top without any animation, it would look
jarring for the crown to fade away from the old panel (and at a 50ms
duration).
2022-03-18 07:25:12 +03:00

271 lines
11 KiB
C#

// 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.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online;
using osu.Game.Online.API;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets;
using osu.Game.Screens.Play.HUD;
using osu.Game.Users;
using osu.Game.Users.Drawables;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
{
public class ParticipantPanel : MultiplayerRoomComposite, IHasContextMenu
{
public readonly MultiplayerRoomUser User;
[Resolved]
private IAPIProvider api { get; set; }
[Resolved]
private IRulesetStore rulesets { get; set; }
private SpriteIcon crown;
private OsuSpriteText userRankText;
private ModDisplay userModsDisplay;
private StateDisplay userStateDisplay;
private IconButton kickButton;
public ParticipantPanel(MultiplayerRoomUser user)
{
User = user;
RelativeSizeAxes = Axes.X;
Height = 40;
}
[BackgroundDependencyLoader]
private void load()
{
var user = User.User;
var backgroundColour = Color4Extensions.FromHex("#33413C");
InternalChild = new GridContainer
{
RelativeSizeAxes = Axes.Both,
ColumnDimensions = new[]
{
new Dimension(GridSizeMode.Absolute, 18),
new Dimension(GridSizeMode.AutoSize),
new Dimension(),
new Dimension(GridSizeMode.AutoSize),
},
Content = new[]
{
new Drawable[]
{
crown = new SpriteIcon
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Icon = FontAwesome.Solid.Crown,
Size = new Vector2(14),
Colour = Color4Extensions.FromHex("#F7E65D"),
Alpha = 0
},
new TeamDisplay(User),
new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
CornerRadius = 5,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = backgroundColour
},
new UserCoverBackground
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
RelativeSizeAxes = Axes.Both,
Width = 0.75f,
User = user,
Colour = ColourInfo.GradientHorizontal(Color4.White.Opacity(0), Color4.White.Opacity(0.25f))
},
new FillFlowContainer
{
RelativeSizeAxes = Axes.Both,
Spacing = new Vector2(10),
Direction = FillDirection.Horizontal,
Children = new Drawable[]
{
new UpdateableAvatar
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
RelativeSizeAxes = Axes.Both,
FillMode = FillMode.Fit,
User = user
},
new UpdateableFlag
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Size = new Vector2(30, 20),
Country = user?.Country
},
new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18),
Text = user?.Username
},
userRankText = new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(size: 14),
}
}
},
new Container
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
AutoSizeAxes = Axes.Both,
Margin = new MarginPadding { Right = 70 },
Child = userModsDisplay = new ModDisplay
{
Scale = new Vector2(0.5f),
ExpansionMode = ExpansionMode.AlwaysContracted,
}
},
userStateDisplay = new StateDisplay
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Margin = new MarginPadding { Right = 10 },
}
}
},
kickButton = new KickButton
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Alpha = 0,
Margin = new MarginPadding(4),
Action = () => Client.KickUser(User.UserID),
},
},
}
};
}
protected override void OnRoomUpdated()
{
base.OnRoomUpdated();
if (Room == null || Client.LocalUser == null)
return;
const double fade_time = 50;
var currentItem = Playlist.GetCurrentItem();
Debug.Assert(currentItem != null);
var ruleset = rulesets.GetRuleset(currentItem.RulesetID)?.CreateInstance();
int? currentModeRank = ruleset != null ? User.User?.RulesetsStatistics?.GetValueOrDefault(ruleset.ShortName)?.GlobalRank : null;
userRankText.Text = currentModeRank != null ? $"#{currentModeRank.Value:N0}" : string.Empty;
userStateDisplay.UpdateStatus(User.State, User.BeatmapAvailability);
if ((User.BeatmapAvailability.State == DownloadState.LocallyAvailable) && (User.State != MultiplayerUserState.Spectating))
userModsDisplay.FadeIn(fade_time);
else
userModsDisplay.FadeOut(fade_time);
if (Client.IsHost && !User.Equals(Client.LocalUser))
kickButton.FadeIn(fade_time);
else
kickButton.FadeOut(fade_time);
crown.Alpha = Room.Host?.Equals(User) == true ? 1 : 0;
// If the mods are updated at the end of the frame, the flow container will skip a reflow cycle: https://github.com/ppy/osu-framework/issues/4187
// This looks particularly jarring here, so re-schedule the update to that start of our frame as a fix.
Schedule(() => userModsDisplay.Current.Value = User.Mods.Select(m => m.ToMod(ruleset)).ToList());
}
public MenuItem[] ContextMenuItems
{
get
{
if (Room == null)
return null;
// If the local user is targetted.
if (User.UserID == api.LocalUser.Value.Id)
return null;
// If the local user is not the host of the room.
if (Room.Host?.UserID != api.LocalUser.Value.Id)
return null;
int targetUser = User.UserID;
return new MenuItem[]
{
new OsuMenuItem("Give host", MenuItemType.Standard, () =>
{
// Ensure the local user is still host.
if (!Client.IsHost)
return;
Client.TransferHost(targetUser);
}),
new OsuMenuItem("Kick", MenuItemType.Destructive, () =>
{
// Ensure the local user is still host.
if (!Client.IsHost)
return;
Client.KickUser(targetUser);
})
};
}
}
public class KickButton : IconButton
{
public KickButton()
{
Icon = FontAwesome.Solid.UserTimes;
TooltipText = "Kick";
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
IconHoverColour = colours.Red;
}
}
}
}