1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-15 15:12:57 +08:00

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.Online.API;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchRulesets.TeamVs;
using osu.Game.Rulesets;
using osu.Game.Screens.Play.HUD;
using osu.Game.Users;
@ -38,7 +37,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
private RulesetStore rulesets { get; set; }
private SpriteIcon crown;
private Box teamDisplay;
private OsuSpriteText userRankText;
private ModDisplay userModsDisplay;
@ -59,106 +57,108 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
var backgroundColour = Color4Extensions.FromHex("#33413C");
InternalChildren = new Drawable[]
InternalChild = new GridContainer
{
crown = new SpriteIcon
RelativeSizeAxes = Axes.Both,
ColumnDimensions = new[]
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Icon = FontAwesome.Solid.Crown,
Size = new Vector2(14),
Colour = Color4Extensions.FromHex("#F7E65D"),
Alpha = 0
new Dimension(GridSizeMode.Absolute, 14),
new Dimension(GridSizeMode.AutoSize),
new Dimension()
},
teamDisplay = new Box
Content = new[]
{
Colour = Color4.Black,
RelativeSizeAxes = Axes.Y,
Width = 15,
Alpha = 0,
},
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = 24 },
Child = new Container
new Drawable[]
{
RelativeSizeAxes = Axes.Both,
Masking = true,
CornerRadius = 5,
Children = new Drawable[]
crown = new SpriteIcon
{
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,
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 Box
{
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,
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 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
},
new Container
{
Scale = new Vector2(0.5f),
ExpansionMode = ExpansionMode.AlwaysContracted,
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 },
}
},
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
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
// 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());
}
[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
{
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;
}
}
}
}