From b76a87e6f886401cdc34245e41b706f4a8d6595f Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 17 Mar 2022 18:58:09 +0900 Subject: [PATCH] Split ready button visual logic into button itself --- .../Visual/Multiplayer/QueueModeTestScene.cs | 4 +- .../TestSceneAllPlayersQueueMode.cs | 8 +- .../TestSceneMultiplayerMatchSubScreen.cs | 2 +- .../TestSceneMultiplayerReadyButton.cs | 16 +- .../Match/MultiplayerReadyButton.cs | 172 ++++++++++++------ 5 files changed, 132 insertions(+), 70 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs index bafc579134..df8f63f6ed 100644 --- a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs +++ b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs @@ -95,10 +95,10 @@ namespace osu.Game.Tests.Visual.Multiplayer protected void RunGameplay() { AddUntilStep("wait for idle", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Idle); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddUntilStep("wait for ready", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddUntilStep("wait for player", () => multiplayerComponents.CurrentScreen is Player player && player.IsLoaded); AddStep("exit player", () => multiplayerComponents.MultiplayerScreen.MakeCurrent()); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs index 0785315b26..266ac60168 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs @@ -102,10 +102,10 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("selected beatmap is initial beatmap", () => Beatmap.Value.BeatmapInfo.OnlineID == InitialBeatmap.OnlineID); AddUntilStep("wait for idle", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Idle); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddUntilStep("wait for ready", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddUntilStep("wait for player", () => CurrentScreen is Player player && player.IsLoaded); AddAssert("ruleset is correct", () => ((Player)CurrentScreen).Ruleset.Value.Equals(new OsuRuleset().RulesetInfo)); @@ -119,10 +119,10 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("selected beatmap is initial beatmap", () => Beatmap.Value.BeatmapInfo.OnlineID == InitialBeatmap.OnlineID); AddUntilStep("wait for idle", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Idle); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddUntilStep("wait for ready", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddUntilStep("wait for player", () => CurrentScreen is Player player && player.IsLoaded); AddAssert("mods are correct", () => !((Player)CurrentScreen).Mods.Value.Any()); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs index 057032c413..a51d4678fe 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs @@ -145,7 +145,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for spectating user state", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddUntilStep("match started", () => MultiplayerClient.Room?.State == MultiplayerRoomState.WaitingForLoad); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs index f34f7c6c91..7f7a4c9c5f 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs @@ -92,10 +92,10 @@ namespace osu.Game.Tests.Visual.Multiplayer MultiplayerClient.TransferHost(2); }); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddUntilStep("user is idle", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Idle); } @@ -111,7 +111,7 @@ namespace osu.Game.Tests.Visual.Multiplayer MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" }); }); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready); verifyGameplayStartFlow(); @@ -126,7 +126,7 @@ namespace osu.Game.Tests.Visual.Multiplayer MultiplayerClient.TransferHost(2); }); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddStep("make user host", () => MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[0].UserID ?? 0)); verifyGameplayStartFlow(); @@ -141,12 +141,12 @@ namespace osu.Game.Tests.Visual.Multiplayer MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" }); }); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready); AddStep("transfer host", () => MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[1].UserID ?? 0)); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddUntilStep("user is idle (match not started)", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Idle); AddAssert("ready button enabled", () => button.ChildrenOfType().Single().Enabled.Value); } @@ -166,7 +166,7 @@ namespace osu.Game.Tests.Visual.Multiplayer if (!isHost) AddStep("transfer host", () => MultiplayerClient.TransferHost(2)); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddRepeatStep("change user ready state", () => { @@ -184,7 +184,7 @@ namespace osu.Game.Tests.Visual.Multiplayer private void verifyGameplayStartFlow() { AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready); - ClickButtonWhenEnabled(); + ClickButtonWhenEnabled(); AddUntilStep("user waiting for load", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.WaitingForLoad); AddStep("finish gameplay", () => diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs index 0c80f6ef5b..920e23eaa1 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs @@ -14,16 +14,12 @@ using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Online.Multiplayer; -using osu.Game.Screens.OnlinePlay.Components; using osuTK; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { public class MultiplayerReadyButton : MultiplayerRoomComposite { - [Resolved] - private OsuColour colours { get; set; } - [Resolved] private OngoingOperationTracker ongoingOperationTracker { get; set; } @@ -34,14 +30,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match private Sample sampleReadyAll; private Sample sampleUnready; - private readonly ButtonWithTrianglesExposed button; + private readonly ReadyButton readyButton; private int countReady; private ScheduledDelegate readySampleDelegate; private IBindable operationInProgress; public MultiplayerReadyButton() { - InternalChild = button = new ButtonWithTrianglesExposed + InternalChild = readyButton = new ReadyButton { RelativeSizeAxes = Axes.Both, Size = Vector2.One, @@ -123,47 +119,26 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match private void updateState() { - var localUser = Client.LocalUser; - - int newCountReady = Room?.Users.Count(u => u.State == MultiplayerUserState.Ready) ?? 0; - int newCountTotal = Room?.Users.Count(u => u.State != MultiplayerUserState.Spectating) ?? 0; - - switch (localUser?.State) + if (Room == null) { - default: - button.Text = "Ready"; - updateButtonColour(true); - break; - - case MultiplayerUserState.Spectating: - case MultiplayerUserState.Ready: - string countText = $"({newCountReady} / {newCountTotal} ready)"; - - if (Room?.Host?.Equals(localUser) == true) - { - button.Text = $"Start match {countText}"; - updateButtonColour(true); - } - else - { - button.Text = $"Waiting for host... {countText}"; - updateButtonColour(false); - } - - break; + readyButton.Enabled.Value = false; + return; } - bool enableButton = - Room?.State == MultiplayerRoomState.Open + var localUser = Client.LocalUser; + + int newCountReady = Room.Users.Count(u => u.State == MultiplayerUserState.Ready); + int newCountTotal = Room.Users.Count(u => u.State != MultiplayerUserState.Spectating); + + readyButton.Enabled.Value = + Room.State == MultiplayerRoomState.Open && CurrentPlaylistItem.Value?.ID == Room.Settings.PlaylistItemId && !Room.Playlist.Single(i => i.ID == Room.Settings.PlaylistItemId).Expired && !operationInProgress.Value; // When the local user is the host and spectating the match, the "start match" state should be enabled if any users are ready. if (localUser?.State == MultiplayerUserState.Spectating) - enableButton &= Room?.Host?.Equals(localUser) == true && newCountReady > 0; - - button.Enabled.Value = enableButton; + readyButton.Enabled.Value &= Room.Host?.Equals(localUser) == true && newCountReady > 0; if (newCountReady == countReady) return; @@ -187,25 +162,112 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match }); } - private void updateButtonColour(bool green) - { - if (green) - { - button.BackgroundColour = colours.Green; - button.Triangles.ColourDark = colours.Green; - button.Triangles.ColourLight = colours.GreenLight; - } - else - { - button.BackgroundColour = colours.YellowDark; - button.Triangles.ColourDark = colours.YellowDark; - button.Triangles.ColourLight = colours.Yellow; - } - } - - private class ButtonWithTrianglesExposed : ReadyButton + public class ReadyButton : Components.ReadyButton { public new Triangles Triangles => base.Triangles; + + [Resolved] + private MultiplayerClient multiplayerClient { get; set; } + + [Resolved] + private OsuColour colours { get; set; } + + [CanBeNull] + private MultiplayerRoom room => multiplayerClient.Room; + + protected override void LoadComplete() + { + base.LoadComplete(); + + multiplayerClient.RoomUpdated += () => Scheduler.AddOnce(onRoomUpdated); + onRoomUpdated(); + } + + private void onRoomUpdated() + { + updateButtonText(); + updateButtonColour(); + } + + private void updateButtonText() + { + if (room == null) + { + Text = "Ready"; + return; + } + + var localUser = multiplayerClient.LocalUser; + + int countReady = room.Users.Count(u => u.State == MultiplayerUserState.Ready); + int countTotal = room.Users.Count(u => u.State != MultiplayerUserState.Spectating); + + string countText = $"({countReady} / {countTotal} ready)"; + + switch (localUser?.State) + { + default: + Text = "Ready"; + break; + + case MultiplayerUserState.Spectating: + case MultiplayerUserState.Ready: + Text = room.Host?.Equals(localUser) == true + ? $"Start match {countText}" + : $"Waiting for host... {countText}"; + + break; + } + } + + private void updateButtonColour() + { + if (room == null) + { + setGreen(); + return; + } + + var localUser = multiplayerClient.LocalUser; + + switch (localUser?.State) + { + default: + setGreen(); + break; + + case MultiplayerUserState.Spectating: + case MultiplayerUserState.Ready: + if (room?.Host?.Equals(localUser) == true) + setGreen(); + else + setYellow(); + + break; + } + + void setYellow() + { + BackgroundColour = colours.YellowDark; + Triangles.ColourDark = colours.YellowDark; + Triangles.ColourLight = colours.Yellow; + } + + void setGreen() + { + BackgroundColour = colours.Green; + Triangles.ColourDark = colours.Green; + Triangles.ColourLight = colours.GreenLight; + } + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (multiplayerClient != null) + multiplayerClient.RoomUpdated -= onRoomUpdated; + } } } }