From ce806dd880f58b03e18fdf80d76ce9f5c67c86e1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Dec 2020 18:25:45 +0900 Subject: [PATCH 1/4] Replace the ready mark display with a state display, showing all participant states --- .../Multiplayer/TestSceneParticipantsList.cs | 1 + .../TestSceneParticipantsList.cs | 11 +- .../Participants/ParticipantPanel.cs | 10 +- .../Participants/ReadyMark.cs | 51 ------- .../Participants/StateDisplay.cs | 128 ++++++++++++++++++ 5 files changed, 138 insertions(+), 63 deletions(-) delete mode 100644 osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/ReadyMark.cs create mode 100644 osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/StateDisplay.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs index 7bbec7d30e..360aa22af9 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs @@ -20,6 +20,7 @@ namespace osu.Game.Tests.Visual.Multiplayer Room.RecentParticipants.Add(new User { Username = "peppy", + CurrentModeRank = 1234, Id = 2 }); } diff --git a/osu.Game.Tests/Visual/RealtimeMultiplayer/TestSceneParticipantsList.cs b/osu.Game.Tests/Visual/RealtimeMultiplayer/TestSceneParticipantsList.cs index 8c997e9e32..35ea0d3813 100644 --- a/osu.Game.Tests/Visual/RealtimeMultiplayer/TestSceneParticipantsList.cs +++ b/osu.Game.Tests/Visual/RealtimeMultiplayer/TestSceneParticipantsList.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Testing; +using osu.Framework.Utils; using osu.Game.Online.RealtimeMultiplayer; using osu.Game.Screens.Multi.RealtimeMultiplayer.Participants; using osu.Game.Users; @@ -65,13 +66,13 @@ namespace osu.Game.Tests.Visual.RealtimeMultiplayer [Test] public void TestToggleReadyState() { - AddAssert("ready mark invisible", () => !this.ChildrenOfType().Single().IsPresent); + AddAssert("ready mark invisible", () => !this.ChildrenOfType().Single().IsPresent); AddStep("make user ready", () => Client.ChangeState(MultiplayerUserState.Ready)); - AddUntilStep("ready mark visible", () => this.ChildrenOfType().Single().IsPresent); + AddUntilStep("ready mark visible", () => this.ChildrenOfType().Single().IsPresent); AddStep("make user idle", () => Client.ChangeState(MultiplayerUserState.Idle)); - AddUntilStep("ready mark invisible", () => !this.ChildrenOfType().Single().IsPresent); + AddUntilStep("ready mark invisible", () => !this.ChildrenOfType().Single().IsPresent); } [Test] @@ -104,11 +105,11 @@ namespace osu.Game.Tests.Visual.RealtimeMultiplayer { Id = i, Username = $"User {i}", + CurrentModeRank = RNG.Next(1, 100000), CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", }); - if (i % 2 == 0) - Client.ChangeUserState(i, MultiplayerUserState.Ready); + Client.ChangeUserState(i, (MultiplayerUserState)RNG.Next(0, (int)MultiplayerUserState.Results)); } }); } diff --git a/osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/ParticipantPanel.cs index 002849a275..a4ff2ce346 100644 --- a/osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/ParticipantPanel.cs @@ -30,7 +30,7 @@ namespace osu.Game.Screens.Multi.RealtimeMultiplayer.Participants [Resolved] private IAPIProvider api { get; set; } - private ReadyMark readyMark; + private StateDisplay userStateDisplay; private SpriteIcon crown; public ParticipantPanel(MultiplayerRoomUser user) @@ -122,12 +122,11 @@ namespace osu.Game.Screens.Multi.RealtimeMultiplayer.Participants } } }, - readyMark = new ReadyMark + userStateDisplay = new StateDisplay { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Margin = new MarginPadding { Right = 10 }, - Alpha = 0 } } } @@ -144,10 +143,7 @@ namespace osu.Game.Screens.Multi.RealtimeMultiplayer.Participants const double fade_time = 50; - if (User.State == MultiplayerUserState.Ready) - readyMark.FadeIn(fade_time); - else - readyMark.FadeOut(fade_time); + userStateDisplay.Status = User.State; if (Room.Host?.Equals(User) == true) crown.FadeIn(fade_time); diff --git a/osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/ReadyMark.cs b/osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/ReadyMark.cs deleted file mode 100644 index df49d9342e..0000000000 --- a/osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/ReadyMark.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osuTK; - -namespace osu.Game.Screens.Multi.RealtimeMultiplayer.Participants -{ - public class ReadyMark : CompositeDrawable - { - public ReadyMark() - { - AutoSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader] - private void load() - { - InternalChild = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Spacing = new Vector2(5), - Children = new Drawable[] - { - new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 12), - Text = "ready", - Colour = Color4Extensions.FromHex("#DDFFFF") - }, - new SpriteIcon - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Icon = FontAwesome.Solid.CheckCircle, - Size = new Vector2(12), - Colour = Color4Extensions.FromHex("#AADD00") - } - } - }; - } - } -} diff --git a/osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/StateDisplay.cs b/osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/StateDisplay.cs new file mode 100644 index 0000000000..db93525217 --- /dev/null +++ b/osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/StateDisplay.cs @@ -0,0 +1,128 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.RealtimeMultiplayer; +using osuTK; + +namespace osu.Game.Screens.Multi.RealtimeMultiplayer.Participants +{ + public class StateDisplay : CompositeDrawable + { + public StateDisplay() + { + AutoSizeAxes = Axes.Both; + } + + private MultiplayerUserState status; + + private OsuSpriteText text; + private SpriteIcon icon; + + private const double fade_time = 50; + + public MultiplayerUserState Status + { + set + { + if (value == status) + return; + + status = value; + + if (IsLoaded) + updateStatus(); + } + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(5), + Children = new Drawable[] + { + text = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(weight: FontWeight.Regular, size: 12), + Colour = Color4Extensions.FromHex("#DDFFFF") + }, + icon = new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.Solid.CheckCircle, + Size = new Vector2(12), + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateStatus(); + } + + [Resolved] + private OsuColour colours { get; set; } + + private void updateStatus() + { + switch (status) + { + default: + this.FadeOut(fade_time); + return; + + case MultiplayerUserState.Ready: + text.Text = "ready"; + icon.Icon = FontAwesome.Solid.CheckCircle; + icon.Colour = Color4Extensions.FromHex("#AADD00"); + break; + + case MultiplayerUserState.WaitingForLoad: + text.Text = "loading"; + icon.Icon = FontAwesome.Solid.PauseCircle; + icon.Colour = colours.Yellow; + break; + + case MultiplayerUserState.Loaded: + text.Text = "loaded"; + icon.Icon = FontAwesome.Solid.DotCircle; + icon.Colour = colours.YellowLight; + break; + + case MultiplayerUserState.Playing: + text.Text = "playing"; + icon.Icon = FontAwesome.Solid.PlayCircle; + icon.Colour = colours.BlueLight; + break; + + case MultiplayerUserState.FinishedPlay: + text.Text = "results pending"; + icon.Icon = FontAwesome.Solid.ArrowAltCircleUp; + icon.Colour = colours.BlueLighter; + break; + + case MultiplayerUserState.Results: + text.Text = "results"; + icon.Icon = FontAwesome.Solid.ArrowAltCircleUp; + icon.Colour = colours.BlueLighter; + break; + } + + this.FadeIn(fade_time); + } + } +} From 23bf9c372c71d15049595955c22bda7df3939dfd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Dec 2020 18:26:39 +0900 Subject: [PATCH 2/4] Fix naming conflict with test scenes --- ...articipantsList.cs => TestSceneTimeshiftParticipantsList.cs} | 2 +- ...sList.cs => TestSceneRealtimeMultiplayerParticipantsList.cs} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename osu.Game.Tests/Visual/Multiplayer/{TestSceneParticipantsList.cs => TestSceneTimeshiftParticipantsList.cs} (95%) rename osu.Game.Tests/Visual/RealtimeMultiplayer/{TestSceneParticipantsList.cs => TestSceneRealtimeMultiplayerParticipantsList.cs} (97%) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftParticipantsList.cs similarity index 95% rename from osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs rename to osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftParticipantsList.cs index 360aa22af9..efc3be032c 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftParticipantsList.cs @@ -8,7 +8,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneParticipantsList : MultiplayerTestScene + public class TestSceneTimeshiftParticipantsList : MultiplayerTestScene { [SetUp] public new void Setup() => Schedule(() => diff --git a/osu.Game.Tests/Visual/RealtimeMultiplayer/TestSceneParticipantsList.cs b/osu.Game.Tests/Visual/RealtimeMultiplayer/TestSceneRealtimeMultiplayerParticipantsList.cs similarity index 97% rename from osu.Game.Tests/Visual/RealtimeMultiplayer/TestSceneParticipantsList.cs rename to osu.Game.Tests/Visual/RealtimeMultiplayer/TestSceneRealtimeMultiplayerParticipantsList.cs index 35ea0d3813..7fd31906f7 100644 --- a/osu.Game.Tests/Visual/RealtimeMultiplayer/TestSceneParticipantsList.cs +++ b/osu.Game.Tests/Visual/RealtimeMultiplayer/TestSceneRealtimeMultiplayerParticipantsList.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Tests.Visual.RealtimeMultiplayer { - public class TestSceneParticipantsList : RealtimeMultiplayerTestScene + public class TestSceneRealtimeMultiplayerParticipantsList : RealtimeMultiplayerTestScene { [SetUp] public new void Setup() => Schedule(() => From 5efc3b94961cf918fa96b54818382e89b2cd9faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 22 Dec 2020 21:12:28 +0100 Subject: [PATCH 3/4] Start state display as hidden Would otherwise flicker for a few frames when a new user was added to the list of participants. --- .../Multi/RealtimeMultiplayer/Participants/StateDisplay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/StateDisplay.cs b/osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/StateDisplay.cs index db93525217..844f239363 100644 --- a/osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/StateDisplay.cs +++ b/osu.Game/Screens/Multi/RealtimeMultiplayer/Participants/StateDisplay.cs @@ -18,6 +18,7 @@ namespace osu.Game.Screens.Multi.RealtimeMultiplayer.Participants public StateDisplay() { AutoSizeAxes = Axes.Both; + Alpha = 0; } private MultiplayerUserState status; From 4a677ecc190f0ec7b354db5f2436349353cd9f2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 22 Dec 2020 21:16:45 +0100 Subject: [PATCH 4/4] Make random state choice in test more robust `RNG.Next(int, int)` is max-exclusive, so the random state choice would actually never pick `MultiplayerUserState.Results` on its own. The only reason why that state ever did show up was by a freak accident of sorts (the logic in `TestRealtimeMultiplayerClient` would automatically convert every `FinishedPlay` state to `Results`, up until seeing the first player that was in the `Playing` state). --- .../TestSceneRealtimeMultiplayerParticipantsList.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/RealtimeMultiplayer/TestSceneRealtimeMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/RealtimeMultiplayer/TestSceneRealtimeMultiplayerParticipantsList.cs index 7fd31906f7..4221821496 100644 --- a/osu.Game.Tests/Visual/RealtimeMultiplayer/TestSceneRealtimeMultiplayerParticipantsList.cs +++ b/osu.Game.Tests/Visual/RealtimeMultiplayer/TestSceneRealtimeMultiplayerParticipantsList.cs @@ -109,7 +109,7 @@ namespace osu.Game.Tests.Visual.RealtimeMultiplayer CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", }); - Client.ChangeUserState(i, (MultiplayerUserState)RNG.Next(0, (int)MultiplayerUserState.Results)); + Client.ChangeUserState(i, (MultiplayerUserState)RNG.Next(0, (int)MultiplayerUserState.Results + 1)); } }); }