Add the ability to change team by clicking current team colour

Definitely not the final UX, but it's what people are used to and easy
to implement, so it'll do for now.
This commit is contained in:
Dean Herbert 2021-08-02 17:07:08 +09:00
parent 9bfb0f1294
commit b8e878ccc9
2 changed files with 218 additions and 113 deletions

View File

@ -17,7 +17,6 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchRulesets.TeamVs;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.HUD;
using osu.Game.Users; using osu.Game.Users;
@ -38,7 +37,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
private RulesetStore rulesets { get; set; } private RulesetStore rulesets { get; set; }
private SpriteIcon crown; private SpriteIcon crown;
private Box teamDisplay;
private OsuSpriteText userRankText; private OsuSpriteText userRankText;
private ModDisplay userModsDisplay; private ModDisplay userModsDisplay;
@ -59,106 +57,108 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
var backgroundColour = Color4Extensions.FromHex("#33413C"); var backgroundColour = Color4Extensions.FromHex("#33413C");
InternalChildren = new Drawable[] InternalChild = new GridContainer
{ {
crown = new SpriteIcon RelativeSizeAxes = Axes.Both,
ColumnDimensions = new[]
{ {
Anchor = Anchor.CentreLeft, new Dimension(GridSizeMode.Absolute, 14),
Origin = Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize),
Icon = FontAwesome.Solid.Crown, new Dimension()
Size = new Vector2(14),
Colour = Color4Extensions.FromHex("#F7E65D"),
Alpha = 0
}, },
teamDisplay = new Box Content = new[]
{ {
Colour = Color4.Black, new Drawable[]
RelativeSizeAxes = Axes.Y,
Width = 15,
Alpha = 0,
},
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = 24 },
Child = new Container
{ {
RelativeSizeAxes = Axes.Both, crown = new SpriteIcon
Masking = true,
CornerRadius = 5,
Children = new Drawable[]
{ {
new Box 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[]
{ {
RelativeSizeAxes = Axes.Both, new Box
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 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[]
{ {
Anchor = Anchor.CentreLeft, new UpdateableAvatar
Origin = Anchor.CentreLeft, {
RelativeSizeAxes = Axes.Both, Anchor = Anchor.CentreLeft,
FillMode = FillMode.Fit, Origin = Anchor.CentreLeft,
User = user RelativeSizeAxes = Axes.Both,
}, FillMode = FillMode.Fit,
new UpdateableFlag User = user
{ },
Anchor = Anchor.CentreLeft, new UpdateableFlag
Origin = Anchor.CentreLeft, {
Size = new Vector2(30, 20), Anchor = Anchor.CentreLeft,
Country = user?.Country Origin = Anchor.CentreLeft,
}, Size = new Vector2(30, 20),
new OsuSpriteText Country = user?.Country
{ },
Anchor = Anchor.CentreLeft, new OsuSpriteText
Origin = Anchor.CentreLeft, {
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18), Anchor = Anchor.CentreLeft,
Text = user?.Username Origin = Anchor.CentreLeft,
}, Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18),
userRankText = new OsuSpriteText Text = user?.Username
{ },
Anchor = Anchor.CentreLeft, userRankText = new OsuSpriteText
Origin = Anchor.CentreLeft, {
Font = OsuFont.GetFont(size: 14), Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(size: 14),
}
} }
} },
}, new Container
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), Anchor = Anchor.CentreRight,
ExpansionMode = ExpansionMode.AlwaysContracted, 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 },
} }
},
userStateDisplay = new StateDisplay
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Margin = new MarginPadding { Right = 10 },
} }
} }
} },
} }
}; };
} }
@ -184,36 +184,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
else else
crown.FadeOut(fade_time); crown.FadeOut(fade_time);
if (User.MatchRulesetState is TeamVsMatchUserState teamState)
{
teamDisplay.Show();
teamDisplay.FadeColour(getColourForTeam(teamState.TeamID), 100, Easing.OutQuint);
}
else
{
teamDisplay.Hide();
}
// 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 // 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. // 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()); Schedule(() => userModsDisplay.Current.Value = User.Mods.Select(m => m.ToMod(ruleset)).ToList());
} }
[Resolved]
private OsuColour colours { get; set; }
private ColourInfo getColourForTeam(int id)
{
switch (id)
{
default:
return colours.Red;
case 1:
return colours.Blue;
}
}
public MenuItem[] ContextMenuItems public MenuItem[] ContextMenuItems
{ {
get get

View File

@ -0,0 +1,130 @@
// 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.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
using osu.Game.Users;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
{
internal class TeamDisplay : MultiplayerRoomComposite
{
private readonly User user;
private Drawable box;
[Resolved]
private OsuColour colours { get; set; }
[Resolved]
private MultiplayerClient client { get; set; }
public TeamDisplay(User user)
{
this.user = user;
RelativeSizeAxes = Axes.Y;
Width = 15;
Margin = new MarginPadding { Horizontal = 3 };
}
[BackgroundDependencyLoader]
private void load()
{
box = new Container
{
RelativeSizeAxes = Axes.Both,
CornerRadius = 5,
Masking = true,
Alpha = 0,
Scale = new Vector2(0, 1),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Child = new Box
{
Colour = Color4.White,
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
};
if (user.Id == client.LocalUser?.UserID)
{
InternalChild = new OsuClickableContainer
{
RelativeSizeAxes = Axes.Both,
TooltipText = "Change team",
Action = changeTeam,
Child = box
};
}
else
{
InternalChild = box;
}
}
private void changeTeam()
{
client.SendMatchRequest(new ChangeTeamRequest
{
TeamID = ((client.LocalUser?.MatchState as TeamVersusUserState)?.TeamID + 1) % 2 ?? 0,
});
}
private int? displayedTeam;
protected override void OnRoomUpdated()
{
base.OnRoomUpdated();
// we don't have a way of knowing when an individual user's state has updated, so just handle on RoomUpdated for now.
var userRoomState = Room?.Users.FirstOrDefault(u => u.UserID == user.Id)?.MatchState;
const double duration = 400;
int? newTeam = (userRoomState as TeamVersusUserState)?.TeamID;
if (newTeam == displayedTeam)
return;
displayedTeam = newTeam;
if (displayedTeam != null)
{
box.FadeIn(duration);
box.FadeColour(getColourForTeam(displayedTeam.Value), duration, Easing.OutQuint);
box.ScaleTo(new Vector2(box.Scale.X < 0 ? 1 : -1, 1), duration, Easing.OutQuint);
}
else
{
box.ScaleTo(new Vector2(0, 1), duration, Easing.OutQuint);
box.FadeOut(duration);
}
}
private ColourInfo getColourForTeam(int id)
{
switch (id)
{
default:
return colours.Red;
case 1:
return colours.Blue;
}
}
}
}