From b31fef7e001c22f5e55c01ff8c3fa4df9c090b01 Mon Sep 17 00:00:00 2001 From: 02Naitsirk <57512128+02Naitsirk@users.noreply.github.com> Date: Thu, 22 Jul 2021 13:49:47 -0400 Subject: [PATCH 001/109] Implement total SR formula that better correlates with pp --- osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index e47f82fb39..2f0b7da789 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -34,7 +34,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty double aimRating = Math.Sqrt(skills[0].DifficultyValue()) * difficulty_multiplier; double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier; - double starRating = aimRating + speedRating + Math.Abs(aimRating - speedRating) / 2; + + double baseAimPerformance = Math.Pow(5 * Math.Max(1, aimRating) - 4, 3) / 100000; + double baseSpeedPerformance = Math.Pow(5 * Math.Max(1, speedRating) - 4, 3) / 100000; + double basePerformance = Math.Pow(Math.Pow(baseAimPerformance, 1.1) + Math.Pow(baseSpeedPerformance, 1.1), 1 / 1.1); + double starRating = basePerformance > 0.00001 ? 0.027 * (Math.Cbrt(100000 / Math.Pow(2, 1 / 1.1) * basePerformance) + 4) : 0; HitWindows hitWindows = new OsuHitWindows(); hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); From 5b5cf30cbd5b862496a26453b6edb5ee69281d1c Mon Sep 17 00:00:00 2001 From: 02Naitsirk <57512128+02Naitsirk@users.noreply.github.com> Date: Sat, 31 Jul 2021 12:23:03 -0400 Subject: [PATCH 002/109] Fix incorrect performance formula MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 2f0b7da789..299d8b8970 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -35,8 +35,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty double aimRating = Math.Sqrt(skills[0].DifficultyValue()) * difficulty_multiplier; double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier; - double baseAimPerformance = Math.Pow(5 * Math.Max(1, aimRating) - 4, 3) / 100000; - double baseSpeedPerformance = Math.Pow(5 * Math.Max(1, speedRating) - 4, 3) / 100000; + double baseAimPerformance = Math.Pow(5 * Math.Max(1, aimRating / 0.0675) - 4, 3) / 100000; + double baseSpeedPerformance = Math.Pow(5 * Math.Max(1, speedRating / 0.0675) - 4, 3) / 100000; double basePerformance = Math.Pow(Math.Pow(baseAimPerformance, 1.1) + Math.Pow(baseSpeedPerformance, 1.1), 1 / 1.1); double starRating = basePerformance > 0.00001 ? 0.027 * (Math.Cbrt(100000 / Math.Pow(2, 1 / 1.1) * basePerformance) + 4) : 0; From ea2ef55a8bcc2867ae414e84c67857263cac8be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 1 Aug 2021 15:27:05 +0200 Subject: [PATCH 003/109] Remove unnecessary whitespace --- osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 299d8b8970..b75bf81071 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty double aimRating = Math.Sqrt(skills[0].DifficultyValue()) * difficulty_multiplier; double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier; - + double baseAimPerformance = Math.Pow(5 * Math.Max(1, aimRating / 0.0675) - 4, 3) / 100000; double baseSpeedPerformance = Math.Pow(5 * Math.Max(1, speedRating / 0.0675) - 4, 3) / 100000; double basePerformance = Math.Pow(Math.Pow(baseAimPerformance, 1.1) + Math.Pow(baseSpeedPerformance, 1.1), 1 / 1.1); From c371e67d705df820ded3c66344a27cf3d1b07b20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 1 Aug 2021 15:32:10 +0200 Subject: [PATCH 004/109] Update diffcalc test to match ground-truth formula --- .../OsuDifficultyCalculatorTest.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs index 8d8387378e..32fba0b70c 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs @@ -15,13 +15,13 @@ namespace osu.Game.Rulesets.Osu.Tests { protected override string ResourceAssembly => "osu.Game.Rulesets.Osu"; - [TestCase(6.7568168283591499d, "diffcalc-test")] - [TestCase(1.0348244046058293d, "zero-length-sliders")] + [TestCase(6.4164199087433484d, "diffcalc-test")] + [TestCase(1.0028132594779837d, "zero-length-sliders")] public void Test(double expected, string name) => base.Test(expected, name); - [TestCase(8.4783236764532557d, "diffcalc-test")] - [TestCase(1.2708532136987165d, "zero-length-sliders")] + [TestCase(8.0749334911818469d, "diffcalc-test")] + [TestCase(1.2251606765323657d, "zero-length-sliders")] public void TestClockRateAdjusted(double expected, string name) => Test(expected, name, new OsuModDoubleTime()); From db1f43f6eb887c2d4c38ad796f00dd075821fb25 Mon Sep 17 00:00:00 2001 From: 02Naitsirk <57512128+02Naitsirk@users.noreply.github.com> Date: Tue, 3 Aug 2021 18:57:33 -0400 Subject: [PATCH 005/109] Multiply star rating by a constant --- osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index b75bf81071..da879cb02e 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty double baseAimPerformance = Math.Pow(5 * Math.Max(1, aimRating / 0.0675) - 4, 3) / 100000; double baseSpeedPerformance = Math.Pow(5 * Math.Max(1, speedRating / 0.0675) - 4, 3) / 100000; double basePerformance = Math.Pow(Math.Pow(baseAimPerformance, 1.1) + Math.Pow(baseSpeedPerformance, 1.1), 1 / 1.1); - double starRating = basePerformance > 0.00001 ? 0.027 * (Math.Cbrt(100000 / Math.Pow(2, 1 / 1.1) * basePerformance) + 4) : 0; + double starRating = basePerformance > 0.00001 ? Math.Cbrt(1.12) * 0.027 * (Math.Cbrt(100000 / Math.Pow(2, 1 / 1.1) * basePerformance) + 4) : 0; HitWindows hitWindows = new OsuHitWindows(); hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); From 0d2ab550dd8c1285d94ae8991e040f06ea9a970a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Aug 2021 13:04:32 +0900 Subject: [PATCH 006/109] Update SR values in tests --- .../OsuDifficultyCalculatorTest.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs index 32fba0b70c..19881b5c33 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs @@ -15,13 +15,13 @@ namespace osu.Game.Rulesets.Osu.Tests { protected override string ResourceAssembly => "osu.Game.Rulesets.Osu"; - [TestCase(6.4164199087433484d, "diffcalc-test")] - [TestCase(1.0028132594779837d, "zero-length-sliders")] + [TestCase(6.6634445062299665d, "diffcalc-test")] + [TestCase(1.0414203870195022d, "zero-length-sliders")] public void Test(double expected, string name) => base.Test(expected, name); - [TestCase(8.0749334911818469d, "diffcalc-test")] - [TestCase(1.2251606765323657d, "zero-length-sliders")] + [TestCase(8.3858089051603368d, "diffcalc-test")] + [TestCase(1.2723279173428435d, "zero-length-sliders")] public void TestClockRateAdjusted(double expected, string name) => Test(expected, name, new OsuModDoubleTime()); From b8a1ebb786c6bd8a9581d62f489ccd598563e513 Mon Sep 17 00:00:00 2001 From: sh0ckR6 Date: Tue, 7 Sep 2021 16:54:21 -0400 Subject: [PATCH 007/109] Hide Popover after failed password attempt Instead of throwing an error, just close the popover and let the user continue --- osu.Game/Screens/OnlinePlay/Components/RoomManager.cs | 3 ++- .../Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 11 +++++++---- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 6 ++++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs index 3b6c1c8be0..4b3617c74a 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs @@ -87,7 +87,8 @@ namespace osu.Game.Screens.OnlinePlay.Components currentJoinRoomRequest.Failure += exception => { - if (!(exception is OperationCanceledException)) + // provide error output if the operation wasn't canceled and the error doesn't stem from an invalid password + if (!(exception is OperationCanceledException) && !((APIException)exception).Message.Equals("Invalid room password", StringComparison.Ordinal)) Logger.Log($"Failed to join room: {exception}", level: LogLevel.Important); onError?.Invoke(exception.ToString()); }; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 6dc3cd18c5..c8b647fc9a 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -178,7 +178,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { private readonly Room room; - public Action JoinRequested; + public Action, Action> JoinRequested; public PasswordEntryPopover(Room room) { @@ -186,6 +186,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge } private OsuPasswordTextBox passwordTextbox; + private TriangleButton joinButton; [BackgroundDependencyLoader] private void load() @@ -201,15 +202,17 @@ namespace osu.Game.Screens.OnlinePlay.Lounge passwordTextbox = new OsuPasswordTextBox { Width = 200, + PlaceholderText = "password", }, - new TriangleButton + joinButton = new TriangleButton { Width = 80, Text = "Join Room", - Action = () => JoinRequested?.Invoke(room, passwordTextbox.Text) } } }; + + joinButton.Action = () => JoinRequested?.Invoke(room, passwordTextbox.Text, null, _ => this.HidePopover()); } protected override void LoadComplete() @@ -217,7 +220,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge base.LoadComplete(); Schedule(() => GetContainingInputManager().ChangeFocus(passwordTextbox)); - passwordTextbox.OnCommit += (_, __) => JoinRequested?.Invoke(room, passwordTextbox.Text); + passwordTextbox.OnCommit += (_, __) => JoinRequested?.Invoke(room, passwordTextbox.Text, null, _ => this.HidePopover()); } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index cca1394b6d..08bdd0487a 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -290,7 +290,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge popoverContainer.HidePopover(); } - public void Join(Room room, string password) => Schedule(() => + public void Join(Room room, string password, Action onSuccess = null, Action onFailure = null) => Schedule(() => { if (joiningRoomOperation != null) return; @@ -302,10 +302,12 @@ namespace osu.Game.Screens.OnlinePlay.Lounge Open(room); joiningRoomOperation?.Dispose(); joiningRoomOperation = null; - }, _ => + onSuccess?.Invoke(room); + }, error => { joiningRoomOperation?.Dispose(); joiningRoomOperation = null; + onFailure?.Invoke(error); }); }); From b1f91596a7e7a07082056686ba49a8acb81244b2 Mon Sep 17 00:00:00 2001 From: sh0ckR6 Date: Tue, 7 Sep 2021 20:05:24 -0400 Subject: [PATCH 008/109] Give user feedback on password attempt fail Shake the popover Set the input box's color to red and set the placeholder text to "incorrect password" --- .../Graphics/Containers/ShakeContainer.cs | 7 +++ .../OnlinePlay/Lounge/DrawableLoungeRoom.cs | 47 +++++++++++++------ 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index dca9df1e98..ffa8ef585e 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -26,6 +27,11 @@ namespace osu.Game.Graphics.Containers /// public float ShakeMagnitude = 8; + /// + /// Fired when finishes + /// + public event Action OnShakeFinish; + /// /// Shake the contents of this container. /// @@ -50,6 +56,7 @@ namespace osu.Game.Graphics.Containers } sequence.MoveToX(0, ShakeDuration / 2, Easing.InSine); + sequence.Finally(_ => OnShakeFinish?.Invoke()); } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index c8b647fc9a..bedee39a26 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -15,6 +15,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Input.Bindings; @@ -187,32 +188,50 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private OsuPasswordTextBox passwordTextbox; private TriangleButton joinButton; + private ShakeContainer shakeContainer; [BackgroundDependencyLoader] private void load() { - Child = new FillFlowContainer + shakeContainer = new ShakeContainer { Margin = new MarginPadding(10), - Spacing = new Vector2(5), AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new Drawable[] + Child = new FillFlowContainer { - passwordTextbox = new OsuPasswordTextBox + Margin = new MarginPadding(10), + Spacing = new Vector2(5), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] { - Width = 200, - PlaceholderText = "password", - }, - joinButton = new TriangleButton - { - Width = 80, - Text = "Join Room", + passwordTextbox = new OsuPasswordTextBox + { + Width = 200, + PlaceholderText = "password", + }, + joinButton = new TriangleButton + { + Width = 80, + Text = "Join Room", + } } } }; + Child = shakeContainer; - joinButton.Action = () => JoinRequested?.Invoke(room, passwordTextbox.Text, null, _ => this.HidePopover()); + joinButton.Action = () => JoinRequested?.Invoke(room, passwordTextbox.Text, null, joinFailed); + } + + private void joinFailed(string error) + { + passwordTextbox.Text = string.Empty; + passwordTextbox.PlaceholderText = "incorrect password"; + passwordTextbox.Colour = Color4.Red; + + shakeContainer.OnShakeFinish += () => passwordTextbox.Colour = Color4.White; + + shakeContainer.Shake(); } protected override void LoadComplete() @@ -220,7 +239,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge base.LoadComplete(); Schedule(() => GetContainingInputManager().ChangeFocus(passwordTextbox)); - passwordTextbox.OnCommit += (_, __) => JoinRequested?.Invoke(room, passwordTextbox.Text, null, _ => this.HidePopover()); + passwordTextbox.OnCommit += (_, __) => JoinRequested?.Invoke(room, passwordTextbox.Text, null, joinFailed); } } } From b8a6925175cc7b40036d10d1e3d74b12feaf331b Mon Sep 17 00:00:00 2001 From: sh0ckR6 Date: Sat, 11 Sep 2021 17:41:07 -0400 Subject: [PATCH 009/109] Use already-resolved LoungeSubScreen instead of nested delegates --- osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index bedee39a26..972c7aed47 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -123,7 +122,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge } } - public Popover GetPopover() => new PasswordEntryPopover(Room) { JoinRequested = lounge.Join }; + public Popover GetPopover() => new PasswordEntryPopover(Room) { Lounge = lounge }; public MenuItem[] ContextMenuItems => new MenuItem[] { @@ -179,7 +178,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { private readonly Room room; - public Action, Action> JoinRequested; + public LoungeSubScreen Lounge; public PasswordEntryPopover(Room room) { @@ -220,7 +219,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge }; Child = shakeContainer; - joinButton.Action = () => JoinRequested?.Invoke(room, passwordTextbox.Text, null, joinFailed); + joinButton.Action = () => Lounge?.Join(room, passwordTextbox.Text, null, joinFailed); } private void joinFailed(string error) @@ -239,7 +238,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge base.LoadComplete(); Schedule(() => GetContainingInputManager().ChangeFocus(passwordTextbox)); - passwordTextbox.OnCommit += (_, __) => JoinRequested?.Invoke(room, passwordTextbox.Text, null, joinFailed); + passwordTextbox.OnCommit += (_, __) => Lounge?.Join(room, passwordTextbox.Text, null, joinFailed); } } } From 6cdc8424527c3c9ccb697f9c9031207d6a3a57bb Mon Sep 17 00:00:00 2001 From: sh0ckR6 Date: Sat, 11 Sep 2021 17:42:49 -0400 Subject: [PATCH 010/109] Remove placeholder text response Weird UX, doesn't feel right compared to the rest of lazer --- osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 972c7aed47..8cf34cd9f3 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -225,8 +225,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private void joinFailed(string error) { passwordTextbox.Text = string.Empty; - passwordTextbox.PlaceholderText = "incorrect password"; - passwordTextbox.Colour = Color4.Red; shakeContainer.OnShakeFinish += () => passwordTextbox.Colour = Color4.White; From e018071be47e31457c6969d0cbac618e37932b3a Mon Sep 17 00:00:00 2001 From: sh0ckR6 Date: Sat, 11 Sep 2021 19:50:41 -0400 Subject: [PATCH 011/109] Remove OnShakeFinish event --- osu.Game/Graphics/Containers/ShakeContainer.cs | 7 ------- osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 2 -- 2 files changed, 9 deletions(-) diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index ffa8ef585e..dca9df1e98 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -27,11 +26,6 @@ namespace osu.Game.Graphics.Containers /// public float ShakeMagnitude = 8; - /// - /// Fired when finishes - /// - public event Action OnShakeFinish; - /// /// Shake the contents of this container. /// @@ -56,7 +50,6 @@ namespace osu.Game.Graphics.Containers } sequence.MoveToX(0, ShakeDuration / 2, Easing.InSine); - sequence.Finally(_ => OnShakeFinish?.Invoke()); } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 8cf34cd9f3..db1566999e 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -226,8 +226,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { passwordTextbox.Text = string.Empty; - shakeContainer.OnShakeFinish += () => passwordTextbox.Colour = Color4.White; - shakeContainer.Shake(); } From 447001931cf67b3896c3934d1c23209b2be3ddc7 Mon Sep 17 00:00:00 2001 From: sh0ckR6 Date: Sun, 12 Sep 2021 14:36:11 -0400 Subject: [PATCH 012/109] Resolve LoungeSubScreen from PasswordEntryPopover This is preferred over passing down the already-resolved LoungeSubScreen --- osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index db1566999e..bec0ea419c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -122,7 +122,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge } } - public Popover GetPopover() => new PasswordEntryPopover(Room) { Lounge = lounge }; + public Popover GetPopover() => new PasswordEntryPopover(Room); public MenuItem[] ContextMenuItems => new MenuItem[] { @@ -178,7 +178,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { private readonly Room room; - public LoungeSubScreen Lounge; + [Resolved(canBeNull: true)] + private LoungeSubScreen lounge { get; set; } public PasswordEntryPopover(Room room) { @@ -219,7 +220,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge }; Child = shakeContainer; - joinButton.Action = () => Lounge?.Join(room, passwordTextbox.Text, null, joinFailed); + joinButton.Action = () => lounge?.Join(room, passwordTextbox.Text, null, joinFailed); } private void joinFailed(string error) @@ -234,7 +235,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge base.LoadComplete(); Schedule(() => GetContainingInputManager().ChangeFocus(passwordTextbox)); - passwordTextbox.OnCommit += (_, __) => Lounge?.Join(room, passwordTextbox.Text, null, joinFailed); + passwordTextbox.OnCommit += (_, __) => lounge?.Join(room, passwordTextbox.Text, null, joinFailed); } } } From aa71e3f3d4e6206798a563c3e4af1291e6626323 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Sep 2021 18:32:48 +0900 Subject: [PATCH 013/109] Update nested game tests in line with framework changes --- .../TestSceneOsuGame.cs | 6 ++---- .../osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs | 6 ++---- .../TestSceneOsuGame.cs | 6 ++---- .../osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs | 6 ++---- osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs | 6 ++---- osu.Game/Tests/Visual/OsuGameTestScene.cs | 5 +---- 6 files changed, 11 insertions(+), 24 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs index 9c512a01ea..536fdfc6df 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/TestSceneOsuGame.cs @@ -15,9 +15,6 @@ namespace osu.Game.Rulesets.EmptyFreeform.Tests [BackgroundDependencyLoader] private void load(GameHost host, OsuGameBase gameBase) { - OsuGame game = new OsuGame(); - game.SetHost(host); - Children = new Drawable[] { new Box @@ -25,8 +22,9 @@ namespace osu.Game.Rulesets.EmptyFreeform.Tests RelativeSizeAxes = Axes.Both, Colour = Color4.Black, }, - game }; + + AddGame(new OsuGame()); } } } diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs index 270d906b01..3cdf44e6f1 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs @@ -15,9 +15,6 @@ namespace osu.Game.Rulesets.Pippidon.Tests [BackgroundDependencyLoader] private void load(GameHost host, OsuGameBase gameBase) { - OsuGame game = new OsuGame(); - game.SetHost(host); - Children = new Drawable[] { new Box @@ -25,8 +22,9 @@ namespace osu.Game.Rulesets.Pippidon.Tests RelativeSizeAxes = Axes.Both, Colour = Color4.Black, }, - game }; + + AddGame(new OsuGame()); } } } diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs index aed6abb6bf..4d3f5086d9 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/TestSceneOsuGame.cs @@ -15,9 +15,6 @@ namespace osu.Game.Rulesets.EmptyScrolling.Tests [BackgroundDependencyLoader] private void load(GameHost host, OsuGameBase gameBase) { - OsuGame game = new OsuGame(); - game.SetHost(host); - Children = new Drawable[] { new Box @@ -25,8 +22,9 @@ namespace osu.Game.Rulesets.EmptyScrolling.Tests RelativeSizeAxes = Axes.Both, Colour = Color4.Black, }, - game }; + + AddGame(new OsuGame()); } } } diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs index 270d906b01..3cdf44e6f1 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/TestSceneOsuGame.cs @@ -15,9 +15,6 @@ namespace osu.Game.Rulesets.Pippidon.Tests [BackgroundDependencyLoader] private void load(GameHost host, OsuGameBase gameBase) { - OsuGame game = new OsuGame(); - game.SetHost(host); - Children = new Drawable[] { new Box @@ -25,8 +22,9 @@ namespace osu.Game.Rulesets.Pippidon.Tests RelativeSizeAxes = Axes.Both, Colour = Color4.Black, }, - game }; + + AddGame(new OsuGame()); } } } diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs index b8232837b5..e38b1353d9 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs @@ -97,9 +97,6 @@ namespace osu.Game.Tests.Visual.Navigation { AddStep("create game", () => { - game = new OsuGame(); - game.SetHost(host); - Children = new Drawable[] { new Box @@ -107,8 +104,9 @@ namespace osu.Game.Tests.Visual.Navigation RelativeSizeAxes = Axes.Both, Colour = Color4.Black, }, - game }; + + AddGame(game = new OsuGame()); }); AddUntilStep("wait for load", () => game.IsLoaded); diff --git a/osu.Game/Tests/Visual/OsuGameTestScene.cs b/osu.Game/Tests/Visual/OsuGameTestScene.cs index f38aaa9358..b56c8a15af 100644 --- a/osu.Game/Tests/Visual/OsuGameTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGameTestScene.cs @@ -81,10 +81,7 @@ namespace osu.Game.Tests.Visual protected void CreateGame() { - Game = new TestOsuGame(LocalStorage, API); - Game.SetHost(host); - - Add(Game); + AddGame(Game = new TestOsuGame(LocalStorage, API)); } protected void PushAndConfirm(Func newScreen) From 24ae530a8087d35119a9b4533571cf4e6dbf9112 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Sep 2021 18:32:58 +0900 Subject: [PATCH 014/109] Add test coverage of double dispose of `OsuGame` --- osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index cc64d37116..0d1719c1d2 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -400,6 +400,7 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("Hold escape", () => InputManager.PressKey(Key.Escape)); AddUntilStep("Wait for intro", () => Game.ScreenStack.CurrentScreen is IntroTriangles); AddUntilStep("Wait for game exit", () => Game.ScreenStack.CurrentScreen == null); + AddStep("test dispose doesn't crash", () => Game.Dispose()); } private void pushEscape() => From d999c29d3ac873f6991cf19030d9e74dc8bc0b49 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Sep 2021 19:38:43 +0900 Subject: [PATCH 015/109] Remove unused `GameHost` DI in `OsuGameTestScene` --- osu.Game/Tests/Visual/OsuGameTestScene.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Tests/Visual/OsuGameTestScene.cs b/osu.Game/Tests/Visual/OsuGameTestScene.cs index b56c8a15af..881c4bab02 100644 --- a/osu.Game/Tests/Visual/OsuGameTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGameTestScene.cs @@ -30,8 +30,6 @@ namespace osu.Game.Tests.Visual /// public abstract class OsuGameTestScene : OsuManualInputManagerTestScene { - private GameHost host; - protected TestOsuGame Game; protected override bool UseFreshStoragePerRun => true; @@ -39,10 +37,8 @@ namespace osu.Game.Tests.Visual protected override bool CreateNestedActionContainer => false; [BackgroundDependencyLoader] - private void load(GameHost host) + private void load() { - this.host = host; - Child = new Box { RelativeSizeAxes = Axes.Both, @@ -55,7 +51,7 @@ namespace osu.Game.Tests.Visual { AddStep("Create new game instance", () => { - if (Game != null) + if (Game?.Parent != null) { Remove(Game); Game.Dispose(); From e8d4e2e6da97c2a7b7dc41f78705bc6ad8a72894 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Sep 2021 19:38:53 +0900 Subject: [PATCH 016/109] Fix tests being blocked by notification overlay popup --- .../Navigation/TestSceneScreenNavigation.cs | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 0d1719c1d2..2c416ee758 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -77,7 +77,13 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("press enter", () => InputManager.Key(Key.Enter)); - AddUntilStep("wait for player", () => (player = Game.ScreenStack.CurrentScreen as Player) != null); + AddUntilStep("wait for player", () => + { + // dismiss any notifications that may appear (ie. muted notification). + clickMouseInCentre(); + return (player = Game.ScreenStack.CurrentScreen as Player) != null; + }); + AddAssert("retry count is 0", () => player.RestartCount == 0); AddStep("attempt to retry", () => player.ChildrenOfType().First().Action()); @@ -104,7 +110,14 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("set mods", () => Game.SelectedMods.Value = new Mod[] { new OsuModNoFail(), new OsuModDoubleTime { SpeedChange = { Value = 2 } } }); AddStep("press enter", () => InputManager.Key(Key.Enter)); - AddUntilStep("wait for player", () => (player = Game.ScreenStack.CurrentScreen as Player) != null); + + AddUntilStep("wait for player", () => + { + // dismiss any notifications that may appear (ie. muted notification). + clickMouseInCentre(); + return (player = Game.ScreenStack.CurrentScreen as Player) != null; + }); + AddUntilStep("wait for track playing", () => beatmap().Track.IsRunning); AddStep("seek to near end", () => player.ChildrenOfType().First().Seek(beatmap().Beatmap.HitObjects[^1].StartTime - 1000)); AddUntilStep("wait for pass", () => (results = Game.ScreenStack.CurrentScreen as ResultsScreen) != null && results.IsLoaded); @@ -131,7 +144,13 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("press enter", () => InputManager.Key(Key.Enter)); - AddUntilStep("wait for player", () => (player = Game.ScreenStack.CurrentScreen as Player) != null); + AddUntilStep("wait for player", () => + { + // dismiss any notifications that may appear (ie. muted notification). + clickMouseInCentre(); + return (player = Game.ScreenStack.CurrentScreen as Player) != null; + }); + AddUntilStep("wait for fail", () => player.HasFailed); AddUntilStep("wait for track stop", () => !Game.MusicController.IsPlaying); @@ -403,6 +422,12 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("test dispose doesn't crash", () => Game.Dispose()); } + private void clickMouseInCentre() + { + InputManager.MoveMouseTo(Game.ScreenSpaceDrawQuad.Centre); + InputManager.Click(MouseButton.Left); + } + private void pushEscape() => AddStep("Press escape", () => InputManager.Key(Key.Escape)); From 80e54d51f2bfe0e367bdd7f65f4a793185bafcd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 11 Sep 2021 16:28:46 +0200 Subject: [PATCH 017/109] Add failing test for preserving editor clock time --- .../Editing/TestSceneDifficultySwitching.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs b/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs index a439555fde..0954bf1b49 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs @@ -55,6 +55,22 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("stack empty", () => Stack.CurrentScreen == null); } + [Test] + public void TestClockPositionPreservedBetweenSwitches() + { + BeatmapInfo targetDifficulty = null; + AddStep("seek editor to 00:05:00", () => EditorClock.Seek(5000)); + + AddStep("set target difficulty", () => targetDifficulty = importedBeatmapSet.Beatmaps.Last(beatmap => !beatmap.Equals(Beatmap.Value.BeatmapInfo))); + switchToDifficulty(() => targetDifficulty); + confirmEditingBeatmap(() => targetDifficulty); + AddAssert("editor clock at 00:05:00", () => EditorClock.CurrentTime == 5000); + + AddStep("exit editor", () => Stack.Exit()); + // ensure editor loader didn't resume. + AddAssert("stack empty", () => Stack.CurrentScreen == null); + } + [Test] public void TestPreventSwitchDueToUnsavedChanges() { @@ -118,7 +134,7 @@ namespace osu.Game.Tests.Visual.Editing private void confirmEditingBeatmap(Func targetDifficulty) { AddUntilStep("current beatmap is correct", () => Beatmap.Value.BeatmapInfo.Equals(targetDifficulty.Invoke())); - AddUntilStep("current screen is editor", () => Stack.CurrentScreen is Editor); + AddUntilStep("current screen is editor", () => Stack.CurrentScreen == Editor && Editor?.IsLoaded == true); } } } From 3fc72271f103918a622d509d86a0fbad01172685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 11 Sep 2021 18:36:57 +0200 Subject: [PATCH 018/109] Restore editor clock time after difficulty switch --- osu.Game/Screens/Edit/Editor.cs | 13 ++++++++++++- osu.Game/Screens/Edit/EditorLoader.cs | 12 ++++++++++-- osu.Game/Screens/Edit/EditorState.cs | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Screens/Edit/EditorState.cs diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 28ae7e620e..502ac7a70f 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -476,6 +476,8 @@ namespace osu.Game.Screens.Edit }); resetTrack(true); + if (loader?.State != null) + restoreState(loader.State); } public override bool OnExiting(IScreen next) @@ -740,7 +742,16 @@ namespace osu.Game.Screens.Edit return new DifficultyMenuItem(beatmapInfo, isCurrentDifficulty, SwitchToDifficulty); } - protected void SwitchToDifficulty(BeatmapInfo beatmapInfo) => loader?.ScheduleDifficultySwitch(beatmapInfo); + protected void SwitchToDifficulty(BeatmapInfo nextBeatmap) => loader?.ScheduleDifficultySwitch(nextBeatmap, new EditorState + { + Time = clock.CurrentTimeAccurate + }); + + private void restoreState([NotNull] EditorState state) + { + if (state.Time != null) + clock.Seek(state.Time.Value); + } private void cancelExit() => loader?.CancelPendingDifficultySwitch(); diff --git a/osu.Game/Screens/Edit/EditorLoader.cs b/osu.Game/Screens/Edit/EditorLoader.cs index 6bbfa92c3b..b6e57b0491 100644 --- a/osu.Game/Screens/Edit/EditorLoader.cs +++ b/osu.Game/Screens/Edit/EditorLoader.cs @@ -20,6 +20,13 @@ namespace osu.Game.Screens.Edit /// public class EditorLoader : ScreenWithBeatmapBackground { + /// + /// The stored state from the last editor opened. + /// This will be read by the next editor instance to be opened to restore any relevant previous state. + /// + [CanBeNull] + public EditorState State; + public override float BackgroundParallaxAmount => 0.1f; public override bool AllowBackButton => false; @@ -61,7 +68,7 @@ namespace osu.Game.Screens.Edit } } - public void ScheduleDifficultySwitch(BeatmapInfo beatmapInfo) + public void ScheduleDifficultySwitch(BeatmapInfo nextBeatmap, EditorState editorState) { scheduledDifficultySwitch?.Cancel(); ValidForResume = true; @@ -70,7 +77,8 @@ namespace osu.Game.Screens.Edit scheduledDifficultySwitch = Schedule(() => { - Beatmap.Value = beatmapManager.GetWorkingBeatmap(beatmapInfo); + Beatmap.Value = beatmapManager.GetWorkingBeatmap(nextBeatmap); + State = editorState; // This screen is a weird exception to the rule that nothing after song select changes the global beatmap. // Because of this, we need to update the background stack's beatmap to match. diff --git a/osu.Game/Screens/Edit/EditorState.cs b/osu.Game/Screens/Edit/EditorState.cs new file mode 100644 index 0000000000..3aa92f35bc --- /dev/null +++ b/osu.Game/Screens/Edit/EditorState.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable enable + +namespace osu.Game.Screens.Edit +{ + /// + /// Structure used to transport data between instances on difficulty change. + /// It's intended to be received by from one editor instance and passed down to the next one. + /// + public class EditorState + { + /// + /// The current clock time when a difficulty switch was requested. + /// + public double? Time { get; set; } + } +} From 79d0f4835e0fbc6fd6fd28be2901c48c3ae7a1a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 11 Sep 2021 17:26:31 +0200 Subject: [PATCH 019/109] Add failing tests for preserving clipboard content --- .../Editing/TestSceneDifficultySwitching.cs | 34 +++++++++++++++++++ .../Screens/Edit/Compose/ComposeScreen.cs | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs b/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs index 0954bf1b49..1b548dc1ba 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs @@ -71,6 +71,40 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("stack empty", () => Stack.CurrentScreen == null); } + [Test] + public void TestClipboardPreservedAfterSwitch([Values] bool sameRuleset) + { + BeatmapInfo targetDifficulty = null; + + AddStep("select first object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.First())); + AddStep("copy object", () => Editor.Copy()); + + AddStep("set target difficulty", () => + { + targetDifficulty = sameRuleset + ? importedBeatmapSet.Beatmaps.Last(beatmap => !beatmap.Equals(Beatmap.Value.BeatmapInfo) && beatmap.RulesetID == Beatmap.Value.BeatmapInfo.RulesetID) + : importedBeatmapSet.Beatmaps.Last(beatmap => !beatmap.Equals(Beatmap.Value.BeatmapInfo) && beatmap.RulesetID != Beatmap.Value.BeatmapInfo.RulesetID); + }); + switchToDifficulty(() => targetDifficulty); + confirmEditingBeatmap(() => targetDifficulty); + + AddAssert("no objects selected", () => !EditorBeatmap.SelectedHitObjects.Any()); + AddStep("paste object", () => Editor.Paste()); + + if (sameRuleset) + AddAssert("object was pasted", () => EditorBeatmap.SelectedHitObjects.Any()); + else + AddAssert("object was not pasted", () => !EditorBeatmap.SelectedHitObjects.Any()); + + AddStep("exit editor", () => Stack.Exit()); + + AddUntilStep("prompt for save dialog shown", () => DialogOverlay.CurrentDialog is PromptForSaveDialog); + AddStep("discard changes", () => ((PromptForSaveDialog)DialogOverlay.CurrentDialog).PerformOkAction()); + + // ensure editor loader didn't resume. + AddAssert("stack empty", () => Stack.CurrentScreen == null); + } + [Test] public void TestPreventSwitchDueToUnsavedChanges() { diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 62b3d33069..e324f1edeb 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -80,7 +80,7 @@ namespace osu.Game.Screens.Edit.Compose public bool OnPressed(PlatformAction action) { if (action == PlatformAction.Copy) - host.GetClipboard().SetText(formatSelectionAsString()); + host.GetClipboard()?.SetText(formatSelectionAsString()); return false; } From 35ee889e5b1b567757632b5bb9dd0b350b5820a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 11 Sep 2021 17:55:11 +0200 Subject: [PATCH 020/109] Restore clipboard content after difficulty switch --- osu.Game/Screens/Edit/Editor.cs | 5 ++++- osu.Game/Screens/Edit/EditorState.cs | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 502ac7a70f..eba75f4408 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -744,13 +744,16 @@ namespace osu.Game.Screens.Edit protected void SwitchToDifficulty(BeatmapInfo nextBeatmap) => loader?.ScheduleDifficultySwitch(nextBeatmap, new EditorState { - Time = clock.CurrentTimeAccurate + Time = clock.CurrentTimeAccurate, + ClipboardContent = editorBeatmap.BeatmapInfo.RulesetID == nextBeatmap.RulesetID ? clipboard.Value : null }); private void restoreState([NotNull] EditorState state) { if (state.Time != null) clock.Seek(state.Time.Value); + + clipboard.Value = state.ClipboardContent ?? clipboard.Value; } private void cancelExit() => loader?.CancelPendingDifficultySwitch(); diff --git a/osu.Game/Screens/Edit/EditorState.cs b/osu.Game/Screens/Edit/EditorState.cs index 3aa92f35bc..09cc1184d2 100644 --- a/osu.Game/Screens/Edit/EditorState.cs +++ b/osu.Game/Screens/Edit/EditorState.cs @@ -15,5 +15,10 @@ namespace osu.Game.Screens.Edit /// The current clock time when a difficulty switch was requested. /// public double? Time { get; set; } + + /// + /// The current editor clipboard content at the time when a difficulty switch was requested. + /// + public string? ClipboardContent { get; set; } } } From cbb9ff1c492b51f450f8841277597ff38de61667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 12 Sep 2021 13:44:25 +0200 Subject: [PATCH 021/109] Only run prompt-for-save test logic when relevant --- .../Visual/Editing/TestSceneDifficultySwitching.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs b/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs index 1b548dc1ba..c81a1abfbc 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs @@ -98,8 +98,11 @@ namespace osu.Game.Tests.Visual.Editing AddStep("exit editor", () => Stack.Exit()); - AddUntilStep("prompt for save dialog shown", () => DialogOverlay.CurrentDialog is PromptForSaveDialog); - AddStep("discard changes", () => ((PromptForSaveDialog)DialogOverlay.CurrentDialog).PerformOkAction()); + if (sameRuleset) + { + AddUntilStep("prompt for save dialog shown", () => DialogOverlay.CurrentDialog is PromptForSaveDialog); + AddStep("discard changes", () => ((PromptForSaveDialog)DialogOverlay.CurrentDialog).PerformOkAction()); + } // ensure editor loader didn't resume. AddAssert("stack empty", () => Stack.CurrentScreen == null); From 3df4cbca2cfd09d81226b530f96fba6a5588e2a9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Sep 2021 13:45:10 +0900 Subject: [PATCH 022/109] Reduce precision of difficulty calculator tests --- osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs b/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs index 76f229a799..fdb3e1d465 100644 --- a/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs +++ b/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs @@ -23,7 +23,10 @@ namespace osu.Game.Tests.Beatmaps protected abstract string ResourceAssembly { get; } protected void Test(double expected, string name, params Mod[] mods) - => Assert.AreEqual(expected, CreateDifficultyCalculator(getBeatmap(name)).Calculate(mods).StarRating); + { + // Platform-dependent math functions (Pow, Cbrt, Exp, etc) may result in minute differences. + Assert.That(CreateDifficultyCalculator(getBeatmap(name)).Calculate(mods).StarRating, Is.EqualTo(expected).Within(0.00001)); + } private WorkingBeatmap getBeatmap(string name) { From eaac2bad3d31dce24d3e6a6fad03a4ff8b849e85 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Sep 2021 13:49:02 +0900 Subject: [PATCH 023/109] Fix incorrect child margin specifications --- osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index bec0ea419c..2fc039ad79 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -193,13 +193,12 @@ namespace osu.Game.Screens.OnlinePlay.Lounge [BackgroundDependencyLoader] private void load() { - shakeContainer = new ShakeContainer + Child = shakeContainer = new ShakeContainer { Margin = new MarginPadding(10), AutoSizeAxes = Axes.Both, Child = new FillFlowContainer { - Margin = new MarginPadding(10), Spacing = new Vector2(5), AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, @@ -218,7 +217,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge } } }; - Child = shakeContainer; joinButton.Action = () => lounge?.Join(room, passwordTextbox.Text, null, joinFailed); } From 6851e0000de64ca7bd41339eedcda4f6d3c7c99f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Sep 2021 13:51:18 +0900 Subject: [PATCH 024/109] Add test coverage --- .../TestSceneMultiplayerLoungeSubScreen.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs index 99f6ab1ae1..01bf742177 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs @@ -3,6 +3,7 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using osu.Framework.Screens; using osu.Framework.Testing; @@ -64,7 +65,23 @@ namespace osu.Game.Tests.Visual.Multiplayer } [Test] - public void TestJoinRoomWithPassword() + public void TestJoinRoomWithIncorrectPassword() + { + DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null; + + AddStep("add room", () => RoomManager.AddRooms(1, withPassword: true)); + AddStep("select room", () => InputManager.Key(Key.Down)); + AddStep("attempt join room", () => InputManager.Key(Key.Enter)); + AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType().FirstOrDefault()) != null); + AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType().First().Text = "wrong"); + AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType().First().TriggerClick()); + + AddAssert("room not joined", () => loungeScreen.IsCurrentScreen()); + AddUntilStep("password prompt still visible", () => passwordEntryPopover.State.Value == Visibility.Visible); + } + + [Test] + public void TestJoinRoomWithCorrectPassword() { DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null; From e3c56f9ebde94c87276af777164f61581142732a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Sep 2021 14:10:55 +0900 Subject: [PATCH 025/109] Show error message in popover --- .../OnlinePlay/Components/RoomManager.cs | 8 ++-- .../OnlinePlay/Lounge/DrawableLoungeRoom.cs | 37 ++++++++++++++----- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs index 4b3617c74a..a64d89b699 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs @@ -87,10 +87,10 @@ namespace osu.Game.Screens.OnlinePlay.Components currentJoinRoomRequest.Failure += exception => { - // provide error output if the operation wasn't canceled and the error doesn't stem from an invalid password - if (!(exception is OperationCanceledException) && !((APIException)exception).Message.Equals("Invalid room password", StringComparison.Ordinal)) - Logger.Log($"Failed to join room: {exception}", level: LogLevel.Important); - onError?.Invoke(exception.ToString()); + if (exception is OperationCanceledException) + return; + + onError?.Invoke(exception.Message); }; api.Queue(currentJoinRoomRequest); diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 2fc039ad79..0dec9b72bf 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -14,7 +14,9 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Input.Bindings; @@ -189,9 +191,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private OsuPasswordTextBox passwordTextbox; private TriangleButton joinButton; private ShakeContainer shakeContainer; + private OsuSpriteText errorText; [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours) { Child = shakeContainer = new ShakeContainer { @@ -201,19 +204,32 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { Spacing = new Vector2(5), AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, + Direction = FillDirection.Vertical, Children = new Drawable[] { - passwordTextbox = new OsuPasswordTextBox + new FillFlowContainer { - Width = 200, - PlaceholderText = "password", + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5), + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + passwordTextbox = new OsuPasswordTextBox + { + Width = 200, + PlaceholderText = "password", + }, + joinButton = new TriangleButton + { + Width = 80, + Text = "Join Room", + } + } }, - joinButton = new TriangleButton + errorText = new OsuSpriteText { - Width = 80, - Text = "Join Room", - } + Colour = colours.Red, + }, } } }; @@ -225,6 +241,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { passwordTextbox.Text = string.Empty; + errorText.Text = error; + errorText.FadeOutFromOne(1000, Easing.In); + shakeContainer.Shake(); } From 7bd749d0eb8bdda4997a66531691cc4f052b8481 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Sep 2021 14:19:55 +0900 Subject: [PATCH 026/109] Remove weird shaking --- .../OnlinePlay/Lounge/DrawableLoungeRoom.cs | 56 +++++++++---------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 0dec9b72bf..a67389e4c0 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -15,7 +15,6 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; @@ -190,47 +189,44 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private OsuPasswordTextBox passwordTextbox; private TriangleButton joinButton; - private ShakeContainer shakeContainer; private OsuSpriteText errorText; [BackgroundDependencyLoader] private void load(OsuColour colours) { - Child = shakeContainer = new ShakeContainer + Padding = new MarginPadding(10); + + Child = new FillFlowContainer { Margin = new MarginPadding(10), + Spacing = new Vector2(5), AutoSizeAxes = Axes.Both, - Child = new FillFlowContainer + Direction = FillDirection.Vertical, + Children = new Drawable[] { - Spacing = new Vector2(5), - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] + new FillFlowContainer { - new FillFlowContainer + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5), + AutoSizeAxes = Axes.Both, + Children = new Drawable[] { - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5), - AutoSizeAxes = Axes.Both, - Children = new Drawable[] + passwordTextbox = new OsuPasswordTextBox { - passwordTextbox = new OsuPasswordTextBox - { - Width = 200, - PlaceholderText = "password", - }, - joinButton = new TriangleButton - { - Width = 80, - Text = "Join Room", - } + Width = 200, + PlaceholderText = "password", + }, + joinButton = new TriangleButton + { + Width = 80, + Text = "Join Room", } - }, - errorText = new OsuSpriteText - { - Colour = colours.Red, - }, - } + } + }, + errorText = new OsuSpriteText + { + Colour = colours.Red, + }, } }; @@ -243,8 +239,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge errorText.Text = error; errorText.FadeOutFromOne(1000, Easing.In); - - shakeContainer.Shake(); } protected override void LoadComplete() From e17b800470d18095e079699795fe475fbd0c18e6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Sep 2021 14:44:23 +0900 Subject: [PATCH 027/109] Move shake logic into extension method --- osu.Game/Extensions/DrawableExtensions.cs | 27 +++++++++++++++ .../Graphics/Containers/ShakeContainer.cs | 34 ++----------------- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/osu.Game/Extensions/DrawableExtensions.cs b/osu.Game/Extensions/DrawableExtensions.cs index 52d8230fb6..b05a2994ea 100644 --- a/osu.Game/Extensions/DrawableExtensions.cs +++ b/osu.Game/Extensions/DrawableExtensions.cs @@ -38,6 +38,33 @@ namespace osu.Game.Extensions return repeatDelegate; } + /// + /// Shake the contents of this container. + /// + /// The target to shake. + /// The length of a single shake. + /// Pixels of displacement per shake. + /// The maximum length the shake should last. + public static void Shake(this Drawable target, double shakeDuration = 80, float shakeMagnitude = 8, double? maximumLength = null) + { + // if we don't have enough time, don't bother shaking. + if (maximumLength < shakeDuration * 2) + return; + + var sequence = target.MoveToX(shakeMagnitude, shakeDuration / 2, Easing.OutSine).Then() + .MoveToX(-shakeMagnitude, shakeDuration, Easing.InOutSine).Then(); + + // if we don't have enough time for the second shake, skip it. + if (!maximumLength.HasValue || maximumLength >= shakeDuration * 4) + { + sequence = sequence + .MoveToX(shakeMagnitude, shakeDuration, Easing.InOutSine).Then() + .MoveToX(-shakeMagnitude, shakeDuration, Easing.InOutSine).Then(); + } + + sequence.MoveToX(0, shakeDuration / 2, Easing.InSine); + } + /// /// Accepts a delta vector in screen-space coordinates and converts it to one which can be applied to this drawable's position. /// diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index dca9df1e98..8a0ce287db 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -1,8 +1,8 @@ // 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.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Extensions; namespace osu.Game.Graphics.Containers { @@ -16,40 +16,10 @@ namespace osu.Game.Graphics.Containers /// public float ShakeDuration = 80; - /// - /// Total number of shakes. May be shortened if possible. - /// - public float TotalShakes = 4; - - /// - /// Pixels of displacement per shake. - /// - public float ShakeMagnitude = 8; - /// /// Shake the contents of this container. /// /// The maximum length the shake should last. - public void Shake(double? maximumLength = null) - { - const float shake_amount = 8; - - // if we don't have enough time, don't bother shaking. - if (maximumLength < ShakeDuration * 2) - return; - - var sequence = this.MoveToX(shake_amount, ShakeDuration / 2, Easing.OutSine).Then() - .MoveToX(-shake_amount, ShakeDuration, Easing.InOutSine).Then(); - - // if we don't have enough time for the second shake, skip it. - if (!maximumLength.HasValue || maximumLength >= ShakeDuration * 4) - { - sequence = sequence - .MoveToX(shake_amount, ShakeDuration, Easing.InOutSine).Then() - .MoveToX(-shake_amount, ShakeDuration, Easing.InOutSine).Then(); - } - - sequence.MoveToX(0, ShakeDuration / 2, Easing.InSine); - } + public void Shake(double? maximumLength = null) => this.Shake(ShakeDuration, maximumLength: maximumLength); } } From 8865e3cab8abdde1164f1d4cadea2a8a1dac1cb9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Sep 2021 14:44:32 +0900 Subject: [PATCH 028/109] Add back shake and tweak transform of text --- osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index a67389e4c0..11c3cfe06a 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -14,6 +14,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -238,7 +239,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge passwordTextbox.Text = string.Empty; errorText.Text = error; - errorText.FadeOutFromOne(1000, Easing.In); + errorText + .FadeIn() + .FlashColour(Color4.White, 200) + .Delay(1000) + .FadeOutFromOne(1000, Easing.In); + + Body.Shake(); } protected override void LoadComplete() From 5058f285048d9ac7354f02d8514203321584c44f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Sep 2021 14:52:50 +0900 Subject: [PATCH 029/109] Remove breaking padding --- osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 11c3cfe06a..310df0b91d 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -195,8 +195,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge [BackgroundDependencyLoader] private void load(OsuColour colours) { - Padding = new MarginPadding(10); - Child = new FillFlowContainer { Margin = new MarginPadding(10), From 67750e6e1a1e0b99091c0f893fd129972df6d4a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Sep 2021 15:08:43 +0900 Subject: [PATCH 030/109] Fix subsequent navigation tests failing due to escape key not being released --- osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 2c416ee758..aeb800f58a 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -418,6 +418,7 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("Hold escape", () => InputManager.PressKey(Key.Escape)); AddUntilStep("Wait for intro", () => Game.ScreenStack.CurrentScreen is IntroTriangles); + AddStep("Release escape", () => InputManager.ReleaseKey(Key.Escape)); AddUntilStep("Wait for game exit", () => Game.ScreenStack.CurrentScreen == null); AddStep("test dispose doesn't crash", () => Game.Dispose()); } From 6cffbee59256e0bca56d424f5b0f77605d3f195a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Sep 2021 17:22:58 +0900 Subject: [PATCH 031/109] Fix random/target mods not working in spectator --- osu.Game/Online/Spectator/SpectatorClient.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs index 2546374b21..494739797a 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -153,9 +153,9 @@ namespace osu.Game.Online.Spectator IsPlaying = true; // transfer state at point of beginning play - currentState.BeatmapID = beatmap.BeatmapInfo.OnlineBeatmapID; - currentState.RulesetID = currentRuleset.Value.ID; - currentState.Mods = currentMods.Value.Select(m => new APIMod(m)); + currentState.BeatmapID = score.ScoreInfo.Beatmap.OnlineBeatmapID; + currentState.RulesetID = score.ScoreInfo.RulesetID; + currentState.Mods = score.ScoreInfo.Mods.Select(m => new APIMod(m)).ToArray(); currentBeatmap = beatmap.PlayableBeatmap; currentScore = score; From b807c161b4907633304322a9525f5569d9bc18d8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Sep 2021 17:23:45 +0900 Subject: [PATCH 032/109] Remove now-unused DI params --- osu.Game/Online/Spectator/SpectatorClient.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs index 494739797a..8c617784b9 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -15,8 +15,6 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Replays.Legacy; -using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Scoring; @@ -46,15 +44,8 @@ namespace osu.Game.Online.Spectator private readonly BindableDictionary playingUserStates = new BindableDictionary(); private IBeatmap? currentBeatmap; - private Score? currentScore; - [Resolved] - private IBindable currentRuleset { get; set; } = null!; - - [Resolved] - private IBindable> currentMods { get; set; } = null!; - private readonly SpectatorState currentState = new SpectatorState(); /// From 63aa3ddcba2ba2d1681c67e1d510ce245a079ef8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Sep 2021 17:45:23 +0900 Subject: [PATCH 033/109] Add animation support for mania notes --- .../Legacy/LegacyHoldNoteHeadPiece.cs | 8 +++--- .../Legacy/LegacyHoldNoteTailPiece.cs | 10 +++---- .../Skinning/Legacy/LegacyNotePiece.cs | 26 +++++++++++++------ osu.Game/Skinning/LegacySkinExtensions.cs | 3 +++ 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs index 21e5bdd5d6..1e75533442 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs @@ -1,18 +1,18 @@ // 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.Graphics.Textures; +using osu.Framework.Graphics; using osu.Game.Skinning; namespace osu.Game.Rulesets.Mania.Skinning.Legacy { public class LegacyHoldNoteHeadPiece : LegacyNotePiece { - protected override Texture GetTexture(ISkinSource skin) + protected override Drawable GetAnimation(ISkinSource skin) { // TODO: Should fallback to the head from default legacy skin instead of note. - return GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage) - ?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage); + return GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage) + ?? GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage); } } } diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs index 232b47ae27..e6d4291d79 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; -using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Skinning; @@ -18,12 +18,12 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy : new ValueChangedEvent(ScrollingDirection.Up, ScrollingDirection.Up)); } - protected override Texture GetTexture(ISkinSource skin) + protected override Drawable GetAnimation(ISkinSource skin) { // TODO: Should fallback to the head from default legacy skin instead of note. - return GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteTailImage) - ?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage) - ?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage); + return GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteTailImage) + ?? GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage) + ?? GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage); } } } diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs index 31279796ce..e8ff1c23f3 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs @@ -1,9 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.Sprites; @@ -19,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy private readonly IBindable direction = new Bindable(); private Container directionContainer; - private Sprite noteSprite; + private Drawable noteAnimation; private float? minimumColumnWidth; @@ -39,7 +41,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Child = noteSprite = new Sprite { Texture = GetTexture(skin) } + Child = noteAnimation = GetAnimation(skin) }; direction.BindTo(scrollingInfo.Direction); @@ -50,12 +52,18 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy { base.Update(); - if (noteSprite.Texture != null) + Texture texture = null; + + if (noteAnimation is Sprite sprite) + texture = sprite.Texture; + else if (noteAnimation is TextureAnimation textureAnimation) + texture = textureAnimation.CurrentFrame; + + if (texture != null) { // The height is scaled to the minimum column width, if provided. float minimumWidth = minimumColumnWidth ?? DrawWidth; - - noteSprite.Scale = Vector2.Divide(new Vector2(DrawWidth, minimumWidth), noteSprite.Texture.DisplayWidth); + noteAnimation.Scale = Vector2.Divide(new Vector2(DrawWidth, minimumWidth), texture.DisplayWidth); } } @@ -73,9 +81,11 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy } } - protected virtual Texture GetTexture(ISkinSource skin) => GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage); + [CanBeNull] + protected virtual Drawable GetAnimation(ISkinSource skin) => GetAnimationFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage); - protected Texture GetTextureFromLookup(ISkin skin, LegacyManiaSkinConfigurationLookups lookup) + [CanBeNull] + protected Drawable GetAnimationFromLookup(ISkin skin, LegacyManiaSkinConfigurationLookups lookup) { string suffix = string.Empty; @@ -93,7 +103,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy string noteImage = GetColumnSkinConfig(skin, lookup)?.Value ?? $"mania-note{FallbackColumnIndex}{suffix}"; - return skin.GetTexture(noteImage, WrapMode.ClampToEdge, WrapMode.ClampToEdge); + return skin.GetAnimation(noteImage, WrapMode.ClampToEdge, WrapMode.ClampToEdge, true, true); } } } diff --git a/osu.Game/Skinning/LegacySkinExtensions.cs b/osu.Game/Skinning/LegacySkinExtensions.cs index ec25268be4..fd1f905868 100644 --- a/osu.Game/Skinning/LegacySkinExtensions.cs +++ b/osu.Game/Skinning/LegacySkinExtensions.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -17,10 +18,12 @@ namespace osu.Game.Skinning { public static class LegacySkinExtensions { + [CanBeNull] public static Drawable GetAnimation(this ISkin source, string componentName, bool animatable, bool looping, bool applyConfigFrameRate = false, string animationSeparator = "-", bool startAtCurrentTime = true, double? frameLength = null) => source.GetAnimation(componentName, default, default, animatable, looping, applyConfigFrameRate, animationSeparator, startAtCurrentTime, frameLength); + [CanBeNull] public static Drawable GetAnimation(this ISkin source, string componentName, WrapMode wrapModeS, WrapMode wrapModeT, bool animatable, bool looping, bool applyConfigFrameRate = false, string animationSeparator = "-", bool startAtCurrentTime = true, double? frameLength = null) From c009e1473ddf319d2229a03bcab7e80e55356ad3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Sep 2021 17:47:12 +0900 Subject: [PATCH 034/109] Add extra safety check --- osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs index e8ff1c23f3..bbc7520bac 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy if (noteAnimation is Sprite sprite) texture = sprite.Texture; - else if (noteAnimation is TextureAnimation textureAnimation) + else if (noteAnimation is TextureAnimation textureAnimation && textureAnimation.FrameCount > 0) texture = textureAnimation.CurrentFrame; if (texture != null) From a7759153385c7d7d9bfa78e0b5b060e994d2d60f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Sep 2021 18:20:28 +0900 Subject: [PATCH 035/109] Fix incorrect beatmap count and SR range in multi lounge --- .../Screens/OnlinePlay/Components/ListingPollingComponent.cs | 5 +++++ .../OnlinePlay/Components/SelectionPollingComponent.cs | 3 +++ 2 files changed, 8 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs index daac6a66cd..5a74df6ab1 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs @@ -57,7 +57,12 @@ namespace osu.Game.Screens.OnlinePlay.Components } foreach (var incoming in result) + { + // Copy the room to itself to populate some members (such as status and playlist expiry). + incoming.CopyFrom(incoming); + RoomManager.AddOrUpdateRoom(incoming); + } initialRoomsReceived.Value = true; tcs.SetResult(true); diff --git a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs index 0769d0747b..0a37d47e34 100644 --- a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs @@ -39,6 +39,9 @@ namespace osu.Game.Screens.OnlinePlay.Components pollReq.Success += result => { + // Copy the room to itself to populate some members (such as status and playlist expiry). + result.CopyFrom(result); + RoomManager.AddOrUpdateRoom(result); tcs.SetResult(true); }; From 2a894e7a3f560ae785e3395b55d36e8695a83741 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Sep 2021 23:26:02 +0900 Subject: [PATCH 036/109] Make `EditorLoader` state `private` --- osu.Game/Screens/Edit/EditorLoader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/EditorLoader.cs b/osu.Game/Screens/Edit/EditorLoader.cs index b6e57b0491..5ad720f7f0 100644 --- a/osu.Game/Screens/Edit/EditorLoader.cs +++ b/osu.Game/Screens/Edit/EditorLoader.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Edit /// This will be read by the next editor instance to be opened to restore any relevant previous state. /// [CanBeNull] - public EditorState State; + private EditorState state; public override float BackgroundParallaxAmount => 0.1f; @@ -78,7 +78,7 @@ namespace osu.Game.Screens.Edit scheduledDifficultySwitch = Schedule(() => { Beatmap.Value = beatmapManager.GetWorkingBeatmap(nextBeatmap); - State = editorState; + state = editorState; // This screen is a weird exception to the rule that nothing after song select changes the global beatmap. // Because of this, we need to update the background stack's beatmap to match. From f8bdca542d2a6d993b3b0d4a6ddc7ae87ddaf9a4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Sep 2021 23:36:17 +0900 Subject: [PATCH 037/109] Make restoring state a `public` call on `Editor` --- osu.Game/Screens/Edit/Editor.cs | 22 +++++++++++----------- osu.Game/Screens/Edit/EditorLoader.cs | 8 +++++++- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index eba75f4408..5bb47e1c11 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -317,6 +317,16 @@ namespace osu.Game.Screens.Edit /// public void UpdateClockSource() => clock.ChangeSource(Beatmap.Value.Track); + /// + /// Restore the editor to a provided state. + /// + /// The state to restore. + public void RestoreState([NotNull] EditorState state) => Schedule(() => + { + clock.Seek(state.Time); + clipboard.Value = state.ClipboardContent; + }); + protected void Save() { // no longer new after first user-triggered save. @@ -476,8 +486,6 @@ namespace osu.Game.Screens.Edit }); resetTrack(true); - if (loader?.State != null) - restoreState(loader.State); } public override bool OnExiting(IScreen next) @@ -745,17 +753,9 @@ namespace osu.Game.Screens.Edit protected void SwitchToDifficulty(BeatmapInfo nextBeatmap) => loader?.ScheduleDifficultySwitch(nextBeatmap, new EditorState { Time = clock.CurrentTimeAccurate, - ClipboardContent = editorBeatmap.BeatmapInfo.RulesetID == nextBeatmap.RulesetID ? clipboard.Value : null + ClipboardContent = editorBeatmap.BeatmapInfo.RulesetID == nextBeatmap.RulesetID ? clipboard.Value : string.Empty }); - private void restoreState([NotNull] EditorState state) - { - if (state.Time != null) - clock.Seek(state.Time.Value); - - clipboard.Value = state.ClipboardContent ?? clipboard.Value; - } - private void cancelExit() => loader?.CancelPendingDifficultySwitch(); public double SnapTime(double time, double? referenceTime) => editorBeatmap.SnapTime(time, referenceTime); diff --git a/osu.Game/Screens/Edit/EditorLoader.cs b/osu.Game/Screens/Edit/EditorLoader.cs index 5ad720f7f0..2a01a5b6b2 100644 --- a/osu.Game/Screens/Edit/EditorLoader.cs +++ b/osu.Game/Screens/Edit/EditorLoader.cs @@ -91,7 +91,13 @@ namespace osu.Game.Screens.Edit private void pushEditor() { - this.Push(CreateEditor()); + var editor = CreateEditor(); + + this.Push(editor); + + if (state != null) + editor.RestoreState(state); + ValidForResume = false; } From 57f8ccca167d48e79c3c5e89b8d9db6d4a7febe9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Sep 2021 23:36:26 +0900 Subject: [PATCH 038/109] Remove nullability from `EditorState` properties Also update the xmldoc to not be specific to difficulty switching --- osu.Game/Screens/Edit/EditorState.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/EditorState.cs b/osu.Game/Screens/Edit/EditorState.cs index 09cc1184d2..4690074e3d 100644 --- a/osu.Game/Screens/Edit/EditorState.cs +++ b/osu.Game/Screens/Edit/EditorState.cs @@ -6,19 +6,18 @@ namespace osu.Game.Screens.Edit { /// - /// Structure used to transport data between instances on difficulty change. - /// It's intended to be received by from one editor instance and passed down to the next one. + /// Structure used to convey the general state of an instance. /// public class EditorState { /// - /// The current clock time when a difficulty switch was requested. + /// The current audio time. /// - public double? Time { get; set; } + public double Time { get; set; } /// - /// The current editor clipboard content at the time when a difficulty switch was requested. + /// The editor clipboard content. /// - public string? ClipboardContent { get; set; } + public string ClipboardContent { get; set; } = string.Empty; } } From b9193aae6dcec54c1e5ff1a51f6863e240de7c74 Mon Sep 17 00:00:00 2001 From: AbstractQbit <38468635+AbstractQbit@users.noreply.github.com> Date: Tue, 14 Sep 2021 17:37:57 +0300 Subject: [PATCH 039/109] Make IOsuScreen.AllowTrackAdjustments nullable Allows for inheriting value from the previous screen if undefined --- osu.Game/OsuGame.cs | 29 +++++++++++++++++-- .../Maintenance/DirectorySelectScreen.cs | 2 +- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/IOsuScreen.cs | 3 +- osu.Game/Screens/Import/FileImportScreen.cs | 2 +- osu.Game/Screens/Menu/MainMenu.cs | 2 +- .../Spectate/MultiSpectatorScreen.cs | 2 +- .../Screens/OnlinePlay/OnlinePlayScreen.cs | 2 +- .../Screens/OnlinePlay/OnlinePlaySubScreen.cs | 2 ++ osu.Game/Screens/OsuScreen.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- .../Play/ScreenWithBeatmapBackground.cs | 2 ++ osu.Game/Screens/StartupScreen.cs | 2 +- 13 files changed, 42 insertions(+), 12 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 2107b3a0e9..c6a07bbbba 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1075,8 +1075,6 @@ namespace osu.Game OverlayActivationMode.BindTo(newOsuScreen.OverlayActivationMode); API.Activity.BindTo(newOsuScreen.Activity); - MusicController.AllowTrackAdjustments = newOsuScreen.AllowTrackAdjustments; - if (newOsuScreen.HideOverlaysOnEnter) CloseAllOverlays(); else @@ -1093,6 +1091,24 @@ namespace osu.Game { ScreenChanged(lastScreen, newScreen); Logger.Log($"Screen changed → {newScreen}"); + + // set AllowTrackAdjustments if new screen defines it, inherit otherwise + if (newScreen is IOsuScreen newOsuScreen && newOsuScreen.AllowTrackAdjustments.HasValue) + { + allowTrackAdjustmentsStack.Push(newOsuScreen.AllowTrackAdjustments.Value); + Logger.Log($"Screen's AllowTrackAdjustments explicit → {allowTrackAdjustmentsStack.First()}"); + } + else if (allowTrackAdjustmentsStack.Any()) + { + allowTrackAdjustmentsStack.Push(allowTrackAdjustmentsStack.First()); + Logger.Log($"Screen's AllowTrackAdjustments inherit → {allowTrackAdjustmentsStack.First()}"); + } + else + { + allowTrackAdjustmentsStack.Push(false); + } + + MusicController.AllowTrackAdjustments = allowTrackAdjustmentsStack.First(); } private void screenExited(IScreen lastScreen, IScreen newScreen) @@ -1102,8 +1118,17 @@ namespace osu.Game if (newScreen == null) Exit(); + + if (allowTrackAdjustmentsStack.Count > 1) + { + allowTrackAdjustmentsStack.Pop(); + MusicController.AllowTrackAdjustments = allowTrackAdjustmentsStack.First(); + Logger.Log($"Screen's AllowTrackAdjustments return ← {allowTrackAdjustmentsStack.First()}"); + } } + private Stack allowTrackAdjustmentsStack = new Stack(); + IBindable ILocalUserPlayInfo.IsPlaying => LocalUserPlaying; } } diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs index 1d67968ab1..6d0e79e2c7 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance private OsuDirectorySelector directorySelector; - public override bool AllowTrackAdjustments => false; + public override bool? AllowTrackAdjustments => false; /// /// Text to display in the header to inform the user of what they are selecting. diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 28ae7e620e..13e4a11915 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Edit public override bool DisallowExternalBeatmapRulesetChanges => true; - public override bool AllowTrackAdjustments => false; + public override bool? AllowTrackAdjustments => false; protected bool HasUnsavedChanges => lastSavedHash != changeHandler.CurrentStateHash; diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index 17384c161c..a1e4d9ed01 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -60,8 +60,9 @@ namespace osu.Game.Screens /// /// Whether mod track adjustments are allowed to be applied. + /// Null means to inherit from the parent screen. /// - bool AllowTrackAdjustments { get; } + bool? AllowTrackAdjustments { get; } /// /// Invoked when the back button has been pressed to close any overlays before exiting this . diff --git a/osu.Game/Screens/Import/FileImportScreen.cs b/osu.Game/Screens/Import/FileImportScreen.cs index 606174193d..69fcf31876 100644 --- a/osu.Game/Screens/Import/FileImportScreen.cs +++ b/osu.Game/Screens/Import/FileImportScreen.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Import { public override bool HideOverlaysOnEnter => true; - public override bool AllowTrackAdjustments => false; + public override bool? AllowTrackAdjustments => false; private OsuFileSelector fileSelector; private Container contentContainer; diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 8b2ec43e3e..00885a91c5 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -36,7 +36,7 @@ namespace osu.Game.Screens.Menu public override bool AllowExternalScreenChange => true; - public override bool AllowTrackAdjustments => false; + public override bool? AllowTrackAdjustments => false; private Screen songSelect; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index bf7c738882..c45e3a79da 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate public override bool DisallowExternalBeatmapRulesetChanges => true; // We are managing our own adjustments. For now, this happens inside the Player instances themselves. - public override bool AllowTrackAdjustments => false; + public override bool? AllowTrackAdjustments => false; /// /// Whether all spectating players have finished loading. diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 62bfd2cfed..e3945c9cac 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.OnlinePlay [Cached] protected readonly OverlayColourProvider ColourProvider = new OverlayColourProvider(OverlayColourScheme.Plum); - public override bool AllowTrackAdjustments => false; + public override bool? AllowTrackAdjustments => false; public override bool CursorVisible => (screenStack?.CurrentScreen as IOnlinePlaySubScreen)?.CursorVisible ?? true; diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs index 3411c4afb1..8c4f0c1394 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs @@ -11,6 +11,8 @@ namespace osu.Game.Screens.OnlinePlay { public override bool DisallowExternalBeatmapRulesetChanges => false; + public override bool? AllowTrackAdjustments => true; + public virtual string ShortTitle => Title; [Resolved(CanBeNull = true)] diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 9aec2a5c19..78908b5d8a 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -81,7 +81,7 @@ namespace osu.Game.Screens public virtual float BackgroundParallaxAmount => 1; - public virtual bool AllowTrackAdjustments => true; + public virtual bool? AllowTrackAdjustments => null; public Bindable Beatmap { get; private set; } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index e8a2790c94..9927467bd6 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Play protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.UserTriggered; // We are managing our own adjustments (see OnEntering/OnExiting). - public override bool AllowTrackAdjustments => false; + public override bool? AllowTrackAdjustments => false; private readonly IBindable gameActive = new Bindable(true); diff --git a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs index 88dab88d42..9bec320e22 100644 --- a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs +++ b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs @@ -10,6 +10,8 @@ namespace osu.Game.Screens.Play { protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); + public override bool? AllowTrackAdjustments => true; + public void ApplyToBackground(Action action) => base.ApplyToBackground(b => action.Invoke((BackgroundScreenBeatmap)b)); } } diff --git a/osu.Game/Screens/StartupScreen.cs b/osu.Game/Screens/StartupScreen.cs index 15f75d7cff..7b73d36fdf 100644 --- a/osu.Game/Screens/StartupScreen.cs +++ b/osu.Game/Screens/StartupScreen.cs @@ -16,7 +16,7 @@ namespace osu.Game.Screens public override bool CursorVisible => false; - public override bool AllowTrackAdjustments => false; + public override bool? AllowTrackAdjustments => false; protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; } From 01d2f4f17a98bfb372410838eb8159c260b6fa8a Mon Sep 17 00:00:00 2001 From: AbstractQbit <38468635+AbstractQbit@users.noreply.github.com> Date: Tue, 14 Sep 2021 18:04:43 +0300 Subject: [PATCH 040/109] Make `allowTrackAdjustmentsStack` readonly --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index c6a07bbbba..5f1b2ac87d 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1127,7 +1127,7 @@ namespace osu.Game } } - private Stack allowTrackAdjustmentsStack = new Stack(); + private readonly Stack allowTrackAdjustmentsStack = new Stack(); IBindable ILocalUserPlayInfo.IsPlaying => LocalUserPlaying; } From bd18c581c11a6437a9a055ae4b267425d8463d6f Mon Sep 17 00:00:00 2001 From: AbstractQbit <38468635+AbstractQbit@users.noreply.github.com> Date: Tue, 14 Sep 2021 21:14:24 +0300 Subject: [PATCH 041/109] Replace `allowTrackAdjustmentsStack` with a Dictionary --- osu.Game/OsuGame.cs | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 5f1b2ac87d..499b561718 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1094,21 +1094,13 @@ namespace osu.Game // set AllowTrackAdjustments if new screen defines it, inherit otherwise if (newScreen is IOsuScreen newOsuScreen && newOsuScreen.AllowTrackAdjustments.HasValue) - { - allowTrackAdjustmentsStack.Push(newOsuScreen.AllowTrackAdjustments.Value); - Logger.Log($"Screen's AllowTrackAdjustments explicit → {allowTrackAdjustmentsStack.First()}"); - } - else if (allowTrackAdjustmentsStack.Any()) - { - allowTrackAdjustmentsStack.Push(allowTrackAdjustmentsStack.First()); - Logger.Log($"Screen's AllowTrackAdjustments inherit → {allowTrackAdjustmentsStack.First()}"); - } + allowTrackAdjustmentsDict[newScreen] = newOsuScreen.AllowTrackAdjustments.Value; + else if (allowTrackAdjustmentsDict.ContainsKey(lastScreen)) + allowTrackAdjustmentsDict[newScreen] = allowTrackAdjustmentsDict[lastScreen]; else - { - allowTrackAdjustmentsStack.Push(false); - } + allowTrackAdjustmentsDict[newScreen] = true; - MusicController.AllowTrackAdjustments = allowTrackAdjustmentsStack.First(); + MusicController.AllowTrackAdjustments = allowTrackAdjustmentsDict[newScreen]; } private void screenExited(IScreen lastScreen, IScreen newScreen) @@ -1116,18 +1108,15 @@ namespace osu.Game ScreenChanged(lastScreen, newScreen); Logger.Log($"Screen changed ← {newScreen}"); + allowTrackAdjustmentsDict.Remove(lastScreen); + if (newScreen == null) Exit(); - - if (allowTrackAdjustmentsStack.Count > 1) - { - allowTrackAdjustmentsStack.Pop(); - MusicController.AllowTrackAdjustments = allowTrackAdjustmentsStack.First(); - Logger.Log($"Screen's AllowTrackAdjustments return ← {allowTrackAdjustmentsStack.First()}"); - } + else + MusicController.AllowTrackAdjustments = allowTrackAdjustmentsDict[newScreen]; } - private readonly Stack allowTrackAdjustmentsStack = new Stack(); + private readonly Dictionary allowTrackAdjustmentsDict = new Dictionary(); IBindable ILocalUserPlayInfo.IsPlaying => LocalUserPlaying; } From baf99619343ff49ed240c8cc09e3db9453dfda2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 14 Sep 2021 22:50:45 +0200 Subject: [PATCH 042/109] Amend xmldoc of shake extension method --- osu.Game/Extensions/DrawableExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Extensions/DrawableExtensions.cs b/osu.Game/Extensions/DrawableExtensions.cs index b05a2994ea..03cc345947 100644 --- a/osu.Game/Extensions/DrawableExtensions.cs +++ b/osu.Game/Extensions/DrawableExtensions.cs @@ -39,7 +39,7 @@ namespace osu.Game.Extensions } /// - /// Shake the contents of this container. + /// Shakes this drawable. /// /// The target to shake. /// The length of a single shake. From 4b3ab42ffd8cb2b9c60490315dce8470637dffcd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Sep 2021 13:18:46 +0900 Subject: [PATCH 043/109] Ensure beatmap is populated --- osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs | 8 +++++++- .../Visual/Gameplay/TestSceneReplayRecording.cs | 8 +++++++- .../Visual/Gameplay/TestSceneSpectatorPlayback.cs | 4 +++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs index b38f7a998d..aded934b88 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs @@ -17,10 +17,12 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Replays; using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Visual.UserInterface; using osuTK; using osuTK.Graphics; @@ -54,7 +56,11 @@ namespace osu.Game.Tests.Visual.Gameplay { recordingManager = new TestRulesetInputManager(new TestSceneModSettings.TestRulesetInfo(), 0, SimultaneousBindingMode.Unique) { - Recorder = recorder = new TestReplayRecorder(new Score { Replay = replay }) + Recorder = recorder = new TestReplayRecorder(new Score + { + Replay = replay, + ScoreInfo = { Beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo } + }) { ScreenSpaceToGamefield = pos => recordingManager.ToLocalSpace(pos), }, diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs index 6e338b7202..37fd1a77d5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs @@ -13,10 +13,12 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Replays; using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Visual.UserInterface; using osuTK; using osuTK.Graphics; @@ -45,7 +47,11 @@ namespace osu.Game.Tests.Visual.Gameplay { recordingManager = new TestRulesetInputManager(new TestSceneModSettings.TestRulesetInfo(), 0, SimultaneousBindingMode.Unique) { - Recorder = new TestReplayRecorder(new Score { Replay = replay }) + Recorder = new TestReplayRecorder(new Score + { + Replay = replay, + ScoreInfo = { Beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo } + }) { ScreenSpaceToGamefield = pos => recordingManager.ToLocalSpace(pos) }, diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs index bb577886cc..039daf39e2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs @@ -25,11 +25,13 @@ using osu.Game.Online.Spectator; using osu.Game.Replays; using osu.Game.Replays.Legacy; using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Visual.UserInterface; using osuTK; using osuTK.Graphics; @@ -354,7 +356,7 @@ namespace osu.Game.Tests.Visual.Gameplay internal class TestReplayRecorder : ReplayRecorder { public TestReplayRecorder() - : base(new Score()) + : base(new Score { ScoreInfo = { Beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo } }) { } From 34bde293abebbe144c6e7ab425aa874af8289da2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Sep 2021 13:26:39 +0900 Subject: [PATCH 044/109] Fix tests --- osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs index bbc7520bac..321a87f8b1 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs @@ -21,6 +21,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy private readonly IBindable direction = new Bindable(); private Container directionContainer; + + [CanBeNull] private Drawable noteAnimation; private float? minimumColumnWidth; @@ -41,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Child = noteAnimation = GetAnimation(skin) + Child = noteAnimation = GetAnimation(skin) ?? Empty() }; direction.BindTo(scrollingInfo.Direction); From a2dcef7c0aa1acd3557007e3c410443862318512 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Sep 2021 13:37:30 +0900 Subject: [PATCH 045/109] Use local (or barebones `BeatmapInfo`) where feasible --- osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs | 4 +--- osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs | 4 +--- osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs index aded934b88..2ce0213ea2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs @@ -17,12 +17,10 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Replays; using osu.Game.Rulesets; -using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Play; -using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Visual.UserInterface; using osuTK; using osuTK.Graphics; @@ -59,7 +57,7 @@ namespace osu.Game.Tests.Visual.Gameplay Recorder = recorder = new TestReplayRecorder(new Score { Replay = replay, - ScoreInfo = { Beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo } + ScoreInfo = { Beatmap = gameplayBeatmap.BeatmapInfo } }) { ScreenSpaceToGamefield = pos => recordingManager.ToLocalSpace(pos), diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs index 37fd1a77d5..85a2870bf9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs @@ -13,12 +13,10 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Replays; using osu.Game.Rulesets; -using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Play; -using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Visual.UserInterface; using osuTK; using osuTK.Graphics; @@ -50,7 +48,7 @@ namespace osu.Game.Tests.Visual.Gameplay Recorder = new TestReplayRecorder(new Score { Replay = replay, - ScoreInfo = { Beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo } + ScoreInfo = { Beatmap = gameplayBeatmap.BeatmapInfo } }) { ScreenSpaceToGamefield = pos => recordingManager.ToLocalSpace(pos) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs index 039daf39e2..d9d0dc6c58 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs @@ -25,13 +25,11 @@ using osu.Game.Online.Spectator; using osu.Game.Replays; using osu.Game.Replays.Legacy; using osu.Game.Rulesets; -using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Screens.Play; -using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Visual.UserInterface; using osuTK; using osuTK.Graphics; @@ -356,7 +354,7 @@ namespace osu.Game.Tests.Visual.Gameplay internal class TestReplayRecorder : ReplayRecorder { public TestReplayRecorder() - : base(new Score { ScoreInfo = { Beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo } }) + : base(new Score { ScoreInfo = { Beatmap = new BeatmapInfo() } }) { } From 8217b90b1cb71f793a25e31dc644794da4b1d189 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 5 Sep 2021 00:41:34 +0300 Subject: [PATCH 046/109] Consider legacy glyph texture heights as the baselines for simplicity Mixing `LegacySpriteText` with legitment fonts should never be the case, so it's fine to consuder the height as the baseline, since there's really no other way around it. --- osu.Game/Skinning/LegacySpriteText.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySpriteText.cs b/osu.Game/Skinning/LegacySpriteText.cs index 7895fcccca..8fc6cbde7d 100644 --- a/osu.Game/Skinning/LegacySpriteText.cs +++ b/osu.Game/Skinning/LegacySpriteText.cs @@ -56,7 +56,7 @@ namespace osu.Game.Skinning if (texture == null) return null; - return new TexturedCharacterGlyph(new CharacterGlyph(character, 0, 0, texture.Width, null), texture, 1f / texture.ScaleAdjust); + return new TexturedCharacterGlyph(new CharacterGlyph(character, 0, 0, texture.Width, texture.Height, null), texture, 1f / texture.ScaleAdjust); } private static string getLookupName(char character) From f9af24df23e88659793eb629ab13be689dfb3d5f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Sep 2021 15:22:27 +0900 Subject: [PATCH 047/109] Fix mania hitobject tests --- .../Skinning/ManiaHitObjectTestScene.cs | 4 +-- .../Skinning/ManiaSkinnableTestScene.cs | 25 ++----------------- 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs index b7d7af6b8c..68cf3b67df 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning { c.Add(CreateHitObject().With(h => { - h.HitObject.StartTime = START_TIME; + h.HitObject.StartTime = Time.Current + 5000; h.AccentColour.Value = Color4.Orange; })); }) @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning { c.Add(CreateHitObject().With(h => { - h.HitObject.StartTime = START_TIME; + h.HitObject.StartTime = Time.Current + 5000; h.AccentColour.Value = Color4.Orange; })); }) diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs index 1d84a2dfcb..ddfd057cd8 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs @@ -19,8 +19,6 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning /// public abstract class ManiaSkinnableTestScene : SkinnableTestScene { - protected const double START_TIME = 1000000000; - [Cached(Type = typeof(IScrollingInfo))] private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo(); @@ -55,27 +53,8 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning public readonly Bindable Direction = new Bindable(); IBindable IScrollingInfo.Direction => Direction; - IBindable IScrollingInfo.TimeRange { get; } = new Bindable(1000); - IScrollAlgorithm IScrollingInfo.Algorithm { get; } = new ZeroScrollAlgorithm(); - } - - private class ZeroScrollAlgorithm : IScrollAlgorithm - { - public double GetDisplayStartTime(double originTime, float offset, double timeRange, float scrollLength) - => double.MinValue; - - public float GetLength(double startTime, double endTime, double timeRange, float scrollLength) - => scrollLength; - - public float PositionAt(double time, double currentTime, double timeRange, float scrollLength) - => (float)((time - START_TIME) / timeRange) * scrollLength; - - public double TimeAt(float position, double currentTime, double timeRange, float scrollLength) - => 0; - - public void Reset() - { - } + IBindable IScrollingInfo.TimeRange { get; } = new Bindable(5000); + IScrollAlgorithm IScrollingInfo.Algorithm { get; } = new ConstantScrollAlgorithm(); } } } From 187c557ea8105dc1db329cdf6828bc2a79fc41dc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Aug 2021 02:21:45 +0900 Subject: [PATCH 048/109] Begin migrating settings implementation across to realm --- osu.Game/Configuration/RealmSetting.cs | 33 +++++++++++++++++++++++++ osu.Game/Configuration/SettingsStore.cs | 25 ++++++++++--------- osu.Game/OsuGameBase.cs | 4 +-- osu.Game/Rulesets/RulesetConfigCache.cs | 4 +-- 4 files changed, 50 insertions(+), 16 deletions(-) create mode 100644 osu.Game/Configuration/RealmSetting.cs diff --git a/osu.Game/Configuration/RealmSetting.cs b/osu.Game/Configuration/RealmSetting.cs new file mode 100644 index 0000000000..b773796067 --- /dev/null +++ b/osu.Game/Configuration/RealmSetting.cs @@ -0,0 +1,33 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Game.Database; +using Realms; + +namespace osu.Game.Configuration +{ + [MapTo(@"Setting")] + public class RealmSetting : RealmObject, IHasGuidPrimaryKey + { + [PrimaryKey] + public Guid ID { get; set; } = Guid.NewGuid(); + + public int? RulesetID { get; set; } + + public int? Variant { get; set; } + + public string Key { get; set; } + + [MapTo(nameof(Value))] + public string ValueString { get; set; } + + public object Value + { + get => ValueString; + set => ValueString = value.ToString(); + } + + public override string ToString() => $"{Key}=>{Value}"; + } +} diff --git a/osu.Game/Configuration/SettingsStore.cs b/osu.Game/Configuration/SettingsStore.cs index 86e84b0732..864fa3cf53 100644 --- a/osu.Game/Configuration/SettingsStore.cs +++ b/osu.Game/Configuration/SettingsStore.cs @@ -1,31 +1,34 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using System.Linq; using osu.Game.Database; +using Realms; namespace osu.Game.Configuration { - public class SettingsStore : DatabaseBackedStore + public class RealmSettingsStore { - public event Action SettingChanged; + private readonly RealmContextFactory realmFactory; - public SettingsStore(DatabaseContextFactory contextFactory) - : base(contextFactory) + public RealmSettingsStore(RealmContextFactory realmFactory) { + this.realmFactory = realmFactory; } /// - /// Retrieve s for a specified ruleset/variant content. + /// Retrieve s for a specified ruleset/variant content. /// /// The ruleset's internal ID. /// An optional variant. - public List Query(int? rulesetId = null, int? variant = null) => - ContextFactory.Get().DatabasedSetting.Where(b => b.RulesetID == rulesetId && b.Variant == variant).ToList(); + public List Query(int? rulesetId = null, int? variant = null) + { + using (var context = realmFactory.GetForRead()) + return context.Realm.All().Where(b => b.RulesetID == rulesetId && b.Variant == variant).ToList(); + } - public void Update(DatabasedSetting setting) + public void Update(RealmSetting setting) { using (ContextFactory.GetForWrite()) { @@ -33,11 +36,9 @@ namespace osu.Game.Configuration Refresh(ref setting); setting.Value = newValue; } - - SettingChanged?.Invoke(); } - public void Delete(DatabasedSetting setting) + public void Delete(RealmSetting setting) { using (var usage = ContextFactory.GetForWrite()) usage.Context.Remove(setting); diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index f4db0f2603..12f53df6e8 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -140,7 +140,7 @@ namespace osu.Game private FileStore fileStore; - private SettingsStore settingsStore; + private RealmSettingsStore settingsStore; private RulesetConfigCache rulesetConfigCache; @@ -279,7 +279,7 @@ namespace osu.Game migrateDataToRealm(); - dependencies.Cache(settingsStore = new SettingsStore(contextFactory)); + dependencies.Cache(settingsStore = new RealmSettingsStore(realmFactory)); dependencies.Cache(rulesetConfigCache = new RulesetConfigCache(settingsStore)); var powerStatus = CreateBatteryInfo(); diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index d42428638c..885fa249df 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -16,9 +16,9 @@ namespace osu.Game.Rulesets public class RulesetConfigCache : Component { private readonly ConcurrentDictionary configCache = new ConcurrentDictionary(); - private readonly SettingsStore settingsStore; + private readonly RealmSettingsStore settingsStore; - public RulesetConfigCache(SettingsStore settingsStore) + public RulesetConfigCache(RealmSettingsStore settingsStore) { this.settingsStore = settingsStore; } From 14314476f07ab0271ac49fbfa8a557d838676b04 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Sep 2021 20:57:19 +0900 Subject: [PATCH 049/109] Update realm to latest version --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 941656bb70..5a302c5349 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -35,7 +35,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + From a2f1752344061e1f9ae4f7a4679f872de90feeaf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Sep 2021 14:39:47 +0900 Subject: [PATCH 050/109] Make settings works with current caching structure Will likely pull out that `RulesetConfigCache` next, but this is an "everything works" state. --- .../ManiaRulesetConfigManager.cs | 6 +- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 4 +- .../Configuration/OsuRulesetConfigManager.cs | 6 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 40 ++++++------- .../Testing/TestSceneRulesetDependencies.cs | 4 +- .../Configuration/DatabasedConfigManager.cs | 59 ++++++------------- osu.Game/Configuration/SettingsStore.cs | 21 +------ osu.Game/OsuGameBase.cs | 5 +- .../Settings/RulesetSettingsSubsection.cs | 4 +- .../Configuration/RulesetConfigManager.cs | 5 +- osu.Game/Rulesets/Ruleset.cs | 34 +++++------ osu.Game/Rulesets/RulesetConfigCache.cs | 34 ++++++++--- 12 files changed, 101 insertions(+), 121 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs index ac8168dfc9..d9bd0ab609 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Configuration.Tracking; -using osu.Game.Configuration; +using osu.Game.Database; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Mania.UI; @@ -11,8 +11,8 @@ namespace osu.Game.Rulesets.Mania.Configuration { public class ManiaRulesetConfigManager : RulesetConfigManager { - public ManiaRulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) - : base(settings, ruleset, variant) + public ManiaRulesetConfigManager(RealmContextFactory realmFactory, RulesetInfo ruleset, int? variant = null) + : base(realmFactory, ruleset, variant) { } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 1f79dae280..7ad27b94eb 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -17,7 +17,7 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; -using osu.Game.Configuration; +using osu.Game.Database; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; @@ -278,7 +278,7 @@ namespace osu.Game.Rulesets.Mania public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new ManiaReplayFrame(); - public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new ManiaRulesetConfigManager(settings, RulesetInfo); + public override IRulesetConfigManager CreateConfig(RealmContextFactory realmFactory) => new ManiaRulesetConfigManager(realmFactory, RulesetInfo); public override RulesetSettingsSubsection CreateSettings() => new ManiaSettingsSubsection(this); diff --git a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs index 9589fd576f..23c25c6558 100644 --- a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Configuration; +using osu.Game.Database; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.UI; @@ -9,8 +9,8 @@ namespace osu.Game.Rulesets.Osu.Configuration { public class OsuRulesetConfigManager : RulesetConfigManager { - public OsuRulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) - : base(settings, ruleset, variant) + public OsuRulesetConfigManager(RealmContextFactory realmFactory, RulesetInfo ruleset, int? variant = null) + : base(realmFactory, ruleset, variant) { } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index f4a93a571d..b7cb0c5313 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -1,41 +1,41 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Osu.Mods; -using osu.Game.Rulesets.Osu.UI; -using osu.Game.Rulesets.UI; +using System; using System.Collections.Generic; +using System.Linq; +using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Game.Overlays.Settings; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.Osu.Edit; -using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Osu.Replays; -using osu.Game.Rulesets.Replays.Types; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; -using osu.Game.Configuration; +using osu.Game.Database; +using osu.Game.Graphics; +using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Difficulty; -using osu.Game.Rulesets.Osu.Scoring; -using osu.Game.Rulesets.Scoring; -using osu.Game.Scoring; -using osu.Game.Skinning; -using System; -using System.Linq; -using osu.Framework.Extensions.EnumExtensions; +using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Edit.Setup; +using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Replays; +using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Osu.Skinning.Legacy; using osu.Game.Rulesets.Osu.Statistics; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.Replays.Types; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; +using osu.Game.Scoring; using osu.Game.Screens.Edit.Setup; using osu.Game.Screens.Ranking.Statistics; +using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu { @@ -229,7 +229,7 @@ namespace osu.Game.Rulesets.Osu public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new OsuReplayFrame(); - public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new OsuRulesetConfigManager(settings, RulesetInfo); + public override IRulesetConfigManager CreateConfig(RealmContextFactory realmFactory) => new OsuRulesetConfigManager(realmFactory, RulesetInfo); protected override IEnumerable GetValidHitResults() { diff --git a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs index 8c6932e792..12960fd4d0 100644 --- a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs +++ b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; using osu.Framework.Testing; using osu.Game.Beatmaps; -using osu.Game.Configuration; +using osu.Game.Database; using osu.Game.Rulesets; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; @@ -74,7 +74,7 @@ namespace osu.Game.Tests.Testing } public override IResourceStore CreateResourceStore() => new NamespacedResourceStore(TestResources.GetStore(), @"Resources"); - public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new TestRulesetConfigManager(); + public override IRulesetConfigManager CreateConfig(RealmContextFactory realmFactory) => new TestRulesetConfigManager(); public override IEnumerable GetModsFor(ModType type) => Array.Empty(); public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => null; diff --git a/osu.Game/Configuration/DatabasedConfigManager.cs b/osu.Game/Configuration/DatabasedConfigManager.cs index b3783b45a8..0514d11e24 100644 --- a/osu.Game/Configuration/DatabasedConfigManager.cs +++ b/osu.Game/Configuration/DatabasedConfigManager.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Configuration; +using osu.Game.Database; using osu.Game.Rulesets; namespace osu.Game.Configuration @@ -13,19 +14,17 @@ namespace osu.Game.Configuration public abstract class DatabasedConfigManager : ConfigManager where TLookup : struct, Enum { - private readonly SettingsStore settings; + private readonly RealmContextFactory realmFactory; private readonly int? variant; - private List databasedSettings; + private List databasedSettings; private readonly RulesetInfo ruleset; - private bool legacySettingsExist; - - protected DatabasedConfigManager(SettingsStore settings, RulesetInfo ruleset = null, int? variant = null) + protected DatabasedConfigManager(RealmContextFactory realmFactory, RulesetInfo ruleset = null, int? variant = null) { - this.settings = settings; + this.realmFactory = realmFactory; this.ruleset = ruleset; this.variant = variant; @@ -36,39 +35,22 @@ namespace osu.Game.Configuration protected override void PerformLoad() { - databasedSettings = settings.Query(ruleset?.ID, variant); - legacySettingsExist = databasedSettings.Any(s => int.TryParse(s.Key, out _)); + var rulesetID = ruleset?.ID; + + // As long as RulesetConfigCache exists, there is no need to subscribe to realm events. + databasedSettings = realmFactory.Context.All().Where(b => b.RulesetID == rulesetID && b.Variant == variant).ToList(); } protected override bool PerformSave() { - lock (dirtySettings) - { - foreach (var setting in dirtySettings) - settings.Update(setting); - dirtySettings.Clear(); - } - + // do nothing, realm saves immediately return true; } - private readonly List dirtySettings = new List(); - protected override void AddBindable(TLookup lookup, Bindable bindable) { base.AddBindable(lookup, bindable); - if (legacySettingsExist) - { - var legacySetting = databasedSettings.Find(s => s.Key == ((int)(object)lookup).ToString()); - - if (legacySetting != null) - { - bindable.Parse(legacySetting.Value); - settings.Delete(legacySetting); - } - } - var setting = databasedSettings.Find(s => s.Key == lookup.ToString()); if (setting != null) @@ -77,12 +59,15 @@ namespace osu.Game.Configuration } else { - settings.Update(setting = new DatabasedSetting + realmFactory.Context.Write(() => { - Key = lookup.ToString(), - Value = bindable.Value, - RulesetID = ruleset?.ID, - Variant = variant, + realmFactory.Context.Add(setting = new RealmSetting + { + Key = lookup.ToString(), + Value = bindable.Value, + RulesetID = ruleset?.ID, + Variant = variant, + }); }); databasedSettings.Add(setting); @@ -90,13 +75,7 @@ namespace osu.Game.Configuration bindable.ValueChanged += b => { - setting.Value = b.NewValue; - - lock (dirtySettings) - { - if (!dirtySettings.Contains(setting)) - dirtySettings.Add(setting); - } + realmFactory.Context.Write(() => setting.Value = b.NewValue); }; } } diff --git a/osu.Game/Configuration/SettingsStore.cs b/osu.Game/Configuration/SettingsStore.cs index 864fa3cf53..49775927b1 100644 --- a/osu.Game/Configuration/SettingsStore.cs +++ b/osu.Game/Configuration/SettingsStore.cs @@ -4,15 +4,14 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Database; -using Realms; namespace osu.Game.Configuration { - public class RealmSettingsStore + public class SettingsStore { private readonly RealmContextFactory realmFactory; - public RealmSettingsStore(RealmContextFactory realmFactory) + public SettingsStore(RealmContextFactory realmFactory) { this.realmFactory = realmFactory; } @@ -27,21 +26,5 @@ namespace osu.Game.Configuration using (var context = realmFactory.GetForRead()) return context.Realm.All().Where(b => b.RulesetID == rulesetId && b.Variant == variant).ToList(); } - - public void Update(RealmSetting setting) - { - using (ContextFactory.GetForWrite()) - { - var newValue = setting.Value; - Refresh(ref setting); - setting.Value = newValue; - } - } - - public void Delete(RealmSetting setting) - { - using (var usage = ContextFactory.GetForWrite()) - usage.Context.Remove(setting); - } } } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 12f53df6e8..600465b823 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -140,8 +140,6 @@ namespace osu.Game private FileStore fileStore; - private RealmSettingsStore settingsStore; - private RulesetConfigCache rulesetConfigCache; private SpectatorClient spectatorClient; @@ -279,8 +277,7 @@ namespace osu.Game migrateDataToRealm(); - dependencies.Cache(settingsStore = new RealmSettingsStore(realmFactory)); - dependencies.Cache(rulesetConfigCache = new RulesetConfigCache(settingsStore)); + dependencies.Cache(rulesetConfigCache = new RulesetConfigCache(realmFactory, RulesetStore)); var powerStatus = CreateBatteryInfo(); if (powerStatus != null) diff --git a/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs b/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs index 93b07fbac7..9ff5b8935a 100644 --- a/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Game.Configuration; +using osu.Game.Database; using osu.Game.Rulesets; using osu.Game.Rulesets.Configuration; @@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Settings { /// /// A which provides subclasses with the - /// from the 's . + /// from the 's . /// public abstract class RulesetSettingsSubsection : SettingsSubsection { diff --git a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs index 0ff3455f00..17dbd30103 100644 --- a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs @@ -3,14 +3,15 @@ using System; using osu.Game.Configuration; +using osu.Game.Database; namespace osu.Game.Rulesets.Configuration { public abstract class RulesetConfigManager : DatabasedConfigManager, IRulesetConfigManager where TLookup : struct, Enum { - protected RulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) - : base(settings, ruleset, variant) + protected RulesetConfigManager(RealmContextFactory realmFactory, RulesetInfo ruleset, int? variant = null) + : base(realmFactory, ruleset, variant) { } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index b0c3836774..cf4ea4f01d 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -5,32 +5,32 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; +using osu.Framework.Extensions; +using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; using osu.Framework.IO.Stores; +using osu.Framework.Testing; using osu.Game.Beatmaps; -using osu.Game.Overlays.Settings; -using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Replays.Types; -using osu.Game.Rulesets.UI; using osu.Game.Beatmaps.Legacy; -using osu.Game.Configuration; +using osu.Game.Database; +using osu.Game.Extensions; +using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Scoring; -using osu.Game.Scoring; -using osu.Game.Skinning; -using osu.Game.Users; -using JetBrains.Annotations; -using osu.Framework.Extensions; -using osu.Framework.Extensions.EnumExtensions; -using osu.Framework.Testing; -using osu.Game.Extensions; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Filter; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Replays.Types; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; +using osu.Game.Scoring; using osu.Game.Screens.Edit.Setup; using osu.Game.Screens.Ranking.Statistics; +using osu.Game.Skinning; +using osu.Game.Users; namespace osu.Game.Rulesets { @@ -262,8 +262,8 @@ namespace osu.Game.Rulesets /// /// Creates the for this . /// - /// The to store the settings. - public virtual IRulesetConfigManager CreateConfig(SettingsStore settings) => null; + /// The to store the settings. + public virtual IRulesetConfigManager CreateConfig(RealmContextFactory realmFactory) => null; /// /// A unique short name to reference this ruleset in online requests. diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index 885fa249df..afdf3219df 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -2,9 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Concurrent; +using System.Collections.Generic; using osu.Framework.Graphics; -using osu.Game.Configuration; +using osu.Game.Database; using osu.Game.Rulesets.Configuration; namespace osu.Game.Rulesets @@ -15,12 +15,29 @@ namespace osu.Game.Rulesets /// public class RulesetConfigCache : Component { - private readonly ConcurrentDictionary configCache = new ConcurrentDictionary(); - private readonly RealmSettingsStore settingsStore; + private readonly RealmContextFactory realmFactory; + private readonly RulesetStore rulesets; - public RulesetConfigCache(RealmSettingsStore settingsStore) + private readonly Dictionary configCache = new Dictionary(); + + public RulesetConfigCache(RealmContextFactory realmFactory, RulesetStore rulesets) { - this.settingsStore = settingsStore; + this.realmFactory = realmFactory; + this.rulesets = rulesets; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + // let's keep things simple for now and just retrieve all the required configs at startup.. + foreach (var ruleset in rulesets.AvailableRulesets) + { + if (ruleset.ID == null) + continue; + + configCache[ruleset.ID.Value] = ruleset.CreateInstance().CreateConfig(realmFactory); + } } /// @@ -34,7 +51,10 @@ namespace osu.Game.Rulesets if (ruleset.RulesetInfo.ID == null) return null; - return configCache.GetOrAdd(ruleset.RulesetInfo.ID.Value, _ => ruleset.CreateConfig(settingsStore)); + if (!configCache.TryGetValue(ruleset.RulesetInfo.ID.Value, out var config)) + return null; + + return config; } protected override void Dispose(bool isDisposing) From ac377a2e3c39235fa18b4be85b90b744b174a2cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Sep 2021 14:56:40 +0900 Subject: [PATCH 051/109] Remove unused `SettingsStore` --- .../Visual/Navigation/TestSceneOsuGame.cs | 1 - osu.Game/Configuration/SettingsStore.cs | 30 ------------------- 2 files changed, 31 deletions(-) delete mode 100644 osu.Game/Configuration/SettingsStore.cs diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs index b8232837b5..43459408d5 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs @@ -75,7 +75,6 @@ namespace osu.Game.Tests.Visual.Navigation typeof(FileStore), typeof(ScoreManager), typeof(BeatmapManager), - typeof(SettingsStore), typeof(RulesetConfigCache), typeof(OsuColour), typeof(IBindable), diff --git a/osu.Game/Configuration/SettingsStore.cs b/osu.Game/Configuration/SettingsStore.cs deleted file mode 100644 index 49775927b1..0000000000 --- a/osu.Game/Configuration/SettingsStore.cs +++ /dev/null @@ -1,30 +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 System.Collections.Generic; -using System.Linq; -using osu.Game.Database; - -namespace osu.Game.Configuration -{ - public class SettingsStore - { - private readonly RealmContextFactory realmFactory; - - public SettingsStore(RealmContextFactory realmFactory) - { - this.realmFactory = realmFactory; - } - - /// - /// Retrieve s for a specified ruleset/variant content. - /// - /// The ruleset's internal ID. - /// An optional variant. - public List Query(int? rulesetId = null, int? variant = null) - { - using (var context = realmFactory.GetForRead()) - return context.Realm.All().Where(b => b.RulesetID == rulesetId && b.Variant == variant).ToList(); - } - } -} From 2bcb3fd304ad8ca70bc1b998239ee10f70b94b1f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Sep 2021 15:22:16 +0900 Subject: [PATCH 052/109] Add migration of existing settings --- osu.Game/OsuGameBase.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 600465b823..489d5b5e51 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -469,6 +469,25 @@ namespace osu.Game db.Context.RemoveRange(existingBindings); + var existingSettings = db.Context.DatabasedSetting; + + // only migrate data if the realm database is empty. + if (!usage.Realm.All().Any()) + { + foreach (var dkb in existingSettings) + { + usage.Realm.Add(new RealmSetting + { + ValueString = dkb.StringValue, + Key = dkb.Key, + RulesetID = dkb.RulesetID, + Variant = dkb.Variant + }); + } + } + + db.Context.RemoveRange(existingSettings); + usage.Commit(); } } From b87af3dd68e3de7b19483210e6d94437a6a6c651 Mon Sep 17 00:00:00 2001 From: AbstractQbit <38468635+AbstractQbit@users.noreply.github.com> Date: Wed, 15 Sep 2021 10:55:16 +0300 Subject: [PATCH 053/109] Move the inherited `AllowTrackAdjustments` into `OsuScreen` --- osu.Game/OsuGame.cs | 21 +++++---------------- osu.Game/Screens/IOsuScreen.cs | 2 +- osu.Game/Screens/OsuScreen.cs | 8 +++++++- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 499b561718..f2f925a778 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1075,6 +1075,11 @@ namespace osu.Game OverlayActivationMode.BindTo(newOsuScreen.OverlayActivationMode); API.Activity.BindTo(newOsuScreen.Activity); + if (newOsuScreen.AllowTrackAdjustments.HasValue) + MusicController.AllowTrackAdjustments = newOsuScreen.AllowTrackAdjustments.Value; + else + newOsuScreen.AllowTrackAdjustments = MusicController.AllowTrackAdjustments; + if (newOsuScreen.HideOverlaysOnEnter) CloseAllOverlays(); else @@ -1091,16 +1096,6 @@ namespace osu.Game { ScreenChanged(lastScreen, newScreen); Logger.Log($"Screen changed → {newScreen}"); - - // set AllowTrackAdjustments if new screen defines it, inherit otherwise - if (newScreen is IOsuScreen newOsuScreen && newOsuScreen.AllowTrackAdjustments.HasValue) - allowTrackAdjustmentsDict[newScreen] = newOsuScreen.AllowTrackAdjustments.Value; - else if (allowTrackAdjustmentsDict.ContainsKey(lastScreen)) - allowTrackAdjustmentsDict[newScreen] = allowTrackAdjustmentsDict[lastScreen]; - else - allowTrackAdjustmentsDict[newScreen] = true; - - MusicController.AllowTrackAdjustments = allowTrackAdjustmentsDict[newScreen]; } private void screenExited(IScreen lastScreen, IScreen newScreen) @@ -1108,16 +1103,10 @@ namespace osu.Game ScreenChanged(lastScreen, newScreen); Logger.Log($"Screen changed ← {newScreen}"); - allowTrackAdjustmentsDict.Remove(lastScreen); - if (newScreen == null) Exit(); - else - MusicController.AllowTrackAdjustments = allowTrackAdjustmentsDict[newScreen]; } - private readonly Dictionary allowTrackAdjustmentsDict = new Dictionary(); - IBindable ILocalUserPlayInfo.IsPlaying => LocalUserPlaying; } } diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index a1e4d9ed01..262bbfedc6 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -62,7 +62,7 @@ namespace osu.Game.Screens /// Whether mod track adjustments are allowed to be applied. /// Null means to inherit from the parent screen. /// - bool? AllowTrackAdjustments { get; } + bool? AllowTrackAdjustments { set; get; } /// /// Invoked when the back button has been pressed to close any overlays before exiting this . diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 78908b5d8a..0deaa3e80e 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -81,7 +81,13 @@ namespace osu.Game.Screens public virtual float BackgroundParallaxAmount => 1; - public virtual bool? AllowTrackAdjustments => null; + private bool? allowTrackAdjustments = null; + + public virtual bool? AllowTrackAdjustments + { + set => allowTrackAdjustments = value; + get => allowTrackAdjustments; + } public Bindable Beatmap { get; private set; } From 48cf98ef9325cfd40fca7ab91bb50cc102517c53 Mon Sep 17 00:00:00 2001 From: AbstractQbit <38468635+AbstractQbit@users.noreply.github.com> Date: Wed, 15 Sep 2021 11:00:49 +0300 Subject: [PATCH 054/109] Rephrase null meaning in `IOsuScreen.AllowTrackAdjustments` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Screens/IOsuScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index 262bbfedc6..735853e462 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -60,7 +60,7 @@ namespace osu.Game.Screens /// /// Whether mod track adjustments are allowed to be applied. - /// Null means to inherit from the parent screen. + /// A value means that the parent screen's value of this setting will be used. /// bool? AllowTrackAdjustments { set; get; } From f54d554d3099ecf845573bbcb9bda1c4250edc3c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Sep 2021 17:03:26 +0900 Subject: [PATCH 055/109] Extract removal to method --- osu.Game/Online/Rooms/Room.cs | 15 ++++++++++----- .../Components/ListingPollingComponent.cs | 4 +--- .../Components/SelectionPollingComponent.cs | 4 +--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index d964060f10..5f71b4be4a 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -179,11 +179,7 @@ namespace osu.Game.Online.Rooms if (EndDate.Value != null && DateTimeOffset.Now >= EndDate.Value) Status.Value = new RoomStatusEnded(); - // Todo: This is not the best way/place to do this, but the intention is to display all playlist items when the room has ended, - // and display only the non-expired playlist items while the room is still active. In order to achieve this, all expired items are removed from the source Room. - // More refactoring is required before this can be done locally instead - DrawableRoomPlaylist is currently directly bound to the playlist to display items in the room. - if (!(Status.Value is RoomStatusEnded)) - other.Playlist.RemoveAll(i => i.Expired); + other.RemoveExpiredPlaylistItems(); if (!Playlist.SequenceEqual(other.Playlist)) { @@ -200,6 +196,15 @@ namespace osu.Game.Online.Rooms Position.Value = other.Position.Value; } + public void RemoveExpiredPlaylistItems() + { + // Todo: This is not the best way/place to do this, but the intention is to display all playlist items when the room has ended, + // and display only the non-expired playlist items while the room is still active. In order to achieve this, all expired items are removed from the source Room. + // More refactoring is required before this can be done locally instead - DrawableRoomPlaylist is currently directly bound to the playlist to display items in the room. + if (!(Status.Value is RoomStatusEnded)) + Playlist.RemoveAll(i => i.Expired); + } + public bool ShouldSerializeRoomID() => false; public bool ShouldSerializeHost() => false; public bool ShouldSerializeEndDate() => false; diff --git a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs index 5a74df6ab1..fcf7767958 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs @@ -58,9 +58,7 @@ namespace osu.Game.Screens.OnlinePlay.Components foreach (var incoming in result) { - // Copy the room to itself to populate some members (such as status and playlist expiry). - incoming.CopyFrom(incoming); - + incoming.RemoveExpiredPlaylistItems(); RoomManager.AddOrUpdateRoom(incoming); } diff --git a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs index 0a37d47e34..b9d2bdf23e 100644 --- a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs @@ -39,9 +39,7 @@ namespace osu.Game.Screens.OnlinePlay.Components pollReq.Success += result => { - // Copy the room to itself to populate some members (such as status and playlist expiry). - result.CopyFrom(result); - + result.RemoveExpiredPlaylistItems(); RoomManager.AddOrUpdateRoom(result); tcs.SetResult(true); }; From 5bb741b4e8126327e9fd4ccd76c76142f8fab39a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Sep 2021 15:22:43 +0900 Subject: [PATCH 056/109] Remove migration of key bindings --- osu.Game/Database/OsuDbContext.cs | 9 +---- .../Input/Bindings/DatabasedKeyBinding.cs | 39 ------------------- osu.Game/OsuGameBase.cs | 20 +--------- 3 files changed, 2 insertions(+), 66 deletions(-) delete mode 100644 osu.Game/Input/Bindings/DatabasedKeyBinding.cs diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 68d186c65d..1d8322aadd 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -12,7 +12,6 @@ using osu.Game.Configuration; using osu.Game.IO; using osu.Game.Rulesets; using osu.Game.Scoring; -using DatabasedKeyBinding = osu.Game.Input.Bindings.DatabasedKeyBinding; using LogLevel = Microsoft.Extensions.Logging.LogLevel; using osu.Game.Skinning; @@ -24,14 +23,13 @@ namespace osu.Game.Database public DbSet BeatmapDifficulty { get; set; } public DbSet BeatmapMetadata { get; set; } public DbSet BeatmapSetInfo { get; set; } - public DbSet DatabasedSetting { get; set; } public DbSet FileInfo { get; set; } public DbSet RulesetInfo { get; set; } public DbSet SkinInfo { get; set; } public DbSet ScoreInfo { get; set; } // migrated to realm - public DbSet DatabasedKeyBinding { get; set; } + public DbSet DatabasedSetting { get; set; } private readonly string connectionString; @@ -138,11 +136,6 @@ namespace osu.Game.Database modelBuilder.Entity().HasIndex(b => b.Hash).IsUnique(); modelBuilder.Entity().HasIndex(b => b.DeletePending); - modelBuilder.Entity().HasIndex(b => new { b.RulesetID, b.Variant }); - modelBuilder.Entity().HasIndex(b => b.IntAction); - modelBuilder.Entity().Ignore(b => b.KeyCombination); - modelBuilder.Entity().Ignore(b => b.Action); - modelBuilder.Entity().HasIndex(b => new { b.RulesetID, b.Variant }); modelBuilder.Entity().HasIndex(b => b.Hash).IsUnique(); diff --git a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs deleted file mode 100644 index ad3493d0fc..0000000000 --- a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs +++ /dev/null @@ -1,39 +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 System.ComponentModel.DataAnnotations.Schema; -using osu.Framework.Input.Bindings; -using osu.Game.Database; - -namespace osu.Game.Input.Bindings -{ - [Table("KeyBinding")] - public class DatabasedKeyBinding : IKeyBinding, IHasPrimaryKey - { - public int ID { get; set; } - - public int? RulesetID { get; set; } - - public int? Variant { get; set; } - - [Column("Keys")] - public string KeysString { get; set; } - - [Column("Action")] - public int IntAction { get; set; } - - [NotMapped] - public KeyCombination KeyCombination - { - get => KeysString; - set => KeysString = value.ToString(); - } - - [NotMapped] - public object Action - { - get => IntAction; - set => IntAction = (int)value; - } - } -} diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 489d5b5e51..ee97b27265 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -450,25 +450,7 @@ namespace osu.Game using (var db = contextFactory.GetForWrite()) using (var usage = realmFactory.GetForWrite()) { - var existingBindings = db.Context.DatabasedKeyBinding; - - // only migrate data if the realm database is empty. - if (!usage.Realm.All().Any()) - { - foreach (var dkb in existingBindings) - { - usage.Realm.Add(new RealmKeyBinding - { - KeyCombinationString = dkb.KeyCombination.ToString(), - ActionInt = (int)dkb.Action, - RulesetID = dkb.RulesetID, - Variant = dkb.Variant - }); - } - } - - db.Context.RemoveRange(existingBindings); - + // migrate ruleset settings. can be removed 20220315. var existingSettings = db.Context.DatabasedSetting; // only migrate data if the realm database is empty. From c36a67d06e718d7e5d05730c7110cb141d2e8ecb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Sep 2021 15:01:48 +0900 Subject: [PATCH 057/109] Fix some tests failing due to using a locally constructed ruleset --- osu.Game/Rulesets/RulesetConfigCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index afdf3219df..f2c3121320 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -52,7 +52,7 @@ namespace osu.Game.Rulesets return null; if (!configCache.TryGetValue(ruleset.RulesetInfo.ID.Value, out var config)) - return null; + return ruleset.CreateConfig(realmFactory); return config; } From 520e5507645fe640073c25c9fc9e62e768a8ea80 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Sep 2021 16:08:31 +0900 Subject: [PATCH 058/109] Bring back `SettingsStore` to avoid changing ruleset API for now Also fixes some remaining test failures due to locally constructed rulesets that are not being tracked by the game. --- .../ManiaRulesetConfigManager.cs | 6 +-- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 4 +- .../Configuration/OsuRulesetConfigManager.cs | 6 +-- osu.Game.Rulesets.Osu/OsuRuleset.cs | 44 +++++++++---------- .../Testing/TestSceneRulesetDependencies.cs | 4 +- .../Configuration/DatabasedConfigManager.cs | 32 +++++++------- osu.Game/Configuration/SettingsStore.cs | 20 +++++++++ .../Settings/RulesetSettingsSubsection.cs | 4 +- .../Configuration/RulesetConfigManager.cs | 5 +-- osu.Game/Rulesets/Ruleset.cs | 30 ++++++------- osu.Game/Rulesets/RulesetConfigCache.cs | 9 +++- 11 files changed, 95 insertions(+), 69 deletions(-) create mode 100644 osu.Game/Configuration/SettingsStore.cs diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs index d9bd0ab609..ac8168dfc9 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Configuration.Tracking; -using osu.Game.Database; +using osu.Game.Configuration; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Mania.UI; @@ -11,8 +11,8 @@ namespace osu.Game.Rulesets.Mania.Configuration { public class ManiaRulesetConfigManager : RulesetConfigManager { - public ManiaRulesetConfigManager(RealmContextFactory realmFactory, RulesetInfo ruleset, int? variant = null) - : base(realmFactory, ruleset, variant) + public ManiaRulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) + : base(settings, ruleset, variant) { } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 7ad27b94eb..1f79dae280 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -17,7 +17,7 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; -using osu.Game.Database; +using osu.Game.Configuration; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; @@ -278,7 +278,7 @@ namespace osu.Game.Rulesets.Mania public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new ManiaReplayFrame(); - public override IRulesetConfigManager CreateConfig(RealmContextFactory realmFactory) => new ManiaRulesetConfigManager(realmFactory, RulesetInfo); + public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new ManiaRulesetConfigManager(settings, RulesetInfo); public override RulesetSettingsSubsection CreateSettings() => new ManiaSettingsSubsection(this); diff --git a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs index 23c25c6558..9589fd576f 100644 --- a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Database; +using osu.Game.Configuration; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.UI; @@ -9,8 +9,8 @@ namespace osu.Game.Rulesets.Osu.Configuration { public class OsuRulesetConfigManager : RulesetConfigManager { - public OsuRulesetConfigManager(RealmContextFactory realmFactory, RulesetInfo ruleset, int? variant = null) - : base(realmFactory, ruleset, variant) + public OsuRulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) + : base(settings, ruleset, variant) { } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index b7cb0c5313..f4a93a571d 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -1,41 +1,41 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.UI; using System.Collections.Generic; -using System.Linq; -using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Bindings; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Legacy; -using osu.Game.Database; -using osu.Game.Graphics; using osu.Game.Overlays.Settings; +using osu.Framework.Input.Bindings; +using osu.Game.Rulesets.Osu.Edit; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Osu.Replays; +using osu.Game.Rulesets.Replays.Types; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Configuration; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Difficulty; -using osu.Game.Rulesets.Osu.Edit; -using osu.Game.Rulesets.Osu.Edit.Setup; -using osu.Game.Rulesets.Osu.Mods; -using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Osu.Scoring; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; +using osu.Game.Skinning; +using System; +using System.Linq; +using osu.Framework.Extensions.EnumExtensions; +using osu.Game.Rulesets.Osu.Edit.Setup; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Skinning.Legacy; using osu.Game.Rulesets.Osu.Statistics; -using osu.Game.Rulesets.Osu.UI; -using osu.Game.Rulesets.Replays.Types; -using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; -using osu.Game.Scoring; using osu.Game.Screens.Edit.Setup; using osu.Game.Screens.Ranking.Statistics; -using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu { @@ -229,7 +229,7 @@ namespace osu.Game.Rulesets.Osu public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new OsuReplayFrame(); - public override IRulesetConfigManager CreateConfig(RealmContextFactory realmFactory) => new OsuRulesetConfigManager(realmFactory, RulesetInfo); + public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new OsuRulesetConfigManager(settings, RulesetInfo); protected override IEnumerable GetValidHitResults() { diff --git a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs index 12960fd4d0..8c6932e792 100644 --- a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs +++ b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; using osu.Framework.Testing; using osu.Game.Beatmaps; -using osu.Game.Database; +using osu.Game.Configuration; using osu.Game.Rulesets; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; @@ -74,7 +74,7 @@ namespace osu.Game.Tests.Testing } public override IResourceStore CreateResourceStore() => new NamespacedResourceStore(TestResources.GetStore(), @"Resources"); - public override IRulesetConfigManager CreateConfig(RealmContextFactory realmFactory) => new TestRulesetConfigManager(); + public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new TestRulesetConfigManager(); public override IEnumerable GetModsFor(ModType type) => Array.Empty(); public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => null; diff --git a/osu.Game/Configuration/DatabasedConfigManager.cs b/osu.Game/Configuration/DatabasedConfigManager.cs index 0514d11e24..d6988e31b5 100644 --- a/osu.Game/Configuration/DatabasedConfigManager.cs +++ b/osu.Game/Configuration/DatabasedConfigManager.cs @@ -18,13 +18,13 @@ namespace osu.Game.Configuration private readonly int? variant; - private List databasedSettings; + private List databasedSettings = new List(); private readonly RulesetInfo ruleset; - protected DatabasedConfigManager(RealmContextFactory realmFactory, RulesetInfo ruleset = null, int? variant = null) + protected DatabasedConfigManager(SettingsStore store = null, RulesetInfo ruleset = null, int? variant = null) { - this.realmFactory = realmFactory; + realmFactory = store?.Realm; this.ruleset = ruleset; this.variant = variant; @@ -37,8 +37,11 @@ namespace osu.Game.Configuration { var rulesetID = ruleset?.ID; - // As long as RulesetConfigCache exists, there is no need to subscribe to realm events. - databasedSettings = realmFactory.Context.All().Where(b => b.RulesetID == rulesetID && b.Variant == variant).ToList(); + if (realmFactory != null) + { + // As long as RulesetConfigCache exists, there is no need to subscribe to realm events. + databasedSettings = realmFactory.Context.All().Where(b => b.RulesetID == rulesetID && b.Variant == variant).ToList(); + } } protected override bool PerformSave() @@ -59,23 +62,22 @@ namespace osu.Game.Configuration } else { - realmFactory.Context.Write(() => + setting = new RealmSetting { - realmFactory.Context.Add(setting = new RealmSetting - { - Key = lookup.ToString(), - Value = bindable.Value, - RulesetID = ruleset?.ID, - Variant = variant, - }); - }); + Key = lookup.ToString(), + Value = bindable.Value, + RulesetID = ruleset?.ID, + Variant = variant, + }; + + realmFactory?.Context.Write(() => realmFactory.Context.Add(setting)); databasedSettings.Add(setting); } bindable.ValueChanged += b => { - realmFactory.Context.Write(() => setting.Value = b.NewValue); + realmFactory?.Context.Write(() => setting.Value = b.NewValue); }; } } diff --git a/osu.Game/Configuration/SettingsStore.cs b/osu.Game/Configuration/SettingsStore.cs new file mode 100644 index 0000000000..2bba20fb09 --- /dev/null +++ b/osu.Game/Configuration/SettingsStore.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Database; + +namespace osu.Game.Configuration +{ + public class SettingsStore + { + // this class mostly exists as a wrapper to avoid breaking the ruleset API (see usage in RulesetConfigManager). + // it may cease to exist going forward, depending on how the structure of the config data layer changes. + + public readonly RealmContextFactory Realm; + + public SettingsStore(RealmContextFactory realmFactory) + { + Realm = realmFactory; + } + } +} diff --git a/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs b/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs index 9ff5b8935a..93b07fbac7 100644 --- a/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Game.Database; +using osu.Game.Configuration; using osu.Game.Rulesets; using osu.Game.Rulesets.Configuration; @@ -10,7 +10,7 @@ namespace osu.Game.Overlays.Settings { /// /// A which provides subclasses with the - /// from the 's . + /// from the 's . /// public abstract class RulesetSettingsSubsection : SettingsSubsection { diff --git a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs index 17dbd30103..0ff3455f00 100644 --- a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs @@ -3,15 +3,14 @@ using System; using osu.Game.Configuration; -using osu.Game.Database; namespace osu.Game.Rulesets.Configuration { public abstract class RulesetConfigManager : DatabasedConfigManager, IRulesetConfigManager where TLookup : struct, Enum { - protected RulesetConfigManager(RealmContextFactory realmFactory, RulesetInfo ruleset, int? variant = null) - : base(realmFactory, ruleset, variant) + protected RulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) + : base(settings, ruleset, variant) { } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index cf4ea4f01d..b0c3836774 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -5,32 +5,32 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; -using osu.Framework.Extensions; -using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; using osu.Framework.IO.Stores; -using osu.Framework.Testing; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Legacy; -using osu.Game.Database; -using osu.Game.Extensions; using osu.Game.Overlays.Settings; -using osu.Game.Rulesets.Configuration; -using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Filter; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Replays.Types; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Configuration; +using osu.Game.Rulesets.Configuration; +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; -using osu.Game.Screens.Edit.Setup; -using osu.Game.Screens.Ranking.Statistics; using osu.Game.Skinning; using osu.Game.Users; +using JetBrains.Annotations; +using osu.Framework.Extensions; +using osu.Framework.Extensions.EnumExtensions; +using osu.Framework.Testing; +using osu.Game.Extensions; +using osu.Game.Rulesets.Filter; +using osu.Game.Screens.Edit.Setup; +using osu.Game.Screens.Ranking.Statistics; namespace osu.Game.Rulesets { @@ -262,8 +262,8 @@ namespace osu.Game.Rulesets /// /// Creates the for this . /// - /// The to store the settings. - public virtual IRulesetConfigManager CreateConfig(RealmContextFactory realmFactory) => null; + /// The to store the settings. + public virtual IRulesetConfigManager CreateConfig(SettingsStore settings) => null; /// /// A unique short name to reference this ruleset in online requests. diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index f2c3121320..aeac052673 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics; +using osu.Game.Configuration; using osu.Game.Database; using osu.Game.Rulesets.Configuration; @@ -30,13 +31,15 @@ namespace osu.Game.Rulesets { base.LoadComplete(); + var settingsStore = new SettingsStore(realmFactory); + // let's keep things simple for now and just retrieve all the required configs at startup.. foreach (var ruleset in rulesets.AvailableRulesets) { if (ruleset.ID == null) continue; - configCache[ruleset.ID.Value] = ruleset.CreateInstance().CreateConfig(realmFactory); + configCache[ruleset.ID.Value] = ruleset.CreateInstance().CreateConfig(settingsStore); } } @@ -52,7 +55,9 @@ namespace osu.Game.Rulesets return null; if (!configCache.TryGetValue(ruleset.RulesetInfo.ID.Value, out var config)) - return ruleset.CreateConfig(realmFactory); + // any ruleset request which wasn't initialised on startup should not be stored to realm. + // this should only be used by tests. + return ruleset.CreateConfig(null); return config; } From 80ecf81be34ce87b350612b3932913e2556cbce8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Sep 2021 16:55:42 +0900 Subject: [PATCH 059/109] Rename all databased setting classes to be specific to rulesets for now --- .../Configuration/DatabasedConfigManager.cs | 84 ------------------- ...RealmSetting.cs => RealmRulesetSetting.cs} | 4 +- osu.Game/OsuGameBase.cs | 4 +- .../Configuration/RulesetConfigManager.cs | 73 +++++++++++++++- 4 files changed, 74 insertions(+), 91 deletions(-) delete mode 100644 osu.Game/Configuration/DatabasedConfigManager.cs rename osu.Game/Configuration/{RealmSetting.cs => RealmRulesetSetting.cs} (87%) diff --git a/osu.Game/Configuration/DatabasedConfigManager.cs b/osu.Game/Configuration/DatabasedConfigManager.cs deleted file mode 100644 index d6988e31b5..0000000000 --- a/osu.Game/Configuration/DatabasedConfigManager.cs +++ /dev/null @@ -1,84 +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 System; -using System.Collections.Generic; -using System.Linq; -using osu.Framework.Bindables; -using osu.Framework.Configuration; -using osu.Game.Database; -using osu.Game.Rulesets; - -namespace osu.Game.Configuration -{ - public abstract class DatabasedConfigManager : ConfigManager - where TLookup : struct, Enum - { - private readonly RealmContextFactory realmFactory; - - private readonly int? variant; - - private List databasedSettings = new List(); - - private readonly RulesetInfo ruleset; - - protected DatabasedConfigManager(SettingsStore store = null, RulesetInfo ruleset = null, int? variant = null) - { - realmFactory = store?.Realm; - this.ruleset = ruleset; - this.variant = variant; - - Load(); - - InitialiseDefaults(); - } - - protected override void PerformLoad() - { - var rulesetID = ruleset?.ID; - - if (realmFactory != null) - { - // As long as RulesetConfigCache exists, there is no need to subscribe to realm events. - databasedSettings = realmFactory.Context.All().Where(b => b.RulesetID == rulesetID && b.Variant == variant).ToList(); - } - } - - protected override bool PerformSave() - { - // do nothing, realm saves immediately - return true; - } - - protected override void AddBindable(TLookup lookup, Bindable bindable) - { - base.AddBindable(lookup, bindable); - - var setting = databasedSettings.Find(s => s.Key == lookup.ToString()); - - if (setting != null) - { - bindable.Parse(setting.Value); - } - else - { - setting = new RealmSetting - { - Key = lookup.ToString(), - Value = bindable.Value, - RulesetID = ruleset?.ID, - Variant = variant, - }; - - realmFactory?.Context.Write(() => realmFactory.Context.Add(setting)); - - databasedSettings.Add(setting); - } - - bindable.ValueChanged += b => - { - realmFactory?.Context.Write(() => setting.Value = b.NewValue); - }; - } - } -} diff --git a/osu.Game/Configuration/RealmSetting.cs b/osu.Game/Configuration/RealmRulesetSetting.cs similarity index 87% rename from osu.Game/Configuration/RealmSetting.cs rename to osu.Game/Configuration/RealmRulesetSetting.cs index b773796067..7623d1f948 100644 --- a/osu.Game/Configuration/RealmSetting.cs +++ b/osu.Game/Configuration/RealmRulesetSetting.cs @@ -7,8 +7,8 @@ using Realms; namespace osu.Game.Configuration { - [MapTo(@"Setting")] - public class RealmSetting : RealmObject, IHasGuidPrimaryKey + [MapTo(@"RulesetSetting")] + public class RealmRulesetSetting : RealmObject, IHasGuidPrimaryKey { [PrimaryKey] public Guid ID { get; set; } = Guid.NewGuid(); diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index ee97b27265..4e4061db9d 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -454,11 +454,11 @@ namespace osu.Game var existingSettings = db.Context.DatabasedSetting; // only migrate data if the realm database is empty. - if (!usage.Realm.All().Any()) + if (!usage.Realm.All().Any()) { foreach (var dkb in existingSettings) { - usage.Realm.Add(new RealmSetting + usage.Realm.Add(new RealmRulesetSetting { ValueString = dkb.StringValue, Key = dkb.Key, diff --git a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs index 0ff3455f00..3f5472e52c 100644 --- a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs @@ -2,16 +2,83 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Bindables; +using osu.Framework.Configuration; using osu.Game.Configuration; +using osu.Game.Database; namespace osu.Game.Rulesets.Configuration { - public abstract class RulesetConfigManager : DatabasedConfigManager, IRulesetConfigManager + public abstract class RulesetConfigManager : ConfigManager, IRulesetConfigManager where TLookup : struct, Enum { - protected RulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) - : base(settings, ruleset, variant) + private readonly RealmContextFactory realmFactory; + + private readonly int? variant; + + private List databasedSettings = new List(); + + private readonly RulesetInfo ruleset; + + protected RulesetConfigManager(SettingsStore store, RulesetInfo ruleset, int? variant = null) { + realmFactory = store?.Realm; + this.ruleset = ruleset; + this.variant = variant; + + Load(); + + InitialiseDefaults(); + } + + protected override void PerformLoad() + { + var rulesetID = ruleset?.ID; + + if (realmFactory != null) + { + // As long as RulesetConfigCache exists, there is no need to subscribe to realm events. + databasedSettings = realmFactory.Context.All().Where(b => b.RulesetID == rulesetID && b.Variant == variant).ToList(); + } + } + + protected override bool PerformSave() + { + // do nothing, realm saves immediately + return true; + } + + protected override void AddBindable(TLookup lookup, Bindable bindable) + { + base.AddBindable(lookup, bindable); + + var setting = databasedSettings.Find(s => s.Key == lookup.ToString()); + + if (setting != null) + { + bindable.Parse(setting.Value); + } + else + { + setting = new RealmRulesetSetting + { + Key = lookup.ToString(), + Value = bindable.Value, + RulesetID = ruleset?.ID, + Variant = variant, + }; + + realmFactory?.Context.Write(() => realmFactory.Context.Add(setting)); + + databasedSettings.Add(setting); + } + + bindable.ValueChanged += b => + { + realmFactory?.Context.Write(() => setting.Value = b.NewValue); + }; } } } From dcfe9c67e3019f91e5b92f1e433dae48d4c79843 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Sep 2021 17:01:31 +0900 Subject: [PATCH 060/109] Make ruleset id non-nullable --- osu.Game/Configuration/RealmRulesetSetting.cs | 3 ++- osu.Game/OsuGameBase.cs | 4 +++- .../Configuration/RulesetConfigManager.cs | 15 +++++++++------ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/osu.Game/Configuration/RealmRulesetSetting.cs b/osu.Game/Configuration/RealmRulesetSetting.cs index 7623d1f948..c88a261ad2 100644 --- a/osu.Game/Configuration/RealmRulesetSetting.cs +++ b/osu.Game/Configuration/RealmRulesetSetting.cs @@ -13,7 +13,8 @@ namespace osu.Game.Configuration [PrimaryKey] public Guid ID { get; set; } = Guid.NewGuid(); - public int? RulesetID { get; set; } + [Indexed] + public int RulesetID { get; set; } public int? Variant { get; set; } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 4e4061db9d..36406ded08 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -458,11 +458,13 @@ namespace osu.Game { foreach (var dkb in existingSettings) { + if (dkb.RulesetID == null) continue; + usage.Realm.Add(new RealmRulesetSetting { ValueString = dkb.StringValue, Key = dkb.Key, - RulesetID = dkb.RulesetID, + RulesetID = dkb.RulesetID.Value, Variant = dkb.Variant }); } diff --git a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs index 3f5472e52c..a97976392a 100644 --- a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs @@ -20,12 +20,17 @@ namespace osu.Game.Rulesets.Configuration private List databasedSettings = new List(); - private readonly RulesetInfo ruleset; + private readonly int rulesetId; protected RulesetConfigManager(SettingsStore store, RulesetInfo ruleset, int? variant = null) { realmFactory = store?.Realm; - this.ruleset = ruleset; + + if (realmFactory != null && !ruleset.ID.HasValue) + throw new InvalidOperationException("Attempted to add databased settings for a non-databased ruleset"); + + rulesetId = ruleset.ID ?? -1; + this.variant = variant; Load(); @@ -35,12 +40,10 @@ namespace osu.Game.Rulesets.Configuration protected override void PerformLoad() { - var rulesetID = ruleset?.ID; - if (realmFactory != null) { // As long as RulesetConfigCache exists, there is no need to subscribe to realm events. - databasedSettings = realmFactory.Context.All().Where(b => b.RulesetID == rulesetID && b.Variant == variant).ToList(); + databasedSettings = realmFactory.Context.All().Where(b => b.RulesetID == rulesetId && b.Variant == variant).ToList(); } } @@ -66,7 +69,7 @@ namespace osu.Game.Rulesets.Configuration { Key = lookup.ToString(), Value = bindable.Value, - RulesetID = ruleset?.ID, + RulesetID = rulesetId, Variant = variant, }; From 15e3f95c87dfef94deccc3f0d349c1b8c32bfb3b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Sep 2021 17:02:39 +0900 Subject: [PATCH 061/109] Remove remnants of `DatabasedSetting` from `SkinInfo` This was never used --- osu.Game/Skinning/SkinInfo.cs | 3 --- osu.Game/Skinning/SkinStore.cs | 6 ------ 2 files changed, 9 deletions(-) diff --git a/osu.Game/Skinning/SkinInfo.cs b/osu.Game/Skinning/SkinInfo.cs index 851d71f914..2bf8668ec6 100644 --- a/osu.Game/Skinning/SkinInfo.cs +++ b/osu.Game/Skinning/SkinInfo.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using osu.Framework.Extensions.ObjectExtensions; -using osu.Game.Configuration; using osu.Game.Database; using osu.Game.Extensions; using osu.Game.IO; @@ -39,8 +38,6 @@ namespace osu.Game.Skinning public List Files { get; set; } = new List(); - public List Settings { get; set; } - public bool DeletePending { get; set; } public static SkinInfo Default { get; } = new SkinInfo diff --git a/osu.Game/Skinning/SkinStore.cs b/osu.Game/Skinning/SkinStore.cs index 153eeda130..31cadb0a24 100644 --- a/osu.Game/Skinning/SkinStore.cs +++ b/osu.Game/Skinning/SkinStore.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; -using Microsoft.EntityFrameworkCore; using osu.Framework.Platform; using osu.Game.Database; @@ -14,9 +12,5 @@ namespace osu.Game.Skinning : base(contextFactory, storage) { } - - protected override IQueryable AddIncludesForDeletion(IQueryable query) => - base.AddIncludesForDeletion(query) - .Include(s => s.Settings); // don't include FileInfo. these are handled by the FileStore itself. } } From a150fb29960bde3dcd9150dc4143eaea4cbead5d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Sep 2021 17:09:02 +0900 Subject: [PATCH 062/109] Add nullability directive and make variant non-nullable --- osu.Game/Configuration/RealmRulesetSetting.cs | 9 ++++++--- osu.Game/OsuGameBase.cs | 2 +- osu.Game/Rulesets/Configuration/RulesetConfigManager.cs | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/osu.Game/Configuration/RealmRulesetSetting.cs b/osu.Game/Configuration/RealmRulesetSetting.cs index c88a261ad2..d1e1bb9ea2 100644 --- a/osu.Game/Configuration/RealmRulesetSetting.cs +++ b/osu.Game/Configuration/RealmRulesetSetting.cs @@ -5,6 +5,8 @@ using System; using osu.Game.Database; using Realms; +#nullable enable + namespace osu.Game.Configuration { [MapTo(@"RulesetSetting")] @@ -16,12 +18,13 @@ namespace osu.Game.Configuration [Indexed] public int RulesetID { get; set; } - public int? Variant { get; set; } + [Indexed] + public int Variant { get; set; } - public string Key { get; set; } + public string Key { get; set; } = string.Empty; [MapTo(nameof(Value))] - public string ValueString { get; set; } + public string ValueString { get; set; } = string.Empty; public object Value { diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 36406ded08..46614ca0ad 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -465,7 +465,7 @@ namespace osu.Game ValueString = dkb.StringValue, Key = dkb.Key, RulesetID = dkb.RulesetID.Value, - Variant = dkb.Variant + Variant = dkb.Variant ?? 0, }); } } diff --git a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs index a97976392a..f4b4e2978c 100644 --- a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Configuration { private readonly RealmContextFactory realmFactory; - private readonly int? variant; + private readonly int variant; private List databasedSettings = new List(); @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Configuration rulesetId = ruleset.ID ?? -1; - this.variant = variant; + this.variant = variant ?? 0; Load(); From a1d325cb22fb066f82f8561d46c2757214b38573 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Sep 2021 17:12:00 +0900 Subject: [PATCH 063/109] Mark key and value non-nullable (at realm end) and simplify `Value` logic --- osu.Game/Configuration/RealmRulesetSetting.cs | 13 ++++--------- osu.Game/OsuGameBase.cs | 2 +- .../Rulesets/Configuration/RulesetConfigManager.cs | 4 ++-- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/osu.Game/Configuration/RealmRulesetSetting.cs b/osu.Game/Configuration/RealmRulesetSetting.cs index d1e1bb9ea2..07e56ad8dd 100644 --- a/osu.Game/Configuration/RealmRulesetSetting.cs +++ b/osu.Game/Configuration/RealmRulesetSetting.cs @@ -21,17 +21,12 @@ namespace osu.Game.Configuration [Indexed] public int Variant { get; set; } + [Required] public string Key { get; set; } = string.Empty; - [MapTo(nameof(Value))] - public string ValueString { get; set; } = string.Empty; + [Required] + public string Value { get; set; } = string.Empty; - public object Value - { - get => ValueString; - set => ValueString = value.ToString(); - } - - public override string ToString() => $"{Key}=>{Value}"; + public override string ToString() => $"{Key} => {Value}"; } } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 46614ca0ad..59a05aec4f 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -462,8 +462,8 @@ namespace osu.Game usage.Realm.Add(new RealmRulesetSetting { - ValueString = dkb.StringValue, Key = dkb.Key, + Value = dkb.StringValue, RulesetID = dkb.RulesetID.Value, Variant = dkb.Variant ?? 0, }); diff --git a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs index f4b4e2978c..a0ec8e3e0e 100644 --- a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs @@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Configuration setting = new RealmRulesetSetting { Key = lookup.ToString(), - Value = bindable.Value, + Value = bindable.Value.ToString(), RulesetID = rulesetId, Variant = variant, }; @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Configuration bindable.ValueChanged += b => { - realmFactory?.Context.Write(() => setting.Value = b.NewValue); + realmFactory?.Context.Write(() => setting.Value = b.NewValue.ToString()); }; } } From cdb44d7239e3ad92a56e40bd04ce5a6ee7ad86c7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Sep 2021 17:16:08 +0900 Subject: [PATCH 064/109] Fix match footer test scene not working in visual testing --- .../Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs index 4e08ffef17..44a8d7b439 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; @@ -15,11 +16,13 @@ namespace osu.Game.Tests.Visual.Multiplayer { SelectedRoom.Value = new Room(); - Child = new MultiplayerMatchFooter + Child = new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Height = 50 + RelativeSizeAxes = Axes.X, + Height = 50, + Child = new MultiplayerMatchFooter() }; }); } From 4f1db5af40c79e038737eef75ab6859641b12fa4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Sep 2021 17:25:07 +0900 Subject: [PATCH 065/109] Attach migration memo to `DatabasedSetting` class for visibility --- osu.Game/Configuration/DatabasedSetting.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Configuration/DatabasedSetting.cs b/osu.Game/Configuration/DatabasedSetting.cs index f5c92b3029..fe1d51d57f 100644 --- a/osu.Game/Configuration/DatabasedSetting.cs +++ b/osu.Game/Configuration/DatabasedSetting.cs @@ -7,7 +7,7 @@ using osu.Game.Database; namespace osu.Game.Configuration { [Table("Settings")] - public class DatabasedSetting : IHasPrimaryKey + public class DatabasedSetting : IHasPrimaryKey // can be removed 20220315. { public int ID { get; set; } From 9b101ea9eb6576d7d579150ce90eb887ff61f6e8 Mon Sep 17 00:00:00 2001 From: AbstractQbit <38468635+AbstractQbit@users.noreply.github.com> Date: Wed, 15 Sep 2021 11:40:23 +0300 Subject: [PATCH 066/109] Add a test for `AllowTrackAdjustments` --- .../Menus/TestSceneMusicActionHandling.cs | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs index 9037338e23..50226ae2e2 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs @@ -9,6 +9,7 @@ using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Input.Bindings; using osu.Game.Overlays; +using osu.Game.Screens; using osu.Game.Tests.Resources; namespace osu.Game.Tests.Visual.Menus @@ -79,5 +80,55 @@ namespace osu.Game.Tests.Visual.Menus trackChangeQueue.Count == 1 && trackChangeQueue.Dequeue().changeDirection == TrackChangeDirection.Next); } + + [Test] + public void TestAllowTrackAdjustments() + { + AddStep("push allowing screen", () => Game.ScreenStack.Push(new AllowScreen())); + AddAssert("allows adjustments", () => Game.MusicController.AllowTrackAdjustments); + + AddStep("push inheriting screen", () => Game.ScreenStack.Push(new InheritScreen())); + AddAssert("allows adjustments", () => Game.MusicController.AllowTrackAdjustments); + + AddStep("push disallowing screen", () => Game.ScreenStack.Push(new DisallowScreen())); + AddAssert("disallows adjustments", () => !Game.MusicController.AllowTrackAdjustments); + + AddStep("push inheriting screen", () => Game.ScreenStack.Push(new InheritScreen())); + AddAssert("disallows adjustments", () => !Game.MusicController.AllowTrackAdjustments); + + AddStep("push inheriting screen", () => Game.ScreenStack.Push(new InheritScreen())); + AddAssert("disallows adjustments", () => !Game.MusicController.AllowTrackAdjustments); + + AddStep("push allowing screen", () => Game.ScreenStack.Push(new AllowScreen())); + AddAssert("allows adjustments", () => Game.MusicController.AllowTrackAdjustments); + + // Now start exiting from screens + AddStep("exit screen", () => Game.ScreenStack.Exit()); + AddAssert("disallows adjustments", () => !Game.MusicController.AllowTrackAdjustments); + + AddStep("exit screen", () => Game.ScreenStack.Exit()); + AddAssert("disallows adjustments", () => !Game.MusicController.AllowTrackAdjustments); + + AddStep("exit screen", () => Game.ScreenStack.Exit()); + AddAssert("disallows adjustments", () => !Game.MusicController.AllowTrackAdjustments); + + AddStep("exit screen", () => Game.ScreenStack.Exit()); + AddAssert("allows adjustments", () => Game.MusicController.AllowTrackAdjustments); + + AddStep("exit screen", () => Game.ScreenStack.Exit()); + AddAssert("allows adjustments", () => Game.MusicController.AllowTrackAdjustments); + } + + private class AllowScreen : OsuScreen + { + public override bool? AllowTrackAdjustments => true; + } + + private class DisallowScreen : OsuScreen + { + public override bool? AllowTrackAdjustments => false; + } + + private class InheritScreen : OsuScreen { } } } From 1181317c729455c2e81b409933c37167e84d55df Mon Sep 17 00:00:00 2001 From: AbstractQbit <38468635+AbstractQbit@users.noreply.github.com> Date: Wed, 15 Sep 2021 12:01:56 +0300 Subject: [PATCH 067/109] Fix issues found by code quality ci --- .../Visual/Menus/TestSceneMusicActionHandling.cs | 4 +++- osu.Game/Screens/IOsuScreen.cs | 2 +- osu.Game/Screens/OsuScreen.cs | 8 +------- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs index 50226ae2e2..79acaedb73 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs @@ -129,6 +129,8 @@ namespace osu.Game.Tests.Visual.Menus public override bool? AllowTrackAdjustments => false; } - private class InheritScreen : OsuScreen { } + private class InheritScreen : OsuScreen + { + } } } diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index 735853e462..fd884586d1 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -62,7 +62,7 @@ namespace osu.Game.Screens /// Whether mod track adjustments are allowed to be applied. /// A value means that the parent screen's value of this setting will be used. /// - bool? AllowTrackAdjustments { set; get; } + bool? AllowTrackAdjustments { get; set; } /// /// Invoked when the back button has been pressed to close any overlays before exiting this . diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 0deaa3e80e..9b4d7f9eda 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -81,13 +81,7 @@ namespace osu.Game.Screens public virtual float BackgroundParallaxAmount => 1; - private bool? allowTrackAdjustments = null; - - public virtual bool? AllowTrackAdjustments - { - set => allowTrackAdjustments = value; - get => allowTrackAdjustments; - } + public virtual bool? AllowTrackAdjustments { get; set; } public Bindable Beatmap { get; private set; } From 07fec268c028dc65b43f38a2cde6da8fe77cd212 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Sep 2021 18:32:52 +0900 Subject: [PATCH 068/109] Limit maximum triangles to avoid GL buffer overflow --- osu.Game/Graphics/Backgrounds/Triangles.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 35c48a50d0..ab8763e576 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.Primitives; using osu.Framework.Allocation; using System.Collections.Generic; using osu.Framework.Graphics.Batches; +using osu.Framework.Graphics.OpenGL.Buffers; using osu.Framework.Graphics.OpenGL.Vertices; using osu.Framework.Lists; @@ -181,7 +182,10 @@ namespace osu.Game.Graphics.Backgrounds private void addTriangles(bool randomY) { - AimCount = (int)(DrawWidth * DrawHeight * 0.002f / (triangleScale * triangleScale) * SpawnRatio); + // limited by the maximum size of QuadVertexBuffer for safety. + const int max_triangles = QuadVertexBuffer.MAX_QUADS; + + AimCount = (int)Math.Min(max_triangles, (DrawWidth * DrawHeight * 0.002f / (triangleScale * triangleScale) * SpawnRatio)); for (int i = 0; i < AimCount - parts.Count; i++) parts.Add(createTriangle(randomY)); From f0439ef50b0dd9217e43508217b34c0e47dcba7b Mon Sep 17 00:00:00 2001 From: AbstractQbit <38468635+AbstractQbit@users.noreply.github.com> Date: Wed, 15 Sep 2021 13:12:57 +0300 Subject: [PATCH 069/109] Remove unnecessary `AllowTrackAdjustments` overrides, add true to `SongSelect` --- .../Settings/Sections/Maintenance/DirectorySelectScreen.cs | 2 -- osu.Game/Screens/Import/FileImportScreen.cs | 2 -- osu.Game/Screens/Menu/MainMenu.cs | 2 -- osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 2 -- osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs | 2 -- osu.Game/Screens/Select/SongSelect.cs | 2 ++ osu.Game/Screens/StartupScreen.cs | 2 -- 7 files changed, 2 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs index 6d0e79e2c7..e509cac2f1 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs @@ -24,8 +24,6 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance private OsuDirectorySelector directorySelector; - public override bool? AllowTrackAdjustments => false; - /// /// Text to display in the header to inform the user of what they are selecting. /// diff --git a/osu.Game/Screens/Import/FileImportScreen.cs b/osu.Game/Screens/Import/FileImportScreen.cs index 69fcf31876..7e1d55b3e2 100644 --- a/osu.Game/Screens/Import/FileImportScreen.cs +++ b/osu.Game/Screens/Import/FileImportScreen.cs @@ -23,8 +23,6 @@ namespace osu.Game.Screens.Import { public override bool HideOverlaysOnEnter => true; - public override bool? AllowTrackAdjustments => false; - private OsuFileSelector fileSelector; private Container contentContainer; private TextFlowContainer currentFileText; diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 00885a91c5..221b31f855 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -36,8 +36,6 @@ namespace osu.Game.Screens.Menu public override bool AllowExternalScreenChange => true; - public override bool? AllowTrackAdjustments => false; - private Screen songSelect; private MenuSideFlashes sideFlashes; diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index e3945c9cac..fc20b21b60 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -24,8 +24,6 @@ namespace osu.Game.Screens.OnlinePlay [Cached] protected readonly OverlayColourProvider ColourProvider = new OverlayColourProvider(OverlayColourScheme.Plum); - public override bool? AllowTrackAdjustments => false; - public override bool CursorVisible => (screenStack?.CurrentScreen as IOnlinePlaySubScreen)?.CursorVisible ?? true; // this is required due to PlayerLoader eventually being pushed to the main stack diff --git a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs index 9bec320e22..88dab88d42 100644 --- a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs +++ b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs @@ -10,8 +10,6 @@ namespace osu.Game.Screens.Play { protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); - public override bool? AllowTrackAdjustments => true; - public void ApplyToBackground(Action action) => base.ApplyToBackground(b => action.Invoke((BackgroundScreenBeatmap)b)); } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index f11f9fd614..1f0f134ba7 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -53,6 +53,8 @@ namespace osu.Game.Screens.Select protected virtual bool DisplayStableImportPrompt => stableImportManager?.SupportsImportFromStable == true; + public override bool? AllowTrackAdjustments => true; + /// /// Can be null if is false. /// diff --git a/osu.Game/Screens/StartupScreen.cs b/osu.Game/Screens/StartupScreen.cs index 7b73d36fdf..be217d6b1f 100644 --- a/osu.Game/Screens/StartupScreen.cs +++ b/osu.Game/Screens/StartupScreen.cs @@ -16,8 +16,6 @@ namespace osu.Game.Screens public override bool CursorVisible => false; - public override bool? AllowTrackAdjustments => false; - protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; } } From 318f0941ca8f53af7bff53cc8ce54226f8a0fbba Mon Sep 17 00:00:00 2001 From: AbstractQbit <38468635+AbstractQbit@users.noreply.github.com> Date: Wed, 15 Sep 2021 21:25:39 +0300 Subject: [PATCH 070/109] Move all the "inherit previous `AllowTrackAdjustments`" logic into `OsuScreen` --- osu.Game/OsuGame.cs | 5 +---- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/IOsuScreen.cs | 2 +- .../Multiplayer/Spectate/MultiSpectatorScreen.cs | 2 +- osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs | 2 +- osu.Game/Screens/OsuScreen.cs | 7 ++++++- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 2 +- 8 files changed, 13 insertions(+), 11 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index f2f925a778..2107b3a0e9 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1075,10 +1075,7 @@ namespace osu.Game OverlayActivationMode.BindTo(newOsuScreen.OverlayActivationMode); API.Activity.BindTo(newOsuScreen.Activity); - if (newOsuScreen.AllowTrackAdjustments.HasValue) - MusicController.AllowTrackAdjustments = newOsuScreen.AllowTrackAdjustments.Value; - else - newOsuScreen.AllowTrackAdjustments = MusicController.AllowTrackAdjustments; + MusicController.AllowTrackAdjustments = newOsuScreen.AllowTrackAdjustments; if (newOsuScreen.HideOverlaysOnEnter) CloseAllOverlays(); diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 028662172d..5bb47e1c11 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Edit public override bool DisallowExternalBeatmapRulesetChanges => true; - public override bool? AllowTrackAdjustments => false; + public override bool AllowTrackAdjustments => false; protected bool HasUnsavedChanges => lastSavedHash != changeHandler.CurrentStateHash; diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index fd884586d1..b12baf233f 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -62,7 +62,7 @@ namespace osu.Game.Screens /// Whether mod track adjustments are allowed to be applied. /// A value means that the parent screen's value of this setting will be used. /// - bool? AllowTrackAdjustments { get; set; } + bool AllowTrackAdjustments { get; } /// /// Invoked when the back button has been pressed to close any overlays before exiting this . diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index c45e3a79da..bf7c738882 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate public override bool DisallowExternalBeatmapRulesetChanges => true; // We are managing our own adjustments. For now, this happens inside the Player instances themselves. - public override bool? AllowTrackAdjustments => false; + public override bool AllowTrackAdjustments => false; /// /// Whether all spectating players have finished loading. diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs index 8c4f0c1394..054009a228 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs @@ -11,7 +11,7 @@ namespace osu.Game.Screens.OnlinePlay { public override bool DisallowExternalBeatmapRulesetChanges => false; - public override bool? AllowTrackAdjustments => true; + public override bool AllowTrackAdjustments => true; public virtual string ShortTitle => Title; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 9b4d7f9eda..01dc703b66 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -81,7 +81,12 @@ namespace osu.Game.Screens public virtual float BackgroundParallaxAmount => 1; - public virtual bool? AllowTrackAdjustments { get; set; } + [Resolved] + private MusicController musicController { get; set; } + + private bool? allowTrackAdjustments; + + public virtual bool AllowTrackAdjustments => allowTrackAdjustments ??= (musicController?.AllowTrackAdjustments ?? false); public Bindable Beatmap { get; private set; } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 9927467bd6..e8a2790c94 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Play protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.UserTriggered; // We are managing our own adjustments (see OnEntering/OnExiting). - public override bool? AllowTrackAdjustments => false; + public override bool AllowTrackAdjustments => false; private readonly IBindable gameActive = new Bindable(true); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 1f0f134ba7..9b6cbad7d1 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -53,7 +53,7 @@ namespace osu.Game.Screens.Select protected virtual bool DisplayStableImportPrompt => stableImportManager?.SupportsImportFromStable == true; - public override bool? AllowTrackAdjustments => true; + public override bool AllowTrackAdjustments => true; /// /// Can be null if is false. From 30c458c662e403bcadaf25a8ac975242989ba35a Mon Sep 17 00:00:00 2001 From: AbstractQbit <38468635+AbstractQbit@users.noreply.github.com> Date: Wed, 15 Sep 2021 21:34:41 +0300 Subject: [PATCH 071/109] Oops, fix not compiling test --- osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs index 79acaedb73..8f6ab5e755 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs @@ -121,12 +121,12 @@ namespace osu.Game.Tests.Visual.Menus private class AllowScreen : OsuScreen { - public override bool? AllowTrackAdjustments => true; + public override bool AllowTrackAdjustments => true; } private class DisallowScreen : OsuScreen { - public override bool? AllowTrackAdjustments => false; + public override bool AllowTrackAdjustments => false; } private class InheritScreen : OsuScreen From 3cd3e133ce2a98205988c480cd44c4e61a5fae59 Mon Sep 17 00:00:00 2001 From: AbstractQbit <38468635+AbstractQbit@users.noreply.github.com> Date: Thu, 16 Sep 2021 01:21:29 +0300 Subject: [PATCH 072/109] Move `AllowTrackAdjustments` test to `TestSceneOsuScreenStack` --- .../Menus/TestSceneMusicActionHandling.cs | 53 +----------- .../Visual/TestSceneOsuScreenStack.cs | 83 ++++++++++++++++++- 2 files changed, 80 insertions(+), 56 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs index 8f6ab5e755..bf6491cd81 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Database; @@ -80,57 +81,5 @@ namespace osu.Game.Tests.Visual.Menus trackChangeQueue.Count == 1 && trackChangeQueue.Dequeue().changeDirection == TrackChangeDirection.Next); } - - [Test] - public void TestAllowTrackAdjustments() - { - AddStep("push allowing screen", () => Game.ScreenStack.Push(new AllowScreen())); - AddAssert("allows adjustments", () => Game.MusicController.AllowTrackAdjustments); - - AddStep("push inheriting screen", () => Game.ScreenStack.Push(new InheritScreen())); - AddAssert("allows adjustments", () => Game.MusicController.AllowTrackAdjustments); - - AddStep("push disallowing screen", () => Game.ScreenStack.Push(new DisallowScreen())); - AddAssert("disallows adjustments", () => !Game.MusicController.AllowTrackAdjustments); - - AddStep("push inheriting screen", () => Game.ScreenStack.Push(new InheritScreen())); - AddAssert("disallows adjustments", () => !Game.MusicController.AllowTrackAdjustments); - - AddStep("push inheriting screen", () => Game.ScreenStack.Push(new InheritScreen())); - AddAssert("disallows adjustments", () => !Game.MusicController.AllowTrackAdjustments); - - AddStep("push allowing screen", () => Game.ScreenStack.Push(new AllowScreen())); - AddAssert("allows adjustments", () => Game.MusicController.AllowTrackAdjustments); - - // Now start exiting from screens - AddStep("exit screen", () => Game.ScreenStack.Exit()); - AddAssert("disallows adjustments", () => !Game.MusicController.AllowTrackAdjustments); - - AddStep("exit screen", () => Game.ScreenStack.Exit()); - AddAssert("disallows adjustments", () => !Game.MusicController.AllowTrackAdjustments); - - AddStep("exit screen", () => Game.ScreenStack.Exit()); - AddAssert("disallows adjustments", () => !Game.MusicController.AllowTrackAdjustments); - - AddStep("exit screen", () => Game.ScreenStack.Exit()); - AddAssert("allows adjustments", () => Game.MusicController.AllowTrackAdjustments); - - AddStep("exit screen", () => Game.ScreenStack.Exit()); - AddAssert("allows adjustments", () => Game.MusicController.AllowTrackAdjustments); - } - - private class AllowScreen : OsuScreen - { - public override bool AllowTrackAdjustments => true; - } - - private class DisallowScreen : OsuScreen - { - public override bool AllowTrackAdjustments => false; - } - - private class InheritScreen : OsuScreen - { - } } } diff --git a/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs index c55988d1bb..ed3935e101 100644 --- a/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs @@ -5,8 +5,8 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Screens; -using osu.Framework.Testing; using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; using osu.Game.Screens; using osu.Game.Screens.Play; using osuTK.Graphics; @@ -18,10 +18,20 @@ namespace osu.Game.Tests.Visual { private TestOsuScreenStack stack; - [SetUpSteps] - public void SetUpSteps() + [Cached] + private MusicController musicController = new MusicController(); + + [BackgroundDependencyLoader] + private void load() { - AddStep("Create new screen stack", () => { Child = stack = new TestOsuScreenStack { RelativeSizeAxes = Axes.Both }; }); + stack = new TestOsuScreenStack { RelativeSizeAxes = Axes.Both }; + stack.ScreenPushed += screenChanged; + stack.ScreenExited += screenChanged; + + Add(musicController); + Add(stack); + + LoadComponent(stack); } [Test] @@ -42,6 +52,44 @@ namespace osu.Game.Tests.Visual AddAssert("Parallax is off", () => stack.ParallaxAmount == 0); } + [Test] + public void AllowTrackAdjustmentsTest() + { + AddStep("push allowing screen", () => stack.Push(loadNewScreen())); + AddAssert("allows adjustments 1", () => musicController.AllowTrackAdjustments); + + AddStep("push inheriting screen", () => stack.Push(loadNewScreen())); + AddAssert("allows adjustments 2", () => musicController.AllowTrackAdjustments); + + AddStep("push disallowing screen", () => stack.Push(loadNewScreen())); + AddAssert("disallows adjustments 3", () => !musicController.AllowTrackAdjustments); + + AddStep("push inheriting screen", () => stack.Push(loadNewScreen())); + AddAssert("disallows adjustments 4", () => !musicController.AllowTrackAdjustments); + + AddStep("push inheriting screen", () => stack.Push(loadNewScreen())); + AddAssert("disallows adjustments 5", () => !musicController.AllowTrackAdjustments); + + AddStep("push allowing screen", () => stack.Push(loadNewScreen())); + AddAssert("allows adjustments 6", () => musicController.AllowTrackAdjustments); + + // Now start exiting from screens + AddStep("exit screen", () => stack.Exit()); + AddAssert("disallows adjustments 7", () => !musicController.AllowTrackAdjustments); + + AddStep("exit screen", () => stack.Exit()); + AddAssert("disallows adjustments 8", () => !musicController.AllowTrackAdjustments); + + AddStep("exit screen", () => stack.Exit()); + AddAssert("disallows adjustments 9", () => !musicController.AllowTrackAdjustments); + + AddStep("exit screen", () => stack.Exit()); + AddAssert("allows adjustments 10", () => musicController.AllowTrackAdjustments); + + AddStep("exit screen", () => stack.Exit()); + AddAssert("allows adjustments 11", () => musicController.AllowTrackAdjustments); + } + public class TestScreen : ScreenWithBeatmapBackground { private readonly string screenText; @@ -78,5 +126,32 @@ namespace osu.Game.Tests.Visual { public new float ParallaxAmount => base.ParallaxAmount; } + + private class AllowScreen : OsuScreen + { + public override bool AllowTrackAdjustments => true; + } + + public class DisallowScreen : OsuScreen + { + public override bool AllowTrackAdjustments => false; + } + + private class InheritScreen : OsuScreen + { + } + + private OsuScreen loadNewScreen() where T : OsuScreen, new() + { + OsuScreen screen = new T(); + LoadComponent(screen); + return screen; + } + + private void screenChanged(IScreen current, IScreen newScreen) + { + if (newScreen is IOsuScreen newOsuScreen) + musicController.AllowTrackAdjustments = newOsuScreen.AllowTrackAdjustments; + } } } From 9057be1a02069917e065a94290685933dd9cf73e Mon Sep 17 00:00:00 2001 From: AbstractQbit <38468635+AbstractQbit@users.noreply.github.com> Date: Thu, 16 Sep 2021 01:30:53 +0300 Subject: [PATCH 073/109] Remove unused usings --- osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs index bf6491cd81..9037338e23 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs @@ -4,13 +4,11 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; -using osu.Framework.Allocation; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Input.Bindings; using osu.Game.Overlays; -using osu.Game.Screens; using osu.Game.Tests.Resources; namespace osu.Game.Tests.Visual.Menus From 45b07aa362b7048ee9ceb3f31e34ad68b4399943 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Sep 2021 15:33:55 +0900 Subject: [PATCH 074/109] Add some basic animated textures to mania metric skin --- .../Resources/metrics-skin/mania-note1-0@2x.png | Bin 0 -> 1874 bytes .../Resources/metrics-skin/mania-note1-1@2x.png | Bin 0 -> 2828 bytes .../Resources/metrics-skin/mania-note1H-0@2x.png | Bin 0 -> 5154 bytes .../Resources/metrics-skin/mania-note1H-1@2x.png | Bin 0 -> 6025 bytes .../Resources/metrics-skin/mania-note2-0@2x.png | Bin 0 -> 1865 bytes .../Resources/metrics-skin/mania-note2-1@2x.png | Bin 0 -> 2847 bytes .../Resources/metrics-skin/mania-note2H@2x.png | Bin 0 -> 5294 bytes .../Resources/metrics-skin/mania-noteS@2x.png | Bin 0 -> 3963 bytes .../Resources/metrics-skin/mania-noteSH@2x.png | Bin 0 -> 3963 bytes 9 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note1-0@2x.png create mode 100644 osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note1-1@2x.png create mode 100644 osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note1H-0@2x.png create mode 100644 osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note1H-1@2x.png create mode 100644 osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note2-0@2x.png create mode 100644 osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note2-1@2x.png create mode 100644 osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note2H@2x.png create mode 100644 osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-noteS@2x.png create mode 100644 osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-noteSH@2x.png diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note1-0@2x.png b/osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note1-0@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2db5d76e7828a025037cbe434f15eb5737ab749f GIT binary patch literal 1874 zcmbVNeM}Q)7=K|Ub}TA!n*`?ca%75Q+_j}p?w~+zVKiH@gJw1oKd#qDXX3h3;tje?9c zQB37iguV2wQ&c(tPt9~%tb*0_I!>}QLP#};mv%{9AU)ITBFGX-fNWH;lhMMxEr(&q zY1hK@l1&PeOHVnRxn&$xP?l#Q%SuSh4rgXS>0VqUpeccXy!29r$GuuO$cu}VrGbt}$AMAAKkB#ZWKdLY0U@x>KmoWcu$?njWj>g?#Ga zy#GqfTS{FNnosepn13qL z>>$Ks!i@|s5DZBf4O&&A5D{So`?1q>hV4#bHos zw~y>PloACbxnt55gE8?_jHq}{ly;^2Y@hhWd~Y=9EZ)G)%X1x@BES#*SJI+~E8)a9 zu1D=_Jy!IQ`h}`BYgCh~qvJ-*+kamf^KD~a)6qOWg(CIn^J%g|t1R;Bkq?mR$NK8z zWm8s8v8Bq-|Fkw4M=mbZt?GU^qxM4EwqpO){r%-vGRf-t&A>dzJrhI$AOj!_WPvAg zpAc@%`tIrY-7oemi>v7^bu3Q_ObGME?n78lS9{<~O++}L8r5x?ZLLFh4|K2@a_~og z-uz4Fzj@ieC0yof@*)jF{b7s^2A}O@=6-l9_eN7XGcgLBw&^qe%w_ezei|%1zuJA_#|#`j%ZyzmY@qf`!86;i>d$AW%2l;<{TVWuZ+l_Y39&;oKWxRB z&WhuUC)I|TE%z}Y?b*SteeW>t?!|>E%|q`2bHVUQc2V~o?PODTLqSZ(CU+)v(hPy0 z>v}KnFMZNg-p?(&SmhaN8e(ReWZ_w7ufNuP`)1Pc$mMg#Hk3D_4GaAKO<`emCl<8b z=~;KL>af4Fg?8RkE(*x@bT;_n4<4C@*KBCRN+SCreOz;m(X;%Y%Y0%@grpR*|En(F z>befubAdevZ!gSfzS28?T5+00KZR{h&nGEL7LW!~t)F6g-lDOgG5&n3&)Qtt0mnT0v*p($g)g-rNDiW6aJo J?47f?;%`E8Pn`e& literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note1-1@2x.png b/osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note1-1@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6e7aded39f315120b9eb7c9fbac3c543faf90c22 GIT binary patch literal 2828 zcmbVOeK?bQAOCGR<@6%;R7%MXPoda5v*k4-)Nn}%#ca1(Z1>v6#u3huUa3o^S`KsS zlvJpslt|}1qG+>99^yEak-VKyt~Knr*V{RN)VZ#w{qy_%zSrmT`F_6N-}k=n?G5l- zH)p2lOaQ@J^-dN-8+>8Ap$%|%*04}@q7_Y>TK~&mxk>1VVni# z9Yh@GZ1LVyC?f#l0Sh4v1&g<1;qiD3g^Fb}qnWJeXj=>sPbA>*WE_EPhsV=MR2rF# z`S7zq(h1oyv_QJohh)gf*&R2-g&BNFWpgq@tg#(-E@42xo6 z0ftD#k}=i{CX370M{M3v7z~;ZUnFMoS&$Fi*#Z&4a=C1pyC-3-mjl5A?@3=vAb5H> zIugn54(>?U(Tn14@9~jKhgk_ch%f%gW&g#cf03&n2c7`QOoxQrM2PJrgn5{ERnxei z@#07zk-Z2MuP^F-;IcpC)5YUWww1XR)XujZ1)_M# z)69Xi*gIaWx}@q~>mGEa?N&c|*rnACC!Jfyou2OSh-rX4?CAht05H@)_y7O)YdE%B zi{=IVzGl2-%k^`lJep{`y-CmmXI3({6u~)@{A~I)j@@N@54!>qV`5%=BpXP7Q=JxU>uTp324eo6pG54ULe z{hetml}73ts)%bZI@6f2ys3BhNKfBHiTa@Luqn>S4MY`ZsYQo1TU0Nlsi{t7^81z? zL1Xr^Ws0MH6BTuY^Oq}5P&8N!xM*;K>U7BNl*TVmck8qU_gKgi)u1`4&#iWuV9g3} zw8BH%B3+(WrGwf)ZWdJks^gLOU|Qrkb%6#~kX!pm7_xs_aL+dXZ#_Yj4WoDJ=lJ}) zq|r2&9P=!B^}j}oJJuY|@I2o#R@Sht$sCn_I!L)u$r<$?a+Dp+?+jnA{LL=7s=V$` zn;HJoGEE8=@owOCwlwDx_vE`oxi(K{0^hSa9_1Q|>Sgp+`{~F?v_u%0*lj9Tr5FS2 zlH>ym?KUlP@vf-fgB*)C!b@A9)%WCj?F4R{?ZZnMi;dAh9mLgaD~l;0Sr~wOZ!<2H z#umSt|2q$D02Gpz3%IazoCdwtb}&=kPd#?3Cj+=qH$CXe-M=rG<6n)MX9$i2gj}tV zHY#Nks&{D$Zk~!QmbJ+S9Q2Z=>A#L^e^SWvmK%71!Xv@m9$T(g#wHN8S%#=|;Y+(I z@ef{itV9RreFp;8wnSVf!nm;fhUfQZ=gmih6_1WRS=~n)3?#k2l+vPC|51Vr zxQUKmBrAS8aJJVb1F0`4n5}iIiI}(|e=Fd>uEn7N^e{JW#^|8$jr~Sv)%-FI0*a@N zUcK$qoYSIrQM0#$sdwRPA2Pe=_O|K!j2va=+3JncGlARPp=ZbD#z;6=Yg&};_kQdu zcckr?wc{)L%df3AS!jkYh|KDl_8!?$w!BFhHau04sZ5VQz7V;MCzIykISkJk8+uwR z;>(eyH78c-ysu(!4wx8#cFwrG;dxP_Zgcs``w6BfUWHa$?OKU0G?VBq4P4b`faYCQ zI)AUx)GAj)u%gO5vc^RlHZWy1Qmu-B12EtSJl^#rH)P=jN?cnKQBJlt2EM0HP_9Z# zVAAWH4r)R8oS9o2%F{!Ks?wfnC&(nyq3|=pGWQ>l3Odso-wv#5pIjXfAXE z)@^2z{**@$$yhj2|ECU$eEs!2972-Ks_MLHolV z*;zmJr`?G+(kwtBueQdNW7SvchUA(4sa<2l36d$b@B7=rUT&daWsmT`#>OC42__of zuTCsOLvV!yj25HOfLB!TG-g*53YG5QG?}I_wnmjr1A=e9;&b!2uN3-g>9yR+kaQF% YQlD)6McVfS`Fjd{JpJgUYomVrA1bYTegFUf literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note1H-0@2x.png b/osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note1H-0@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f11fb4f853f011a3e76be6851249fab8cfb31ace GIT binary patch literal 5154 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 Gz42f2c@AFy literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note1H-1@2x.png b/osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note1H-1@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4eac5f6f2a62e9ad22096d02b1ba310e69c00a82 GIT binary patch literal 6025 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 DP%iL7 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note2-0@2x.png b/osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note2-0@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..456cee538227bd08e4edcb652d421db6cf08d5a2 GIT binary patch literal 1865 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 literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note2H@2x.png b/osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-note2H@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e6da7a10550e46638ecb65a4460eea43eb4d66c8 GIT binary patch literal 5294 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 HIXwI~zp|9c literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-noteSH@2x.png b/osu.Game.Rulesets.Mania.Tests/Resources/metrics-skin/mania-noteSH@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c9bc23e8d9233fbb3b3adb132c50eef6d7f78a11 GIT binary patch literal 3963 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 HIXwI~zp|9c literal 0 HcmV?d00001 From fa693bb8a83ff8ec32c59e31f2a31211af76b8ea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Sep 2021 16:08:09 +0900 Subject: [PATCH 075/109] Move `MusicController` adjustment set to inside `OsuScreen` itself (and result `nullable`) --- .../Visual/TestSceneOsuScreenStack.cs | 12 ++--------- osu.Game/OsuGame.cs | 2 -- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/IOsuScreen.cs | 4 ++-- .../Spectate/MultiSpectatorScreen.cs | 2 +- .../Screens/OnlinePlay/OnlinePlaySubScreen.cs | 2 +- osu.Game/Screens/OsuScreen.cs | 20 +++++++++++++------ osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 2 +- 9 files changed, 23 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs index ed3935e101..7729ad0ff3 100644 --- a/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs @@ -25,8 +25,6 @@ namespace osu.Game.Tests.Visual private void load() { stack = new TestOsuScreenStack { RelativeSizeAxes = Axes.Both }; - stack.ScreenPushed += screenChanged; - stack.ScreenExited += screenChanged; Add(musicController); Add(stack); @@ -129,12 +127,12 @@ namespace osu.Game.Tests.Visual private class AllowScreen : OsuScreen { - public override bool AllowTrackAdjustments => true; + public override bool? AllowTrackAdjustments => true; } public class DisallowScreen : OsuScreen { - public override bool AllowTrackAdjustments => false; + public override bool? AllowTrackAdjustments => false; } private class InheritScreen : OsuScreen @@ -147,11 +145,5 @@ namespace osu.Game.Tests.Visual LoadComponent(screen); return screen; } - - private void screenChanged(IScreen current, IScreen newScreen) - { - if (newScreen is IOsuScreen newOsuScreen) - musicController.AllowTrackAdjustments = newOsuScreen.AllowTrackAdjustments; - } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 2107b3a0e9..ce84c4bd2a 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1075,8 +1075,6 @@ namespace osu.Game OverlayActivationMode.BindTo(newOsuScreen.OverlayActivationMode); API.Activity.BindTo(newOsuScreen.Activity); - MusicController.AllowTrackAdjustments = newOsuScreen.AllowTrackAdjustments; - if (newOsuScreen.HideOverlaysOnEnter) CloseAllOverlays(); else diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 5bb47e1c11..028662172d 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Edit public override bool DisallowExternalBeatmapRulesetChanges => true; - public override bool AllowTrackAdjustments => false; + public override bool? AllowTrackAdjustments => false; protected bool HasUnsavedChanges => lastSavedHash != changeHandler.CurrentStateHash; diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index b12baf233f..910a0c7d61 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -59,10 +59,10 @@ namespace osu.Game.Screens Bindable Ruleset { get; } /// - /// Whether mod track adjustments are allowed to be applied. + /// Whether mod track adjustments should be applied on entering this screen. /// A value means that the parent screen's value of this setting will be used. /// - bool AllowTrackAdjustments { get; } + bool? AllowTrackAdjustments { get; } /// /// Invoked when the back button has been pressed to close any overlays before exiting this . diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index bf7c738882..c45e3a79da 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate public override bool DisallowExternalBeatmapRulesetChanges => true; // We are managing our own adjustments. For now, this happens inside the Player instances themselves. - public override bool AllowTrackAdjustments => false; + public override bool? AllowTrackAdjustments => false; /// /// Whether all spectating players have finished loading. diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs index 054009a228..8c4f0c1394 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs @@ -11,7 +11,7 @@ namespace osu.Game.Screens.OnlinePlay { public override bool DisallowExternalBeatmapRulesetChanges => false; - public override bool AllowTrackAdjustments => true; + public override bool? AllowTrackAdjustments => true; public virtual string ShortTitle => Title; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 01dc703b66..d3981b715c 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -11,11 +11,11 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Beatmaps; -using osu.Game.Rulesets; -using osu.Game.Screens.Menu; using osu.Game.Overlays; -using osu.Game.Users; +using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Menu; +using osu.Game.Users; namespace osu.Game.Screens { @@ -84,9 +84,7 @@ namespace osu.Game.Screens [Resolved] private MusicController musicController { get; set; } - private bool? allowTrackAdjustments; - - public virtual bool AllowTrackAdjustments => allowTrackAdjustments ??= (musicController?.AllowTrackAdjustments ?? false); + public virtual bool? AllowTrackAdjustments => null; public Bindable Beatmap { get; private set; } @@ -96,6 +94,8 @@ namespace osu.Game.Screens private OsuScreenDependencies screenDependencies; + private bool trackAdjustmentStateAtSuspend; + internal void CreateLeasedDependencies(IReadOnlyDependencyContainer dependencies) => createDependencies(dependencies); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -175,8 +175,11 @@ namespace osu.Game.Screens { if (PlayResumeSound) sampleExit?.Play(); + applyArrivingDefaults(true); + musicController.AllowTrackAdjustments = trackAdjustmentStateAtSuspend; + base.OnResuming(last); } @@ -184,6 +187,8 @@ namespace osu.Game.Screens { base.OnSuspending(next); + trackAdjustmentStateAtSuspend = musicController.AllowTrackAdjustments; + onSuspendingLogo(); } @@ -191,6 +196,9 @@ namespace osu.Game.Screens { applyArrivingDefaults(false); + if (AllowTrackAdjustments != null) + musicController.AllowTrackAdjustments = AllowTrackAdjustments.Value; + if (backgroundStack?.Push(ownedBackground = CreateBackground()) != true) { // If the constructed instance was not actually pushed to the background stack, we don't want to track it unnecessarily. diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index e8a2790c94..9927467bd6 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Play protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.UserTriggered; // We are managing our own adjustments (see OnEntering/OnExiting). - public override bool AllowTrackAdjustments => false; + public override bool? AllowTrackAdjustments => false; private readonly IBindable gameActive = new Bindable(true); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 9b6cbad7d1..1f0f134ba7 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -53,7 +53,7 @@ namespace osu.Game.Screens.Select protected virtual bool DisplayStableImportPrompt => stableImportManager?.SupportsImportFromStable == true; - public override bool AllowTrackAdjustments => true; + public override bool? AllowTrackAdjustments => true; /// /// Can be null if is false. From b58415fe198b571dd00640f8689fe22f304bcebd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Sep 2021 16:12:14 +0900 Subject: [PATCH 076/109] Make suspend stored state nullable to ensure we don't break it --- osu.Game/Screens/OsuScreen.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index d3981b715c..f425144c6b 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -94,7 +95,7 @@ namespace osu.Game.Screens private OsuScreenDependencies screenDependencies; - private bool trackAdjustmentStateAtSuspend; + private bool? trackAdjustmentStateAtSuspend; internal void CreateLeasedDependencies(IReadOnlyDependencyContainer dependencies) => createDependencies(dependencies); @@ -178,7 +179,9 @@ namespace osu.Game.Screens applyArrivingDefaults(true); - musicController.AllowTrackAdjustments = trackAdjustmentStateAtSuspend; + Debug.Assert(trackAdjustmentStateAtSuspend != null); + + musicController.AllowTrackAdjustments = trackAdjustmentStateAtSuspend.Value; base.OnResuming(last); } From 3495fae5191eaca5fb0842873830071e3c65b9ce Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Sep 2021 16:31:41 +0900 Subject: [PATCH 077/109] Handle potential for `OnResuming` call without an `OnSuspending` first --- osu.Game/Screens/OsuScreen.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index f425144c6b..ccc891d3bf 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -179,9 +178,10 @@ namespace osu.Game.Screens applyArrivingDefaults(true); - Debug.Assert(trackAdjustmentStateAtSuspend != null); - - musicController.AllowTrackAdjustments = trackAdjustmentStateAtSuspend.Value; + // it's feasible to resume to a screen if the target screen never loaded successfully. + // in such a case there's no need to restore this value. + if (trackAdjustmentStateAtSuspend != null) + musicController.AllowTrackAdjustments = trackAdjustmentStateAtSuspend.Value; base.OnResuming(last); } From 51997fa5330e6694220e7fa0e730d00efae58863 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 16 Sep 2021 16:02:04 +0800 Subject: [PATCH 078/109] Add localisation for GlobalActions --- .../Input/Bindings/GlobalActionContainer.cs | 50 ++++ .../GlobalActionKeyBindingStrings.cs | 254 ++++++++++++++++++ .../Settings/Sections/Input/KeyBindingRow.cs | 2 +- 3 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Localisation/GlobalActionKeyBindingStrings.cs diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 0176a00e9d..73d824a5d2 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -7,6 +7,8 @@ using System.Linq; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Bindings; +using osu.Framework.Localisation; +using osu.Game.Localisation; namespace osu.Game.Input.Bindings { @@ -137,151 +139,199 @@ namespace osu.Game.Input.Bindings public enum GlobalAction { + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleChat))] [Description("Toggle chat overlay")] ToggleChat, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleSocial))] [Description("Toggle social overlay")] ToggleSocial, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ResetInputSettings))] [Description("Reset input settings")] ResetInputSettings, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleToolbar))] [Description("Toggle toolbar")] ToggleToolbar, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleSettings))] [Description("Toggle settings")] ToggleSettings, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleBeatmapListing))] [Description("Toggle beatmap listing")] ToggleBeatmapListing, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.IncreaseVolume))] [Description("Increase volume")] IncreaseVolume, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.DecreaseVolume))] [Description("Decrease volume")] DecreaseVolume, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleMute))] [Description("Toggle mute")] ToggleMute, // In-Game Keybindings + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SkipCutscene))] [Description("Skip cutscene")] SkipCutscene, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.QuickRetry))] [Description("Quick retry (hold)")] QuickRetry, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.TakeScreenshot))] [Description("Take screenshot")] TakeScreenshot, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleGameplayMouseButtons))] [Description("Toggle gameplay mouse buttons")] ToggleGameplayMouseButtons, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.Back))] [Description("Back")] Back, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.IncreaseScrollSpeed))] [Description("Increase scroll speed")] IncreaseScrollSpeed, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.DecreaseScrollSpeed))] [Description("Decrease scroll speed")] DecreaseScrollSpeed, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.Select))] [Description("Select")] Select, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.QuickExit))] [Description("Quick exit (hold)")] QuickExit, // Game-wide beatmap music controller keybindings + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.MusicNext))] [Description("Next track")] MusicNext, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.MusicPrev))] [Description("Previous track")] MusicPrev, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.MusicPlay))] [Description("Play / pause")] MusicPlay, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleNowPlaying))] [Description("Toggle now playing overlay")] ToggleNowPlaying, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SelectPrevious))] [Description("Previous selection")] SelectPrevious, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SelectNext))] [Description("Next selection")] SelectNext, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.Home))] [Description("Home")] Home, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleNotifications))] [Description("Toggle notifications")] ToggleNotifications, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.PauseGameplay))] [Description("Pause gameplay")] PauseGameplay, // Editor + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorSetupMode))] [Description("Setup mode")] EditorSetupMode, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorComposeMode))] [Description("Compose mode")] EditorComposeMode, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorDesignMode))] [Description("Design mode")] EditorDesignMode, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorTimingMode))] [Description("Timing mode")] EditorTimingMode, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.HoldForHUD))] [Description("Hold for HUD")] HoldForHUD, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.RandomSkin))] [Description("Random skin")] RandomSkin, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.TogglePauseReplay))] [Description("Pause / resume replay")] TogglePauseReplay, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleInGameInterface))] [Description("Toggle in-game interface")] ToggleInGameInterface, // Song select keybindings + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleModSelection))] [Description("Toggle Mod Select")] ToggleModSelection, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SelectNextRandom))] [Description("Random")] SelectNextRandom, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SelectPreviousRandom))] [Description("Rewind")] SelectPreviousRandom, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleBeatmapOptions))] [Description("Beatmap Options")] ToggleBeatmapOptions, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorVerifyMode))] [Description("Verify mode")] EditorVerifyMode, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorNudgeLeft))] [Description("Nudge selection left")] EditorNudgeLeft, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorNudgeRight))] [Description("Nudge selection right")] EditorNudgeRight, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleSkinEditor))] [Description("Toggle skin editor")] ToggleSkinEditor, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.PreviousVolumeMeter))] [Description("Previous volume meter")] PreviousVolumeMeter, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.NextVolumeMeter))] [Description("Next volume meter")] NextVolumeMeter, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SeekReplayForward))] [Description("Seek replay forward")] SeekReplayForward, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SeekReplayBackward))] [Description("Seek replay backward")] SeekReplayBackward, + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleChatFocus))] [Description("Toggle chat focus")] ToggleChatFocus } diff --git a/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs b/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs new file mode 100644 index 0000000000..14159f0d34 --- /dev/null +++ b/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs @@ -0,0 +1,254 @@ +// 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.Localisation; + +namespace osu.Game.Localisation +{ + public static class GlobalActionKeyBindingStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.GlobalActionKeyBinding"; + + /// + /// "Toggle chat overlay" + /// + public static LocalisableString ToggleChat => new TranslatableString(getKey(@"toggle_chat"), @"Toggle chat overlay"); + + /// + /// "Toggle social overlay" + /// + public static LocalisableString ToggleSocial => new TranslatableString(getKey(@"toggle_social"), @"Toggle social overlay"); + + /// + /// "Reset input settings" + /// + public static LocalisableString ResetInputSettings => new TranslatableString(getKey(@"reset_input_settings"), @"Reset input settings"); + + /// + /// "Toggle toolbar" + /// + public static LocalisableString ToggleToolbar => new TranslatableString(getKey(@"toggle_toolbar"), @"Toggle toolbar"); + + /// + /// "Toggle settings" + /// + public static LocalisableString ToggleSettings => new TranslatableString(getKey(@"toggle_settings"), @"Toggle settings"); + + /// + /// "Toggle beatmap listing" + /// + public static LocalisableString ToggleBeatmapListing => new TranslatableString(getKey(@"toggle_beatmap_listing"), @"Toggle beatmap listing"); + + /// + /// "Increase volume" + /// + public static LocalisableString IncreaseVolume => new TranslatableString(getKey(@"increase_volume"), @"Increase volume"); + + /// + /// "Decrease volume" + /// + public static LocalisableString DecreaseVolume => new TranslatableString(getKey(@"decrease_volume"), @"Decrease volume"); + + /// + /// "Toggle mute" + /// + public static LocalisableString ToggleMute => new TranslatableString(getKey(@"toggle_mute"), @"Toggle mute"); + + /// + /// "Skip cutscene" + /// + public static LocalisableString SkipCutscene => new TranslatableString(getKey(@"skip_cutscene"), @"Skip cutscene"); + + /// + /// "Quick retry (hold)" + /// + public static LocalisableString QuickRetry => new TranslatableString(getKey(@"quick_retry"), @"Quick retry (hold)"); + + /// + /// "Take screenshot" + /// + public static LocalisableString TakeScreenshot => new TranslatableString(getKey(@"take_screenshot"), @"Take screenshot"); + + /// + /// "Toggle gameplay mouse buttons" + /// + public static LocalisableString ToggleGameplayMouseButtons => new TranslatableString(getKey(@"toggle_gameplay_mouse_buttons"), @"Toggle gameplay mouse buttons"); + + /// + /// "Back" + /// + public static LocalisableString Back => new TranslatableString(getKey(@"back"), @"Back"); + + /// + /// "Increase scroll speed" + /// + public static LocalisableString IncreaseScrollSpeed => new TranslatableString(getKey(@"increase_scroll_speed"), @"Increase scroll speed"); + + /// + /// "Decrease scroll speed" + /// + public static LocalisableString DecreaseScrollSpeed => new TranslatableString(getKey(@"decrease_scroll_speed"), @"Decrease scroll speed"); + + /// + /// "Select" + /// + public static LocalisableString Select => new TranslatableString(getKey(@"select"), @"Select"); + + /// + /// "Quick exit (hold)" + /// + public static LocalisableString QuickExit => new TranslatableString(getKey(@"quick_exit"), @"Quick exit (hold)"); + + /// + /// "Next track" + /// + public static LocalisableString MusicNext => new TranslatableString(getKey(@"music_next"), @"Next track"); + + /// + /// "Previous track" + /// + public static LocalisableString MusicPrev => new TranslatableString(getKey(@"music_prev"), @"Previous track"); + + /// + /// "Play / pause" + /// + public static LocalisableString MusicPlay => new TranslatableString(getKey(@"music_play"), @"Play / pause"); + + /// + /// "Toggle now playing overlay" + /// + public static LocalisableString ToggleNowPlaying => new TranslatableString(getKey(@"toggle_now_playing"), @"Toggle now playing overlay"); + + /// + /// "Previous selection" + /// + public static LocalisableString SelectPrevious => new TranslatableString(getKey(@"select_previous"), @"Previous selection"); + + /// + /// "Next selection" + /// + public static LocalisableString SelectNext => new TranslatableString(getKey(@"select_next"), @"Next selection"); + + /// + /// "Home" + /// + public static LocalisableString Home => new TranslatableString(getKey(@"home"), @"Home"); + + /// + /// "Toggle notifications" + /// + public static LocalisableString ToggleNotifications => new TranslatableString(getKey(@"toggle_notifications"), @"Toggle notifications"); + + /// + /// "Pause gameplay" + /// + public static LocalisableString PauseGameplay => new TranslatableString(getKey(@"pause_gameplay"), @"Pause gameplay"); + + /// + /// "Setup mode" + /// + public static LocalisableString EditorSetupMode => new TranslatableString(getKey(@"editor_setup_mode"), @"Setup mode"); + + /// + /// "Compose mode" + /// + public static LocalisableString EditorComposeMode => new TranslatableString(getKey(@"editor_compose_mode"), @"Compose mode"); + + /// + /// "Design mode" + /// + public static LocalisableString EditorDesignMode => new TranslatableString(getKey(@"editor_design_mode"), @"Design mode"); + + /// + /// "Timing mode" + /// + public static LocalisableString EditorTimingMode => new TranslatableString(getKey(@"editor_timing_mode"), @"Timing mode"); + + /// + /// "Hold for HUD" + /// + public static LocalisableString HoldForHUD => new TranslatableString(getKey(@"hold_for_hud"), @"Hold for HUD"); + + /// + /// "Random skin" + /// + public static LocalisableString RandomSkin => new TranslatableString(getKey(@"random_skin"), @"Random skin"); + + /// + /// "Pause / resume replay" + /// + public static LocalisableString TogglePauseReplay => new TranslatableString(getKey(@"toggle_pause_replay"), @"Pause / resume replay"); + + /// + /// "Toggle in-game interface" + /// + public static LocalisableString ToggleInGameInterface => new TranslatableString(getKey(@"toggle_in_game_interface"), @"Toggle in-game interface"); + + /// + /// "Toggle Mod Select" + /// + public static LocalisableString ToggleModSelection => new TranslatableString(getKey(@"toggle_mod_selection"), @"Toggle Mod Select"); + + /// + /// "Random" + /// + public static LocalisableString SelectNextRandom => new TranslatableString(getKey(@"select_next_random"), @"Random"); + + /// + /// "Rewind" + /// + public static LocalisableString SelectPreviousRandom => new TranslatableString(getKey(@"select_previous_random"), @"Rewind"); + + /// + /// "Beatmap Options" + /// + public static LocalisableString ToggleBeatmapOptions => new TranslatableString(getKey(@"toggle_beatmap_options"), @"Beatmap Options"); + + /// + /// "Verify mode" + /// + public static LocalisableString EditorVerifyMode => new TranslatableString(getKey(@"editor_verify_mode"), @"Verify mode"); + + /// + /// "Nudge selection left" + /// + public static LocalisableString EditorNudgeLeft => new TranslatableString(getKey(@"editor_nudge_left"), @"Nudge selection left"); + + /// + /// "Nudge selection right" + /// + public static LocalisableString EditorNudgeRight => new TranslatableString(getKey(@"editor_nudge_right"), @"Nudge selection right"); + + /// + /// "Toggle skin editor" + /// + public static LocalisableString ToggleSkinEditor => new TranslatableString(getKey(@"toggle_skin_editor"), @"Toggle skin editor"); + + /// + /// "Previous volume meter" + /// + public static LocalisableString PreviousVolumeMeter => new TranslatableString(getKey(@"previous_volume_meter"), @"Previous volume meter"); + + /// + /// "Next volume meter" + /// + public static LocalisableString NextVolumeMeter => new TranslatableString(getKey(@"next_volume_meter"), @"Next volume meter"); + + /// + /// "Seek replay forward" + /// + public static LocalisableString SeekReplayForward => new TranslatableString(getKey(@"seek_replay_forward"), @"Seek replay forward"); + + /// + /// "Seek replay backward" + /// + public static LocalisableString SeekReplayBackward => new TranslatableString(getKey(@"seek_replay_backward"), @"Seek replay backward"); + + /// + /// "Toggle chat focus" + /// + public static LocalisableString ToggleChatFocus => new TranslatableString(getKey(@"toggle_chat_focus"), @"Toggle chat focus"); + + private static string getKey(string key) => $"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs index c38c516f21..85d88c96f8 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs @@ -115,7 +115,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input }, text = new OsuSpriteText { - Text = action.GetDescription(), + Text = action.GetLocalisableDescription(), Margin = new MarginPadding(padding), }, buttons = new FillFlowContainer From 18e7d86dd4cd60fd81aeff9fd5b7b42723ebd63e Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 16 Sep 2021 17:08:19 +0800 Subject: [PATCH 079/109] Resolve test failure after localizing --- osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs index 57ba051214..168d9fafcf 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs @@ -234,7 +234,7 @@ namespace osu.Game.Tests.Visual.Settings { AddAssert($"Check {name} is bound to {keyName}", () => { - var firstRow = panel.ChildrenOfType().First(r => r.ChildrenOfType().Any(s => s.Text == name)); + var firstRow = panel.ChildrenOfType().First(r => r.ChildrenOfType().Any(s => s.Text.ToString() == name)); var firstButton = firstRow.ChildrenOfType().First(); return firstButton.Text.Text == keyName; @@ -247,7 +247,7 @@ namespace osu.Game.Tests.Visual.Settings AddStep($"Scroll to {name}", () => { - var firstRow = panel.ChildrenOfType().First(r => r.ChildrenOfType().Any(s => s.Text == name)); + var firstRow = panel.ChildrenOfType().First(r => r.ChildrenOfType().Any(s => s.Text.ToString() == name)); firstButton = firstRow.ChildrenOfType().First(); panel.ChildrenOfType().First().ScrollTo(firstButton); From e323f10cd5334f19c9c2578f0e7ea5bd3f262373 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 16 Sep 2021 17:10:29 +0800 Subject: [PATCH 080/109] Remove unused [Description] --- .../Input/Bindings/GlobalActionContainer.cs | 48 ------------------- 1 file changed, 48 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 73d824a5d2..cfb377f74a 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -140,199 +140,151 @@ namespace osu.Game.Input.Bindings public enum GlobalAction { [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleChat))] - [Description("Toggle chat overlay")] ToggleChat, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleSocial))] - [Description("Toggle social overlay")] ToggleSocial, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ResetInputSettings))] - [Description("Reset input settings")] ResetInputSettings, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleToolbar))] - [Description("Toggle toolbar")] ToggleToolbar, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleSettings))] - [Description("Toggle settings")] ToggleSettings, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleBeatmapListing))] - [Description("Toggle beatmap listing")] ToggleBeatmapListing, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.IncreaseVolume))] - [Description("Increase volume")] IncreaseVolume, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.DecreaseVolume))] - [Description("Decrease volume")] DecreaseVolume, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleMute))] - [Description("Toggle mute")] ToggleMute, // In-Game Keybindings [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SkipCutscene))] - [Description("Skip cutscene")] SkipCutscene, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.QuickRetry))] - [Description("Quick retry (hold)")] QuickRetry, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.TakeScreenshot))] - [Description("Take screenshot")] TakeScreenshot, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleGameplayMouseButtons))] - [Description("Toggle gameplay mouse buttons")] ToggleGameplayMouseButtons, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.Back))] - [Description("Back")] Back, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.IncreaseScrollSpeed))] - [Description("Increase scroll speed")] IncreaseScrollSpeed, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.DecreaseScrollSpeed))] - [Description("Decrease scroll speed")] DecreaseScrollSpeed, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.Select))] - [Description("Select")] Select, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.QuickExit))] - [Description("Quick exit (hold)")] QuickExit, // Game-wide beatmap music controller keybindings [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.MusicNext))] - [Description("Next track")] MusicNext, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.MusicPrev))] - [Description("Previous track")] MusicPrev, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.MusicPlay))] - [Description("Play / pause")] MusicPlay, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleNowPlaying))] - [Description("Toggle now playing overlay")] ToggleNowPlaying, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SelectPrevious))] - [Description("Previous selection")] SelectPrevious, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SelectNext))] - [Description("Next selection")] SelectNext, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.Home))] - [Description("Home")] Home, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleNotifications))] - [Description("Toggle notifications")] ToggleNotifications, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.PauseGameplay))] - [Description("Pause gameplay")] PauseGameplay, // Editor [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorSetupMode))] - [Description("Setup mode")] EditorSetupMode, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorComposeMode))] - [Description("Compose mode")] EditorComposeMode, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorDesignMode))] - [Description("Design mode")] EditorDesignMode, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorTimingMode))] - [Description("Timing mode")] EditorTimingMode, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.HoldForHUD))] - [Description("Hold for HUD")] HoldForHUD, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.RandomSkin))] - [Description("Random skin")] RandomSkin, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.TogglePauseReplay))] - [Description("Pause / resume replay")] TogglePauseReplay, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleInGameInterface))] - [Description("Toggle in-game interface")] ToggleInGameInterface, // Song select keybindings [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleModSelection))] - [Description("Toggle Mod Select")] ToggleModSelection, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SelectNextRandom))] - [Description("Random")] SelectNextRandom, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SelectPreviousRandom))] - [Description("Rewind")] SelectPreviousRandom, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleBeatmapOptions))] - [Description("Beatmap Options")] ToggleBeatmapOptions, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorVerifyMode))] - [Description("Verify mode")] EditorVerifyMode, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorNudgeLeft))] - [Description("Nudge selection left")] EditorNudgeLeft, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorNudgeRight))] - [Description("Nudge selection right")] EditorNudgeRight, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleSkinEditor))] - [Description("Toggle skin editor")] ToggleSkinEditor, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.PreviousVolumeMeter))] - [Description("Previous volume meter")] PreviousVolumeMeter, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.NextVolumeMeter))] - [Description("Next volume meter")] NextVolumeMeter, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SeekReplayForward))] - [Description("Seek replay forward")] SeekReplayForward, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SeekReplayBackward))] - [Description("Seek replay backward")] SeekReplayBackward, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleChatFocus))] - [Description("Toggle chat focus")] ToggleChatFocus } } From f9d5abff8a8d3b6752343c185eb7767a3944a532 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 16 Sep 2021 18:26:12 +0900 Subject: [PATCH 081/109] Update with keybinding changes --- .../UI/PippidonCharacter.cs | 7 ++++--- osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs | 4 ++-- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 9 +++++---- .../Objects/Drawables/DrawableHoldNote.cs | 9 +++++---- .../Objects/Drawables/DrawableHoldNoteHead.cs | 5 +++-- .../Objects/Drawables/DrawableHoldNoteTail.cs | 5 +++-- .../Objects/Drawables/DrawableNote.cs | 7 ++++--- .../Skinning/Legacy/LegacyColumnBackground.cs | 9 +++++---- .../Skinning/Legacy/LegacyKeyArea.cs | 9 +++++---- osu.Game.Rulesets.Mania/UI/Column.cs | 7 ++++--- .../UI/Components/ColumnBackground.cs | 9 +++++---- .../UI/Components/DefaultColumnBackground.cs | 9 +++++---- .../UI/Components/DefaultKeyArea.cs | 9 +++++---- .../Components/PathControlPointVisualiser.cs | 6 +++--- .../Objects/Drawables/DrawableHitCircle.cs | 9 +++++---- .../UI/Cursor/OsuCursorContainer.cs | 9 +++++---- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 6 +++--- .../DrawableTestHit.cs | 3 ++- .../DrawableTestStrongHit.cs | 3 ++- .../Objects/Drawables/DrawableDrumRoll.cs | 5 +++-- .../Objects/Drawables/DrawableDrumRollTick.cs | 7 ++++--- .../Objects/Drawables/DrawableHit.cs | 17 +++++++++-------- .../Objects/Drawables/DrawableSwell.cs | 5 +++-- .../Objects/Drawables/DrawableSwellTick.cs | 3 ++- .../Objects/Drawables/DrawableTaikoHitObject.cs | 5 +++-- .../Skinning/Legacy/LegacyInputDrum.cs | 9 +++++---- osu.Game.Rulesets.Taiko/UI/InputDrum.cs | 9 +++++---- .../Visual/Gameplay/TestSceneKeyBindings.cs | 7 ++++--- .../Visual/Gameplay/TestSceneReplayRecorder.cs | 4 ++-- .../Visual/Gameplay/TestSceneReplayRecording.cs | 4 ++-- .../Gameplay/TestSceneSpectatorPlayback.cs | 4 ++-- .../Containers/OsuFocusedOverlayContainer.cs | 6 +++--- osu.Game/Graphics/ScreenshotManager.cs | 7 ++++--- osu.Game/Graphics/UserInterface/BackButton.cs | 7 ++++--- .../Graphics/UserInterface/FocusedTextBox.cs | 6 +++--- .../Graphics/UserInterface/SearchTextBox.cs | 6 +++--- osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs | 7 ++++--- osu.Game/Input/IdleTracker.cs | 8 ++++---- osu.Game/OsuGame.cs | 7 ++++--- .../BeatmapListingSearchControl.cs | 4 ++-- osu.Game/Overlays/ChangelogOverlay.cs | 5 +++-- osu.Game/Overlays/ChatOverlay.cs | 6 +++--- osu.Game/Overlays/DialogOverlay.cs | 7 ++++--- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 +- .../Overlays/Music/MusicKeyBindingHandler.cs | 15 ++++++++------- osu.Game/Overlays/Toolbar/Toolbar.cs | 6 +++--- osu.Game/Overlays/Toolbar/ToolbarButton.cs | 6 +++--- .../Overlays/Volume/VolumeControlReceptor.cs | 14 +++++++------- osu.Game/Overlays/Volume/VolumeMeter.cs | 6 +++--- osu.Game/Rulesets/UI/ReplayRecorder.cs | 8 ++++---- osu.Game/Rulesets/UI/RulesetInputManager.cs | 6 +++--- .../UI/Scrolling/DrawableScrollingRuleset.cs | 7 ++++--- .../Compose/Components/BlueprintContainer.cs | 6 +++--- .../Edit/Compose/Components/SelectionHandler.cs | 6 +++--- .../Timeline/TimelineSelectionHandler.cs | 7 ++++--- osu.Game/Screens/Edit/Compose/ComposeScreen.cs | 7 ++++--- osu.Game/Screens/Edit/Editor.cs | 12 ++++++------ osu.Game/Screens/Menu/ButtonSystem.cs | 6 +++--- osu.Game/Screens/Menu/ExitConfirmOverlay.cs | 9 +++++---- .../Lounge/Components/RoomsContainer.cs | 14 +++++++------- .../OnlinePlay/Lounge/DrawableLoungeRoom.cs | 6 +++--- .../Match/Components/CreateRoomButton.cs | 7 ++++--- .../Match/Components/RoomSettingsOverlay.cs | 7 ++++--- .../Multiplayer/GameplayChatDisplay.cs | 6 +++--- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 6 +++--- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 8 ++++---- osu.Game/Screens/Play/HUDOverlay.cs | 9 +++++---- osu.Game/Screens/Play/HotkeyExitOverlay.cs | 9 +++++---- osu.Game/Screens/Play/HotkeyRetryOverlay.cs | 9 +++++---- osu.Game/Screens/Play/ReplayPlayer.cs | 9 +++++---- osu.Game/Screens/Play/SkipOverlay.cs | 6 +++--- osu.Game/Screens/Ranking/ResultsScreen.cs | 7 ++++--- osu.Game/Screens/Select/BeatmapCarousel.cs | 14 +++++++------- osu.Game/Screens/Select/FooterButton.cs | 6 +++--- osu.Game/Screens/Select/FooterButtonRandom.cs | 11 ++++++----- osu.Game/Screens/Select/SongSelect.cs | 6 +++--- osu.Game/Skinning/Editor/SkinEditorOverlay.cs | 7 ++++--- 77 files changed, 302 insertions(+), 257 deletions(-) diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/PippidonCharacter.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/PippidonCharacter.cs index dd0a20f1b4..98dba622d0 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/PippidonCharacter.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/UI/PippidonCharacter.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Containers; using osuTK; @@ -61,9 +62,9 @@ namespace osu.Game.Rulesets.Pippidon.UI } } - public bool OnPressed(PippidonAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case PippidonAction.MoveUp: changeLane(-1); @@ -78,7 +79,7 @@ namespace osu.Game.Rulesets.Pippidon.UI } } - public void OnReleased(PippidonAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs index 73b60f51a4..d0a94767d1 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -44,9 +44,9 @@ namespace osu.Game.Rulesets.Catch.Mods } // disable keyboard controls - public bool OnPressed(CatchAction action) => true; + public bool OnPressed(KeyBindingPressEvent e) => true; - public void OnReleased(CatchAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index b30c3d82a4..604e878782 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Catch.Replays; @@ -144,9 +145,9 @@ namespace osu.Game.Rulesets.Catch.UI Catcher.VisualDirection = Direction.Left; } - public bool OnPressed(CatchAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case CatchAction.MoveLeft: currentDirection--; @@ -164,9 +165,9 @@ namespace osu.Game.Rulesets.Catch.UI return false; } - public void OnReleased(CatchAction action) + public void OnReleased(KeyBindingReleaseEvent e) { - switch (action) + switch (e.Action) { case CatchAction.MoveLeft: currentDirection++; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 2923a2af2f..4e9781f336 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -7,6 +7,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Mania.Skinning.Default; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -253,12 +254,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables HoldBrokenTime = Time.Current; } - public bool OnPressed(ManiaAction action) + public bool OnPressed(KeyBindingPressEvent e) { if (AllJudged) return false; - if (action != Action.Value) + if (e.Action != Action.Value) return false; // do not run any of this logic when rewinding, as it inverts order of presses/releases. @@ -288,12 +289,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables isHitting.Value = true; } - public void OnReleased(ManiaAction action) + public void OnReleased(KeyBindingReleaseEvent e) { if (AllJudged) return; - if (action != Action.Value) + if (e.Action != Action.Value) return; // do not run any of this logic when rewinding, as it inverts order of presses/releases. diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs index 8458345998..6722ad8ab8 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Objects.Drawables @@ -43,9 +44,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables // it will be hidden along with its parenting hold note when required. } - public override bool OnPressed(ManiaAction action) => false; // Handled by the hold note + public override bool OnPressed(KeyBindingPressEvent e) => false; // Handled by the hold note - public override void OnReleased(ManiaAction action) + public override void OnReleased(KeyBindingReleaseEvent e) { } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs index 18aa3f66d4..803685363c 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Objects.Drawables @@ -68,9 +69,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }); } - public override bool OnPressed(ManiaAction action) => false; // Handled by the hold note + public override bool OnPressed(KeyBindingPressEvent e) => false; // Handled by the hold note - public override void OnReleased(ManiaAction action) + public override void OnReleased(KeyBindingReleaseEvent e) { } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index d53c28868d..51727908c9 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Configuration; @@ -97,9 +98,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables ApplyResult(r => r.Type = result); } - public virtual bool OnPressed(ManiaAction action) + public virtual bool OnPressed(KeyBindingPressEvent e) { - if (action != Action.Value) + if (e.Action != Action.Value) return false; if (CheckHittable?.Invoke(this, Time.Current) == false) @@ -108,7 +109,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables return UpdateResult(true); } - public virtual void OnReleased(ManiaAction action) + public virtual void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs index 661e7f66f4..54ddcbd5fe 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Skinning; using osuTK; @@ -76,9 +77,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy } } - public bool OnPressed(ManiaAction action) + public bool OnPressed(KeyBindingPressEvent e) { - if (action == Column.Action.Value) + if (e.Action == Column.Action.Value) { light.FadeIn(); light.ScaleTo(Vector2.One); @@ -87,12 +88,12 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy return false; } - public void OnReleased(ManiaAction action) + public void OnReleased(KeyBindingReleaseEvent e) { // Todo: Should be 400 * 100 / CurrentBPM const double animation_length = 250; - if (action == Column.Action.Value) + if (e.Action == Column.Action.Value) { light.FadeTo(0, animation_length); light.ScaleTo(new Vector2(1, 0), animation_length); diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs index 10319a7d4d..9c339345c4 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Skinning; @@ -86,9 +87,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy } } - public bool OnPressed(ManiaAction action) + public bool OnPressed(KeyBindingPressEvent e) { - if (action == column.Action.Value) + if (e.Action == column.Action.Value) { upSprite.FadeTo(0); downSprite.FadeTo(1); @@ -97,9 +98,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy return false; } - public void OnReleased(ManiaAction action) + public void OnReleased(KeyBindingReleaseEvent e) { - if (action == column.Action.Value) + if (e.Action == column.Action.Value) { upSprite.Delay(LegacyHitExplosion.FADE_IN_DURATION).FadeTo(1); downSprite.Delay(LegacyHitExplosion.FADE_IN_DURATION).FadeTo(0); diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index f5e30efd91..9d060944cd 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -10,6 +10,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Pooling; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; @@ -122,16 +123,16 @@ namespace osu.Game.Rulesets.Mania.UI HitObjectArea.Explosions.Add(hitExplosionPool.Get(e => e.Apply(result))); } - public bool OnPressed(ManiaAction action) + public bool OnPressed(KeyBindingPressEvent e) { - if (action != Action.Value) + if (e.Action != Action.Value) return false; sampleTriggerSource.Play(); return true; } - public void OnReleased(ManiaAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index 75cc351310..77ddc6fbbf 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Rulesets.UI.Scrolling; using osuTK.Graphics; @@ -91,16 +92,16 @@ namespace osu.Game.Rulesets.Mania.UI.Components direction.Value == ScrollingDirection.Up ? dimPoint : brightPoint); } - public bool OnPressed(ManiaAction action) + public bool OnPressed(KeyBindingPressEvent e) { - if (action == this.action.Value) + if (e.Action == action.Value) backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint); return false; } - public void OnReleased(ManiaAction action) + public void OnReleased(KeyBindingReleaseEvent e) { - if (action == this.action.Value) + if (e.Action == action.Value) backgroundOverlay.FadeTo(0, 250, Easing.OutQuint); } } diff --git a/osu.Game.Rulesets.Mania/UI/Components/DefaultColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/DefaultColumnBackground.cs index 4b4bc157d5..807f6a77d9 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/DefaultColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/DefaultColumnBackground.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Rulesets.UI.Scrolling; using osuTK.Graphics; @@ -74,16 +75,16 @@ namespace osu.Game.Rulesets.Mania.UI.Components } } - public bool OnPressed(ManiaAction action) + public bool OnPressed(KeyBindingPressEvent e) { - if (action == column.Action.Value) + if (e.Action == column.Action.Value) backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint); return false; } - public void OnReleased(ManiaAction action) + public void OnReleased(KeyBindingReleaseEvent e) { - if (action == column.Action.Value) + if (e.Action == column.Action.Value) backgroundOverlay.FadeTo(0, 250, Easing.OutQuint); } } diff --git a/osu.Game.Rulesets.Mania/UI/Components/DefaultKeyArea.cs b/osu.Game.Rulesets.Mania/UI/Components/DefaultKeyArea.cs index 47cb9bd45a..267ed1f5f4 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/DefaultKeyArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/DefaultKeyArea.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Rulesets.UI.Scrolling; using osuTK; using osuTK.Graphics; @@ -101,16 +102,16 @@ namespace osu.Game.Rulesets.Mania.UI.Components } } - public bool OnPressed(ManiaAction action) + public bool OnPressed(KeyBindingPressEvent e) { - if (action == column.Action.Value) + if (e.Action == column.Action.Value) keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint).Then().ScaleTo(1.3f, 250, Easing.OutQuint); return false; } - public void OnReleased(ManiaAction action) + public void OnReleased(KeyBindingReleaseEvent e) { - if (action == column.Action.Value) + if (e.Action == column.Action.Value) keyIcon.ScaleTo(1f, 125, Easing.OutQuint); } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 6269a41350..1be9b5bf2e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -127,9 +127,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return false; } - public bool OnPressed(PlatformAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case PlatformAction.Delete: return DeleteSelected(); @@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return false; } - public void OnReleased(PlatformAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 46fc8f99b2..b6ac62d370 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Judgements; @@ -228,15 +229,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables CornerExponent = 2; } - public bool OnPressed(OsuAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case OsuAction.LeftButton: case OsuAction.RightButton: if (IsHovered && (Hit?.Invoke() ?? false)) { - HitAction = action; + HitAction = e.Action; return true; } @@ -246,7 +247,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return false; } - public void OnReleased(OsuAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } } diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 5812e8cf75..8c76f8a128 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets.Osu.Configuration; @@ -115,9 +116,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor (ActiveCursor as OsuCursor)?.Contract(); } - public bool OnPressed(OsuAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case OsuAction.LeftButton: case OsuAction.RightButton: @@ -129,9 +130,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor return false; } - public void OnReleased(OsuAction action) + public void OnReleased(KeyBindingReleaseEvent e) { - switch (action) + switch (e.Action) { case OsuAction.LeftButton: case OsuAction.RightButton: diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 27d48d1296..4d4340936d 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -89,9 +89,9 @@ namespace osu.Game.Rulesets.Osu.UI base.OnHoverLost(e); } - public bool OnPressed(OsuAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case OsuAction.LeftButton: case OsuAction.RightButton: @@ -106,7 +106,7 @@ namespace osu.Game.Rulesets.Osu.UI return false; } - public void OnReleased(OsuAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs b/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs index f048cad18c..6d4cac0ebe 100644 --- a/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs +++ b/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs @@ -1,6 +1,7 @@ // 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.Input.Events; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Scoring; @@ -37,6 +38,6 @@ namespace osu.Game.Rulesets.Taiko.Tests Result.Type = Type; } - public override bool OnPressed(TaikoAction action) => false; + public override bool OnPressed(KeyBindingPressEvent e) => false; } } diff --git a/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs b/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs index 829bcf34a1..ea877c9e17 100644 --- a/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs +++ b/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; @@ -30,6 +31,6 @@ namespace osu.Game.Rulesets.Taiko.Tests nestedStrongHit.Result.Type = hitBoth ? Type : HitResult.Miss; } - public override bool OnPressed(TaikoAction action) => false; + public override bool OnPressed(KeyBindingPressEvent e) => false; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index d066abf767..521189d36c 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -11,6 +11,7 @@ using osu.Game.Rulesets.Objects.Drawables; using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; @@ -112,7 +113,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override SkinnableDrawable CreateMainPiece() => new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.DrumRollBody), _ => new ElongatedCirclePiece()); - public override bool OnPressed(TaikoAction action) => false; + public override bool OnPressed(KeyBindingPressEvent e) => false; private void onNewResult(DrawableHitObject obj, JudgementResult result) { @@ -196,7 +197,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables ApplyResult(r => r.Type = ParentHitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult); } - public override bool OnPressed(TaikoAction action) => false; + public override bool OnPressed(KeyBindingPressEvent e) => false; } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index 0df45c424d..dc2ed200a1 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -4,6 +4,7 @@ using System; using JetBrains.Annotations; using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Skinning.Default; using osu.Game.Skinning; @@ -61,9 +62,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - public override bool OnPressed(TaikoAction action) + public override bool OnPressed(KeyBindingPressEvent e) { - JudgementType = action == TaikoAction.LeftRim || action == TaikoAction.RightRim ? HitType.Rim : HitType.Centre; + JudgementType = e.Action == TaikoAction.LeftRim || e.Action == TaikoAction.RightRim ? HitType.Rim : HitType.Centre; return UpdateResult(true); } @@ -91,7 +92,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables ApplyResult(r => r.Type = ParentHitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult); } - public override bool OnPressed(TaikoAction action) => false; + public override bool OnPressed(KeyBindingPressEvent e) => false; } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 1e9fc187eb..97adc5f197 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -8,6 +8,7 @@ using System.Linq; using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osu.Game.Audio; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; @@ -145,19 +146,19 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables ApplyResult(r => r.Type = result); } - public override bool OnPressed(TaikoAction action) + public override bool OnPressed(KeyBindingPressEvent e) { if (pressHandledThisFrame) return true; if (Judged) return false; - validActionPressed = HitActions.Contains(action); + validActionPressed = HitActions.Contains(e.Action); // Only count this as handled if the new judgement is a hit var result = UpdateResult(true); if (IsHit) - HitAction = action; + HitAction = e.Action; // Regardless of whether we've hit or not, any secondary key presses in the same frame should be discarded // E.g. hitting a non-strong centre as a strong should not fall through and perform a hit on the next note @@ -165,11 +166,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return result; } - public override void OnReleased(TaikoAction action) + public override void OnReleased(KeyBindingReleaseEvent e) { - if (action == HitAction) + if (e.Action == HitAction) HitAction = null; - base.OnReleased(action); + base.OnReleased(e); } protected override void Update() @@ -265,7 +266,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables ApplyResult(r => r.Type = r.Judgement.MaxResult); } - public override bool OnPressed(TaikoAction action) + public override bool OnPressed(KeyBindingPressEvent e) { // Don't process actions until the main hitobject is hit if (!ParentHitObject.IsHit) @@ -276,7 +277,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return false; // Don't handle invalid hit action presses - if (!ParentHitObject.HitActions.Contains(action)) + if (!ParentHitObject.HitActions.Contains(e.Action)) return false; return UpdateResult(true); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 888f47d341..2d19296d06 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -12,6 +12,7 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Skinning.Default; @@ -266,13 +267,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private bool? lastWasCentre; - public override bool OnPressed(TaikoAction action) + public override bool OnPressed(KeyBindingPressEvent e) { // Don't handle keys before the swell starts if (Time.Current < HitObject.StartTime) return false; - var isCentre = action == TaikoAction.LeftCentre || action == TaikoAction.RightCentre; + var isCentre = e.Action == TaikoAction.LeftCentre || e.Action == TaikoAction.RightCentre; // Ensure alternating centre and rim hits if (lastWasCentre == isCentre) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index 47fc7e5ab3..d4ea9ed29f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -3,6 +3,7 @@ using JetBrains.Annotations; using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Taiko.Skinning.Default; using osu.Game.Skinning; @@ -34,7 +35,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { } - public override bool OnPressed(TaikoAction action) => false; + public override bool OnPressed(KeyBindingPressEvent e) => false; protected override SkinnableDrawable CreateMainPiece() => new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.DrumRollTick), _ => new TickPiece()); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 6a8d8a611c..eb64ba72f2 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Audio; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Skinning; @@ -76,9 +77,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// public Drawable CreateProxiedContent() => proxiedContent.CreateProxy(); - public abstract bool OnPressed(TaikoAction action); + public abstract bool OnPressed(KeyBindingPressEvent e); - public virtual void OnReleased(TaikoAction action) + public virtual void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs index 9d35093591..86be40dea8 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.UI; using osu.Game.Skinning; @@ -141,16 +142,16 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy Centre.Texture = skin.GetTexture(@"taiko-drum-inner"); } - public bool OnPressed(TaikoAction action) + public bool OnPressed(KeyBindingPressEvent e) { Drawable target = null; - if (action == CentreAction) + if (e.Action == CentreAction) { target = Centre; sampleTriggerSource.Play(HitType.Centre); } - else if (action == RimAction) + else if (e.Action == RimAction) { target = Rim; sampleTriggerSource.Play(HitType.Rim); @@ -173,7 +174,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy return false; } - public void OnReleased(TaikoAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } } diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index ddfaf64549..861b800038 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.UI; @@ -151,19 +152,19 @@ namespace osu.Game.Rulesets.Taiko.UI [Resolved(canBeNull: true)] private GameplayClock gameplayClock { get; set; } - public bool OnPressed(TaikoAction action) + public bool OnPressed(KeyBindingPressEvent e) { Drawable target = null; Drawable back = null; - if (action == CentreAction) + if (e.Action == CentreAction) { target = centreHit; back = centre; sampleTriggerSource.Play(HitType.Centre); } - else if (action == RimAction) + else if (e.Action == RimAction) { target = rimHit; back = rim; @@ -195,7 +196,7 @@ namespace osu.Game.Rulesets.Taiko.UI return false; } - public void OnReleased(TaikoAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyBindings.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyBindings.cs index 6de85499c5..0a39d94027 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyBindings.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyBindings.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Input.Bindings; @@ -80,13 +81,13 @@ namespace osu.Game.Tests.Visual.Gameplay { public bool ReceivedAction; - public bool OnPressed(TestAction action) + public bool OnPressed(KeyBindingPressEvent e) { - ReceivedAction = action == TestAction.Down; + ReceivedAction = e.Action == TestAction.Down; return true; } - public void OnReleased(TestAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs index 2ce0213ea2..0a3fedaf8e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs @@ -226,13 +226,13 @@ namespace osu.Game.Tests.Visual.Gameplay return base.OnMouseMove(e); } - public bool OnPressed(TestAction action) + public bool OnPressed(KeyBindingPressEvent e) { box.Colour = Color4.White; return true; } - public void OnReleased(TestAction action) + public void OnReleased(KeyBindingReleaseEvent e) { box.Colour = Color4.Black; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs index 85a2870bf9..dfd5e2dc58 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs @@ -159,13 +159,13 @@ namespace osu.Game.Tests.Visual.Gameplay return base.OnMouseMove(e); } - public bool OnPressed(TestAction action) + public bool OnPressed(KeyBindingPressEvent e) { box.Colour = Color4.White; return true; } - public void OnReleased(TestAction action) + public void OnReleased(KeyBindingReleaseEvent e) { box.Colour = Color4.Black; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs index d9d0dc6c58..6f5f774758 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs @@ -279,13 +279,13 @@ namespace osu.Game.Tests.Visual.Gameplay return base.OnMouseMove(e); } - public bool OnPressed(TestAction action) + public bool OnPressed(KeyBindingPressEvent e) { box.Colour = Color4.White; return true; } - public void OnReleased(TestAction action) + public void OnReleased(KeyBindingReleaseEvent e) { box.Colour = Color4.Black; } diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index b9b098df80..16ec7ab838 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -88,9 +88,9 @@ namespace osu.Game.Graphics.Containers base.OnMouseUp(e); } - public virtual bool OnPressed(GlobalAction action) + public virtual bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.Back: Hide(); @@ -103,7 +103,7 @@ namespace osu.Game.Graphics.Containers return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index fb7fe4947b..9cd403f409 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -12,6 +12,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Framework.Platform; using osu.Framework.Threading; using osu.Game.Configuration; @@ -57,9 +58,9 @@ namespace osu.Game.Graphics shutter = audio.Samples.Get("UI/shutter"); } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.TakeScreenshot: shutter.Play(); @@ -70,7 +71,7 @@ namespace osu.Game.Graphics return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 1607762908..c965fbcf45 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Input.Bindings; namespace osu.Game.Graphics.UserInterface @@ -61,9 +62,9 @@ namespace osu.Game.Graphics.UserInterface { public Action OnBackPressed; - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.Back: OnBackPressed?.Invoke(); @@ -73,7 +74,7 @@ namespace osu.Game.Graphics.UserInterface return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } } diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index 6c8238a1b8..ceea9620c8 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -70,11 +70,11 @@ namespace osu.Game.Graphics.UserInterface return base.OnKeyDown(e); } - public virtual bool OnPressed(GlobalAction action) + public virtual bool OnPressed(KeyBindingPressEvent e) { if (!HasFocus) return false; - if (action == GlobalAction.Back) + if (e.Action == GlobalAction.Back) { if (Text.Length > 0) { @@ -86,7 +86,7 @@ namespace osu.Game.Graphics.UserInterface return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index 4a91741ce6..6937782be6 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -30,9 +30,9 @@ namespace osu.Game.Graphics.UserInterface PlaceholderText = "type to search"; } - public override bool OnPressed(PlatformAction action) + public override bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case PlatformAction.MoveBackwardLine: case PlatformAction.MoveForwardLine: @@ -43,7 +43,7 @@ namespace osu.Game.Graphics.UserInterface return false; } - return base.OnPressed(action); + return base.OnPressed(e); } protected override bool OnKeyDown(KeyDownEvent e) diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs b/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs index 2cb696be0a..226c39c030 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Input.Bindings; using osu.Game.Overlays; using osuTK; @@ -55,12 +56,12 @@ namespace osu.Game.Graphics.UserInterfaceV2 this.FadeOut(fade_duration, Easing.OutQuint); } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { if (State.Value == Visibility.Hidden) return false; - if (action == GlobalAction.Back) + if (e.Action == GlobalAction.Back) { Hide(); return true; @@ -69,7 +70,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } } diff --git a/osu.Game/Input/IdleTracker.cs b/osu.Game/Input/IdleTracker.cs index f3d531cf6c..bfe21f650a 100644 --- a/osu.Game/Input/IdleTracker.cs +++ b/osu.Game/Input/IdleTracker.cs @@ -55,13 +55,13 @@ namespace osu.Game.Input isIdle.Value = TimeSpentIdle > timeToIdle && AllowIdle; } - public bool OnPressed(PlatformAction action) => updateLastInteractionTime(); + public bool OnPressed(KeyBindingPressEvent e) => updateLastInteractionTime(); - public void OnReleased(PlatformAction action) => updateLastInteractionTime(); + public void OnReleased(KeyBindingReleaseEvent e) => updateLastInteractionTime(); - public bool OnPressed(GlobalAction action) => updateLastInteractionTime(); + public bool OnPressed(KeyBindingPressEvent e) => updateLastInteractionTime(); - public void OnReleased(GlobalAction action) => updateLastInteractionTime(); + public void OnReleased(KeyBindingReleaseEvent e) => updateLastInteractionTime(); protected override bool Handle(UIEvent e) { diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ce84c4bd2a..0e55a65aec 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -27,6 +27,7 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Collections; @@ -968,11 +969,11 @@ namespace osu.Game return component; } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { if (introScreen == null) return false; - switch (action) + switch (e.Action) { case GlobalAction.ResetInputSettings: Host.ResetInputHandlers(); @@ -1006,7 +1007,7 @@ namespace osu.Game #endregion - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs index 07a0cfb57f..bbde03aa10 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs @@ -186,9 +186,9 @@ namespace osu.Game.Overlays.BeatmapListing return true; } - public override bool OnPressed(GlobalAction action) + public override bool OnPressed(KeyBindingPressEvent e) { - if (!base.OnPressed(action)) + if (!base.OnPressed(e)) return false; TextChanged?.Invoke(); diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index a8f2e654d7..ce12e9554d 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -10,6 +10,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osu.Game.Input.Bindings; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; @@ -91,9 +92,9 @@ namespace osu.Game.Overlays Show(); } - public override bool OnPressed(GlobalAction action) + public override bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.Back: if (Current.Value == null) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 0445c63eb4..25c5154d4a 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -372,9 +372,9 @@ namespace osu.Game.Overlays return base.OnKeyDown(e); } - public bool OnPressed(PlatformAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case PlatformAction.TabNew: ChannelTabControl.SelectChannelSelectorTab(); @@ -392,7 +392,7 @@ namespace osu.Game.Overlays return false; } - public void OnReleased(PlatformAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index 43ef42a809..d5d31343f2 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -7,6 +7,7 @@ using osu.Game.Overlays.Dialog; using osu.Game.Graphics.Containers; using osu.Game.Input.Bindings; using System.Linq; +using osu.Framework.Input.Events; namespace osu.Game.Overlays { @@ -83,16 +84,16 @@ namespace osu.Game.Overlays this.FadeOut(PopupDialog.EXIT_DURATION, Easing.InSine); } - public override bool OnPressed(GlobalAction action) + public override bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.Select: CurrentDialog?.Buttons.OfType().FirstOrDefault()?.TriggerClick(); return true; } - return base.OnPressed(action); + return base.OnPressed(e); } } } diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index fdef48d556..ec7e49920c 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -416,7 +416,7 @@ namespace osu.Game.Overlays.Mods return base.OnKeyDown(e); } - public override bool OnPressed(GlobalAction action) => false; // handled by back button + public override bool OnPressed(KeyBindingPressEvent e) => false; // handled by back button private void updateAvailableMods() { diff --git a/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs b/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs index f06e02e5e1..dba4bf926f 100644 --- a/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs +++ b/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Input.Bindings; @@ -26,23 +27,23 @@ namespace osu.Game.Overlays.Music [Resolved(canBeNull: true)] private OnScreenDisplay onScreenDisplay { get; set; } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { if (beatmap.Disabled) return false; - switch (action) + switch (e.Action) { case GlobalAction.MusicPlay: // use previous state as TogglePause may not update the track's state immediately (state update is run on the audio thread see https://github.com/ppy/osu/issues/9880#issuecomment-674668842) bool wasPlaying = musicController.IsPlaying; if (musicController.TogglePause()) - onScreenDisplay?.Display(new MusicActionToast(wasPlaying ? "Pause track" : "Play track", action)); + onScreenDisplay?.Display(new MusicActionToast(wasPlaying ? "Pause track" : "Play track", e.Action)); return true; case GlobalAction.MusicNext: - musicController.NextTrack(() => onScreenDisplay?.Display(new MusicActionToast("Next track", action))); + musicController.NextTrack(() => onScreenDisplay?.Display(new MusicActionToast("Next track", e.Action))); return true; @@ -52,11 +53,11 @@ namespace osu.Game.Overlays.Music switch (res) { case PreviousTrackResult.Restart: - onScreenDisplay?.Display(new MusicActionToast("Restart track", action)); + onScreenDisplay?.Display(new MusicActionToast("Restart track", e.Action)); break; case PreviousTrackResult.Previous: - onScreenDisplay?.Display(new MusicActionToast("Previous track", action)); + onScreenDisplay?.Display(new MusicActionToast("Previous track", e.Action)); break; } }); @@ -67,7 +68,7 @@ namespace osu.Game.Overlays.Music return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 7481cfdbf5..dc0b06b255 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -178,12 +178,12 @@ namespace osu.Game.Overlays.Toolbar this.FadeOut(transition_time, Easing.InQuint); } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { if (OverlayActivationMode.Value == OverlayActivation.Disabled) return false; - switch (action) + switch (e.Action) { case GlobalAction.ToggleToolbar: hiddenByUser = State.Value == Visibility.Visible; // set before toggling to allow the operation to always succeed. @@ -194,7 +194,7 @@ namespace osu.Game.Overlays.Toolbar return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index 6da41b2b5f..dd554200ca 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -184,9 +184,9 @@ namespace osu.Game.Overlays.Toolbar tooltipContainer.FadeOut(100); } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - if (action == Hotkey) + if (e.Action == Hotkey) { TriggerClick(); return true; @@ -195,7 +195,7 @@ namespace osu.Game.Overlays.Toolbar return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Overlays/Volume/VolumeControlReceptor.cs b/osu.Game/Overlays/Volume/VolumeControlReceptor.cs index b24214ff3d..4129b46ce3 100644 --- a/osu.Game/Overlays/Volume/VolumeControlReceptor.cs +++ b/osu.Game/Overlays/Volume/VolumeControlReceptor.cs @@ -19,27 +19,27 @@ namespace osu.Game.Overlays.Volume private ScheduledDelegate keyRepeat; - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.DecreaseVolume: case GlobalAction.IncreaseVolume: keyRepeat?.Cancel(); - keyRepeat = this.BeginKeyRepeat(Scheduler, () => ActionRequested?.Invoke(action), 150); + keyRepeat = this.BeginKeyRepeat(Scheduler, () => ActionRequested?.Invoke(e.Action), 150); return true; case GlobalAction.ToggleMute: case GlobalAction.NextVolumeMeter: case GlobalAction.PreviousVolumeMeter: - ActionRequested?.Invoke(action); + ActionRequested?.Invoke(e.Action); return true; } return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { keyRepeat?.Cancel(); } @@ -54,7 +54,7 @@ namespace osu.Game.Overlays.Volume return true; } - public bool OnScroll(GlobalAction action, float amount, bool isPrecise) => - ScrollActionRequested?.Invoke(action, amount, isPrecise) ?? false; + public bool OnScroll(KeyBindingScrollEvent e) => + ScrollActionRequested?.Invoke(e.Action, e.ScrollAmount, e.IsPrecise) ?? false; } } diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 7249dd77e5..ff28b45ebb 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -365,12 +365,12 @@ namespace osu.Game.Overlays.Volume { } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { if (!IsHovered) return false; - switch (action) + switch (e.Action) { case GlobalAction.SelectPrevious: State = SelectionState.Selected; @@ -386,7 +386,7 @@ namespace osu.Game.Overlays.Volume return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Rulesets/UI/ReplayRecorder.cs b/osu.Game/Rulesets/UI/ReplayRecorder.cs index d18e0f9541..b57c224059 100644 --- a/osu.Game/Rulesets/UI/ReplayRecorder.cs +++ b/osu.Game/Rulesets/UI/ReplayRecorder.cs @@ -70,16 +70,16 @@ namespace osu.Game.Rulesets.UI return base.OnMouseMove(e); } - public bool OnPressed(T action) + public bool OnPressed(KeyBindingPressEvent e) { - pressedActions.Add(action); + pressedActions.Add(e.Action); recordFrame(true); return false; } - public void OnReleased(T action) + public void OnReleased(KeyBindingReleaseEvent e) { - pressedActions.Remove(action); + pressedActions.Remove(e.Action); recordFrame(true); } diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index e6cd2aa3dc..a3f311c7a6 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -152,12 +152,12 @@ namespace osu.Game.Rulesets.UI { } - public bool OnPressed(T action) => Target.Children.OfType>().Any(c => c.OnPressed(action, Clock.Rate >= 0)); + public bool OnPressed(KeyBindingPressEvent e) => Target.Children.OfType>().Any(c => c.OnPressed(e.Action, Clock.Rate >= 0)); - public void OnReleased(T action) + public void OnReleased(KeyBindingReleaseEvent e) { foreach (var c in Target.Children.OfType>()) - c.OnReleased(action, Clock.Rate >= 0); + c.OnReleased(e.Action, Clock.Rate >= 0); } } diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index f8d5a6c5a9..7b30bb9574 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -8,6 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Framework.Lists; using osu.Framework.Threading; using osu.Game.Beatmaps; @@ -188,12 +189,12 @@ namespace osu.Game.Rulesets.UI.Scrolling /// The amount to adjust by. Greater than 0 if the scroll speed should be increased, less than 0 if it should be decreased. protected virtual void AdjustScrollSpeed(int amount) => this.TransformBindableTo(TimeRange, TimeRange.Value - amount * time_span_step, 200, Easing.OutQuint); - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { if (!UserScrollSpeedAdjustment) return false; - switch (action) + switch (e.Action) { case GlobalAction.IncreaseScrollSpeed: scheduleScrollSpeedAdjustment(1); @@ -209,7 +210,7 @@ namespace osu.Game.Rulesets.UI.Scrolling private ScheduledDelegate scheduledScrollSpeedAdjustment; - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { scheduledScrollSpeedAdjustment?.Cancel(); scheduledScrollSpeedAdjustment = null; diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index b99dacbd4a..75d4d13f94 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -228,9 +228,9 @@ namespace osu.Game.Screens.Edit.Compose.Components return false; } - public bool OnPressed(PlatformAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case PlatformAction.SelectAll: SelectAll(); @@ -240,7 +240,7 @@ namespace osu.Game.Screens.Edit.Compose.Components return false; } - public void OnReleased(PlatformAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 1d1d95890f..44eb062db8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -137,9 +137,9 @@ namespace osu.Game.Screens.Edit.Compose.Components /// Whether any items could be reversed. public virtual bool HandleReverse() => false; - public bool OnPressed(PlatformAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case PlatformAction.Delete: DeleteSelected(); @@ -149,7 +149,7 @@ namespace osu.Game.Screens.Edit.Compose.Components return false; } - public void OnReleased(PlatformAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineSelectionHandler.cs index 354013a5fd..c43e554b85 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineSelectionHandler.cs @@ -4,6 +4,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Input.Bindings; using osu.Game.Rulesets.Objects; using osuTK; @@ -20,9 +21,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline // for now we always allow movement. snapping is provided by the Timeline's "distance" snap implementation public override bool HandleMovement(MoveSelectionEvent moveEvent) => true; - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.EditorNudgeLeft: nudgeSelection(-1); @@ -36,7 +37,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index e324f1edeb..926a2ad4e0 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Extensions; @@ -77,15 +78,15 @@ namespace osu.Game.Screens.Edit.Compose #region Input Handling - public bool OnPressed(PlatformAction action) + public bool OnPressed(KeyBindingPressEvent e) { - if (action == PlatformAction.Copy) + if (e.Action == PlatformAction.Copy) host.GetClipboard()?.SetText(formatSelectionAsString()); return false; } - public void OnReleased(PlatformAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 028662172d..2ff0101dc0 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -347,9 +347,9 @@ namespace osu.Game.Screens.Edit clock.ProcessFrame(); } - public bool OnPressed(PlatformAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case PlatformAction.Cut: Cut(); @@ -379,7 +379,7 @@ namespace osu.Game.Screens.Edit return false; } - public void OnReleased(PlatformAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } @@ -434,9 +434,9 @@ namespace osu.Game.Screens.Edit return true; } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.Back: // as we don't want to display the back button, manual handling of exit action is required. @@ -468,7 +468,7 @@ namespace osu.Game.Screens.Edit } } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 6c712e9d5b..5f76176aab 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -218,9 +218,9 @@ namespace osu.Game.Screens.Menu return base.OnKeyDown(e); } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.Back: return goBack(); @@ -234,7 +234,7 @@ namespace osu.Game.Screens.Menu } } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs index a491283e5f..364da2f887 100644 --- a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs +++ b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Input.Bindings; using osu.Game.Overlays; @@ -18,9 +19,9 @@ namespace osu.Game.Screens.Menu { } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - if (action == GlobalAction.Back) + if (e.Action == GlobalAction.Back) { BeginConfirm(); return true; @@ -29,9 +30,9 @@ namespace osu.Game.Screens.Menu return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { - if (action == GlobalAction.Back) + if (e.Action == GlobalAction.Back) { if (!Fired) AbortConfirm(); diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index 76cb02199b..907b7e308a 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -141,29 +141,29 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components #region Key selection logic (shared with BeatmapCarousel) - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.SelectNext: - beginRepeatSelection(() => selectNext(1), action); + beginRepeatSelection(() => selectNext(1), e.Action); return true; case GlobalAction.SelectPrevious: - beginRepeatSelection(() => selectNext(-1), action); + beginRepeatSelection(() => selectNext(-1), e.Action); return true; } return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.SelectNext: case GlobalAction.SelectPrevious: - endRepeatSelection(action); + endRepeatSelection(e.Action); break; } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 95fa34ab43..d55cccd414 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -132,12 +132,12 @@ namespace osu.Game.Screens.OnlinePlay.Lounge }) }; - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { if (SelectedRoom.Value != Room) return false; - switch (action) + switch (e.Action) { case GlobalAction.Select: TriggerClick(); @@ -147,7 +147,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs b/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs index 3801463095..53131ab90e 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Input; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; namespace osu.Game.Screens.OnlinePlay.Match.Components { @@ -16,12 +17,12 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components Triangles.TriangleScale = 1.5f; } - public bool OnPressed(PlatformAction action) + public bool OnPressed(KeyBindingPressEvent e) { if (!Enabled.Value) return false; - switch (action) + switch (e.Action) { case PlatformAction.DocumentNew: // might as well also handle new tab. it's a bit of an undefined flow on this screen. @@ -33,7 +34,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components return false; } - public void OnReleased(PlatformAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } } diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs index 7a8839cdad..a6cdde14f6 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -63,9 +64,9 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components Settings.Delay(TRANSITION_DURATION / 2).FadeOut(TRANSITION_DURATION / 2); } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.Select: if (IsLoading) @@ -86,7 +87,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs index 3af72fa25a..af0c50a848 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs @@ -71,9 +71,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer }, true); } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.ToggleChatFocus: if (Textbox.HasFocus) @@ -94,7 +94,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 0efa66bac0..9e3400b09d 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -187,9 +187,9 @@ namespace osu.Game.Screens.Play InternalButtons.Add(button); } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.SelectPrevious: InternalButtons.SelectPrevious(); @@ -211,7 +211,7 @@ namespace osu.Game.Screens.Play return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 284ac899ed..850543136c 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -206,9 +206,9 @@ namespace osu.Game.Screens.Play.HUD base.OnHoverLost(e); } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.Back: case GlobalAction.PauseGameplay: // in the future this behaviour will differ for replays etc. @@ -220,9 +220,9 @@ namespace osu.Game.Screens.Play.HUD return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.Back: case GlobalAction.PauseGameplay: diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 13df9fefa7..54c74a7177 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -11,6 +11,7 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Configuration; using osu.Game.Input.Bindings; using osu.Game.Overlays; @@ -280,9 +281,9 @@ namespace osu.Game.Screens.Play protected PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.HoldForHUD: holdingForHUD = true; @@ -311,9 +312,9 @@ namespace osu.Game.Screens.Play return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.HoldForHUD: holdingForHUD = false; diff --git a/osu.Game/Screens/Play/HotkeyExitOverlay.cs b/osu.Game/Screens/Play/HotkeyExitOverlay.cs index 8d7e2481bf..13b72ffaf6 100644 --- a/osu.Game/Screens/Play/HotkeyExitOverlay.cs +++ b/osu.Game/Screens/Play/HotkeyExitOverlay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Input.Bindings; using osu.Game.Overlays; @@ -9,17 +10,17 @@ namespace osu.Game.Screens.Play { public class HotkeyExitOverlay : HoldToConfirmOverlay, IKeyBindingHandler { - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - if (action != GlobalAction.QuickExit) return false; + if (e.Action != GlobalAction.QuickExit) return false; BeginConfirm(); return true; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { - if (action != GlobalAction.QuickExit) return; + if (e.Action != GlobalAction.QuickExit) return; AbortConfirm(); } diff --git a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs index 58fd941f36..308befe372 100644 --- a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs +++ b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Input.Bindings; using osu.Game.Overlays; @@ -9,17 +10,17 @@ namespace osu.Game.Screens.Play { public class HotkeyRetryOverlay : HoldToConfirmOverlay, IKeyBindingHandler { - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - if (action != GlobalAction.QuickRetry) return false; + if (e.Action != GlobalAction.QuickRetry) return false; BeginConfirm(); return true; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { - if (action != GlobalAction.QuickRetry) return; + if (e.Action != GlobalAction.QuickRetry) return; AbortConfirm(); } diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index adbb5a53f6..0c6f1ed911 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Extensions; @@ -49,11 +50,11 @@ namespace osu.Game.Screens.Play private ScheduledDelegate keyboardSeekDelegate; - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { const double keyboard_seek_amount = 5000; - switch (action) + switch (e.Action) { case GlobalAction.SeekReplayBackward: keyboardSeekDelegate?.Cancel(); @@ -83,9 +84,9 @@ namespace osu.Game.Screens.Play } } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.SeekReplayBackward: case GlobalAction.SeekReplayForward: diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index a2145b7014..b04fcba0c6 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -144,9 +144,9 @@ namespace osu.Game.Screens.Play return base.OnMouseMove(e); } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.SkipCutscene: if (!button.Enabled.Value) @@ -159,7 +159,7 @@ namespace osu.Game.Screens.Play return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs index 822ee1cf90..af60296344 100644 --- a/osu.Game/Screens/Ranking/ResultsScreen.cs +++ b/osu.Game/Screens/Ranking/ResultsScreen.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -327,9 +328,9 @@ namespace osu.Game.Screens.Ranking } } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.Select: statisticsPanel.ToggleVisibility(); @@ -339,7 +340,7 @@ namespace osu.Game.Screens.Ranking return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index b05b7aeb32..5eceae3c6e 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -514,29 +514,29 @@ namespace osu.Game.Screens.Select base.OnKeyUp(e); } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.SelectNext: - beginRepeatSelection(() => SelectNext(1, false), action); + beginRepeatSelection(() => SelectNext(1, false), e.Action); return true; case GlobalAction.SelectPrevious: - beginRepeatSelection(() => SelectNext(-1, false), action); + beginRepeatSelection(() => SelectNext(-1, false), e.Action); return true; } return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.SelectNext: case GlobalAction.SelectPrevious: - endRepeatSelection(action); + endRepeatSelection(e.Action); break; } } diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index 9c0a68133c..8d2ea47757 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -172,9 +172,9 @@ namespace osu.Game.Screens.Select return base.OnClick(e); } - public virtual bool OnPressed(GlobalAction action) + public virtual bool OnPressed(KeyBindingPressEvent e) { - if (action == Hotkey) + if (e.Action == Hotkey) { TriggerClick(); return true; @@ -183,6 +183,6 @@ namespace osu.Game.Screens.Select return false; } - public virtual void OnReleased(GlobalAction action) { } + public virtual void OnReleased(KeyBindingReleaseEvent e) { } } } diff --git a/osu.Game/Screens/Select/FooterButtonRandom.cs b/osu.Game/Screens/Select/FooterButtonRandom.cs index 1eaf2c591e..1d4722cf5d 100644 --- a/osu.Game/Screens/Select/FooterButtonRandom.cs +++ b/osu.Game/Screens/Select/FooterButtonRandom.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Input.Bindings; @@ -58,11 +59,11 @@ namespace osu.Game.Screens.Select }; } - public override bool OnPressed(GlobalAction action) + public override bool OnPressed(KeyBindingPressEvent e) { - rewindSearch = action == GlobalAction.SelectPreviousRandom; + rewindSearch = e.Action == GlobalAction.SelectPreviousRandom; - if (action != GlobalAction.SelectNextRandom && action != GlobalAction.SelectPreviousRandom) + if (e.Action != GlobalAction.SelectNextRandom && e.Action != GlobalAction.SelectPreviousRandom) { return false; } @@ -71,9 +72,9 @@ namespace osu.Game.Screens.Select return true; } - public override void OnReleased(GlobalAction action) + public override void OnReleased(KeyBindingReleaseEvent e) { - if (action == GlobalAction.SelectPreviousRandom) + if (e.Action == GlobalAction.SelectPreviousRandom) { rewindSearch = false; } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 1f0f134ba7..9801098952 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -812,11 +812,11 @@ namespace osu.Game.Screens.Select Schedule(() => BeatmapDetails.Refresh()))); } - public virtual bool OnPressed(GlobalAction action) + public virtual bool OnPressed(KeyBindingPressEvent e) { if (!this.IsCurrentScreen()) return false; - switch (action) + switch (e.Action) { case GlobalAction.Select: FinaliseSelection(); @@ -826,7 +826,7 @@ namespace osu.Game.Screens.Select return false; } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } diff --git a/osu.Game/Skinning/Editor/SkinEditorOverlay.cs b/osu.Game/Skinning/Editor/SkinEditorOverlay.cs index 2562e9c57c..396852365f 100644 --- a/osu.Game/Skinning/Editor/SkinEditorOverlay.cs +++ b/osu.Game/Skinning/Editor/SkinEditorOverlay.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Input.Bindings; @@ -32,9 +33,9 @@ namespace osu.Game.Skinning.Editor RelativeSizeAxes = Axes.Both; } - public bool OnPressed(GlobalAction action) + public bool OnPressed(KeyBindingPressEvent e) { - switch (action) + switch (e.Action) { case GlobalAction.Back: if (skinEditor?.State.Value != Visibility.Visible) @@ -97,7 +98,7 @@ namespace osu.Game.Skinning.Editor } } - public void OnReleased(GlobalAction action) + public void OnReleased(KeyBindingReleaseEvent e) { } From e8dea0138cb8fc4de9d6eba5ab9df355489aaf90 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 16 Sep 2021 18:28:35 +0900 Subject: [PATCH 082/109] Fix one more issue --- osu.Game/Screens/Edit/Verify/IssueTable.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Verify/IssueTable.cs b/osu.Game/Screens/Edit/Verify/IssueTable.cs index 05a8fdd26d..b38a62d838 100644 --- a/osu.Game/Screens/Edit/Verify/IssueTable.cs +++ b/osu.Game/Screens/Edit/Verify/IssueTable.cs @@ -8,6 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Input.Bindings; @@ -52,7 +53,7 @@ namespace osu.Game.Screens.Edit.Verify if (issue.Time != null) { clock.Seek(issue.Time.Value); - editor.OnPressed(GlobalAction.EditorComposeMode); + editor.OnPressed(new KeyBindingPressEvent(GetContainingInputManager().CurrentState, GlobalAction.EditorComposeMode)); } if (!issue.HitObjects.Any()) From a18fed0da49ba399974bf62322a52da9db1a3300 Mon Sep 17 00:00:00 2001 From: kj415j45 Date: Thu, 16 Sep 2021 17:38:33 +0800 Subject: [PATCH 083/109] Remove unused using --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index cfb377f74a..f62131e2d7 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.ComponentModel; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Input; From d8f27633a4f05a75475fa330b8f758af2d81632d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 16 Sep 2021 19:35:15 +0900 Subject: [PATCH 084/109] Fix legacy approach circles accepting alpha --- .../TestSceneSkinFallbacks.cs | 5 +- .../Objects/Drawables/DrawableHitCircle.cs | 18 +++++-- osu.Game.Rulesets.Osu/OsuSkinComponents.cs | 1 + .../Skinning/Default/ApproachCircle.cs | 50 ------------------- .../Skinning/Default/DefaultApproachCircle.cs | 49 ++++++++++++++++++ .../Skinning/Legacy/LegacyApproachCircle.cs | 49 ++++++++++++++++++ .../Legacy/OsuLegacySkinTransformer.cs | 3 ++ 7 files changed, 120 insertions(+), 55 deletions(-) delete mode 100644 osu.Game.Rulesets.Osu/Skinning/Default/ApproachCircle.cs create mode 100644 osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs create mode 100644 osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index 662cbaee68..0f362851a9 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -20,6 +20,7 @@ using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Skinning; using osu.Game.Storyboards; using osu.Game.Tests.Visual; @@ -86,9 +87,9 @@ namespace osu.Game.Rulesets.Osu.Tests if (firstObject == null) return false; - var skinnable = firstObject.ApproachCircle.Child as SkinnableDrawable; + var skinnable = firstObject.ApproachCircle; - if (skin == null && skinnable?.Drawable is Sprite) + if (skin == null && skinnable?.Drawable is DefaultApproachCircle) // check for default skin provider return true; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 46fc8f99b2..7d28ec822d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public OsuAction? HitAction => HitArea.HitAction; protected virtual OsuSkinComponents CirclePieceComponent => OsuSkinComponents.HitCircle; - public ApproachCircle ApproachCircle { get; private set; } + public SkinnableDrawable ApproachCircle { get; private set; } public HitReceptor HitArea { get; private set; } public SkinnableDrawable CirclePiece { get; private set; } @@ -74,8 +74,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Anchor = Anchor.Centre, Origin = Anchor.Centre, }, - ApproachCircle = new ApproachCircle + ApproachCircle = new ProxyableSkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.ApproachCircle), _ => new DefaultApproachCircle()) { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, Alpha = 0, Scale = new Vector2(4), } @@ -88,7 +91,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables PositionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); StackHeightBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); ScaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue)); - AccentColour.BindValueChanged(accent => ApproachCircle.Colour = accent.NewValue); } protected override void LoadComplete() @@ -250,5 +252,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { } } + + private class ProxyableSkinnableDrawable : SkinnableDrawable + { + public override bool RemoveWhenNotAlive => false; + + public ProxyableSkinnableDrawable(ISkinComponent component, Func defaultImplementation = null, ConfineMode confineMode = ConfineMode.NoScaling) + : base(component, defaultImplementation, confineMode) + { + } + } } } diff --git a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs index 46e501758b..59fe353bd2 100644 --- a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs +++ b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs @@ -18,5 +18,6 @@ namespace osu.Game.Rulesets.Osu SliderBall, SliderBody, SpinnerBody, + ApproachCircle, } } diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/ApproachCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ApproachCircle.cs deleted file mode 100644 index 62f00a2b49..0000000000 --- a/osu.Game.Rulesets.Osu/Skinning/Default/ApproachCircle.cs +++ /dev/null @@ -1,50 +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.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Textures; -using osu.Game.Skinning; -using osuTK; - -namespace osu.Game.Rulesets.Osu.Skinning.Default -{ - public class ApproachCircle : Container - { - public override bool RemoveWhenNotAlive => false; - - public ApproachCircle() - { - Anchor = Anchor.Centre; - Origin = Anchor.Centre; - - RelativeSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - Child = new SkinnableApproachCircle(); - } - - private class SkinnableApproachCircle : SkinnableSprite - { - public SkinnableApproachCircle() - : base("Gameplay/osu/approachcircle") - { - } - - protected override Drawable CreateDefault(ISkinComponent component) - { - var drawable = base.CreateDefault(component); - - // account for the sprite being used for the default approach circle being taken from stable, - // when hitcircles have 5px padding on each size. this should be removed if we update the sprite. - drawable.Scale = new Vector2(128 / 118f); - - return drawable; - } - } - } -} diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs new file mode 100644 index 0000000000..a522367fe6 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs @@ -0,0 +1,49 @@ +// 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.Bindables; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Skinning; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Skinning.Default +{ + public class DefaultApproachCircle : SkinnableSprite + { + private readonly IBindable accentColour = new Bindable(); + + [Resolved] + private DrawableHitObject drawableObject { get; set; } + + public DefaultApproachCircle() + : base("Gameplay/osu/approachcircle") + { + } + + [BackgroundDependencyLoader] + private void load() + { + accentColour.BindTo(drawableObject.AccentColour); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + accentColour.BindValueChanged(colour => Colour = colour.NewValue, true); + } + + protected override Drawable CreateDefault(ISkinComponent component) + { + var drawable = base.CreateDefault(component); + + // Although this is a non-legacy component, osu-resources currently stores approach circle as a legacy-like texture. + // See LegacyApproachCircle for documentation as to why this is required. + drawable.Scale = new Vector2(128 / 118f); + + return drawable; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs new file mode 100644 index 0000000000..09f759fe7d --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs @@ -0,0 +1,49 @@ +// 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.Bindables; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Skinning; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Skinning.Legacy +{ + public class LegacyApproachCircle : SkinnableSprite + { + private readonly IBindable accentColour = new Bindable(); + + [Resolved] + private DrawableHitObject drawableObject { get; set; } + + public LegacyApproachCircle() + : base("approachcircle") + { + } + + [BackgroundDependencyLoader] + private void load() + { + accentColour.BindTo(drawableObject.AccentColour); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + accentColour.BindValueChanged(colour => Colour = LegacyColourCompatibility.DisallowZeroAlpha(colour.NewValue), true); + } + + protected override Drawable CreateDefault(ISkinComponent component) + { + var drawable = base.CreateDefault(component); + + // account for the sprite being used for the default approach circle being taken from stable, + // when hitcircles have 5px padding on each size. this should be removed if we update the sprite. + drawable.Scale = new Vector2(128 / 118f); + + return drawable; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs index 41b0a88f11..190195f0a6 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs @@ -108,6 +108,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy return new LegacyOldStyleSpinner(); return null; + + case OsuSkinComponents.ApproachCircle: + return new LegacyApproachCircle(); } } From bcbd0e096165cd7d1cf3ad871e43b9fc1a79e3e6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 16 Sep 2021 20:06:20 +0900 Subject: [PATCH 085/109] Revert ctor param --- osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs index 09f759fe7d..6a2cb871b1 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy private DrawableHitObject drawableObject { get; set; } public LegacyApproachCircle() - : base("approachcircle") + : base("Gameplay/osu/approachcircle") { } From a1d33c1a46f954ae94705a3106ddc9b37e267a68 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Sep 2021 22:38:19 +0900 Subject: [PATCH 086/109] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index d4331a5e65..7707b717e9 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5a302c5349..390b026497 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 73e0030114..6e852c4321 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - + From bb132f9509ee954625e75c6461b5b293832ea72b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Sep 2021 22:41:35 +0900 Subject: [PATCH 087/109] Update a few more missed event changes in tests --- .../TestSceneDrawableManiaHitObject.cs | 3 ++- osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs | 5 +++-- osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableManiaHitObject.cs index 4a6c59e297..92c95b8fde 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableManiaHitObject.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; @@ -58,7 +59,7 @@ namespace osu.Game.Rulesets.Mania.Tests AddStep("Hold key", () => { clock.CurrentTime = 0; - note.OnPressed(ManiaAction.Key1); + note.OnPressed(new KeyBindingPressEvent(GetContainingInputManager().CurrentState, ManiaAction.Key1)); }); AddStep("progress time", () => clock.CurrentTime = 500); AddAssert("head is visible", () => note.Head.Alpha == 1); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs index 2326a0c391..f9dc9abd75 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; using osu.Framework.Input; +using osu.Framework.Input.Events; using osu.Framework.Testing.Input; using osu.Framework.Utils; using osu.Game.Audio; @@ -143,9 +144,9 @@ namespace osu.Game.Rulesets.Osu.Tests pressed = value; if (value) - OnPressed(OsuAction.LeftButton); + OnPressed(new KeyBindingPressEvent(GetContainingInputManager().CurrentState, OsuAction.LeftButton)); else - OnReleased(OsuAction.LeftButton); + OnReleased(new KeyBindingReleaseEvent(GetContainingInputManager().CurrentState, OsuAction.LeftButton)); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs index 1fdcd73dde..575523b168 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs @@ -4,6 +4,7 @@ using System; using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Osu.Objects; @@ -97,7 +98,7 @@ namespace osu.Game.Rulesets.Osu.Tests private void scheduleHit() => AddStep("schedule action", () => { var delay = hitCircle.StartTime - hitCircle.HitWindows.WindowFor(HitResult.Great) - Time.Current; - Scheduler.AddDelayed(() => hitAreaReceptor.OnPressed(OsuAction.LeftButton), delay); + Scheduler.AddDelayed(() => hitAreaReceptor.OnPressed(new KeyBindingPressEvent(GetContainingInputManager().CurrentState, OsuAction.LeftButton)), delay); }); } } From edb1230111ef1cc1680ee1a032dc1ca951e8fcef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Sep 2021 22:48:09 +0900 Subject: [PATCH 088/109] Fix potential nullref throw on failed startup --- osu.Game/Database/DatabaseContextFactory.cs | 7 +++++-- osu.Game/OsuGameBase.cs | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/DatabaseContextFactory.cs b/osu.Game/Database/DatabaseContextFactory.cs index 1cceb59b11..d402195f29 100644 --- a/osu.Game/Database/DatabaseContextFactory.cs +++ b/osu.Game/Database/DatabaseContextFactory.cs @@ -163,8 +163,11 @@ namespace osu.Game.Database public void FlushConnections() { - foreach (var context in threadContexts.Values) - context.Dispose(); + if (threadContexts != null) + { + foreach (var context in threadContexts.Values) + context.Dispose(); + } recycleThreadContexts(); } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 59a05aec4f..7aa460981a 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -527,7 +527,7 @@ namespace osu.Game BeatmapManager?.Dispose(); LocalConfig?.Dispose(); - contextFactory.FlushConnections(); + contextFactory?.FlushConnections(); } } } From 414735b8d083117491ff8cbca9d078b62c5fe0ca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Sep 2021 00:18:08 +0900 Subject: [PATCH 089/109] Bump mobile project props realm references --- osu.Android.props | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 7707b717e9..0e60a5a99e 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -56,6 +56,6 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 6e852c4321..2158772b83 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -99,6 +99,6 @@ - + From 2983d5468247a5d7db672eaa7db1f6868103370c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 16 Sep 2021 17:32:23 -0700 Subject: [PATCH 090/109] Fix wiki main page blurb overflowing at higher ui scale --- osu.Game/Overlays/Wiki/WikiMainPage.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Wiki/WikiMainPage.cs b/osu.Game/Overlays/Wiki/WikiMainPage.cs index 3fb0aa450e..c9ee2cbfd5 100644 --- a/osu.Game/Overlays/Wiki/WikiMainPage.cs +++ b/osu.Game/Overlays/Wiki/WikiMainPage.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics.Containers; using HtmlAgilityPack; using osu.Framework.Allocation; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Wiki { @@ -56,12 +56,12 @@ namespace osu.Game.Overlays.Wiki { Vertical = 30, }, - Child = new OsuSpriteText + Child = new OsuTextFlowContainer(t => t.Font = OsuFont.GetFont(Typeface.Inter, size: 12, weight: FontWeight.Light)) { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Text = blurbNode.InnerText, - Font = OsuFont.GetFont(Typeface.Inter, size: 12, weight: FontWeight.Light), - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, + TextAnchor = Anchor.TopCentre, } }; } From 55feb47e61878ef97cf890de0e58f731150908cb Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 16 Sep 2021 20:17:21 -0700 Subject: [PATCH 091/109] Disallow track adjustments on playlists / multi lounge --- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 08bdd0487a..9481ffc3e4 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -37,6 +37,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { public override string Title => "Lounge"; + public override bool? AllowTrackAdjustments => false; + protected override BackgroundScreen CreateBackground() => new LoungeBackgroundScreen { SelectedRoom = { BindTarget = SelectedRoom } From cd4ba71a6b012f0dd106a099df0ecffdb97d0fbb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Sep 2021 13:22:39 +0900 Subject: [PATCH 092/109] Revert "Merge pull request #14772 from Joehuu/lounge-disallow-track-adj" This reverts commit 06ff4838fb55f3362019ac0e173f10b64ec372b2, reversing changes made to 5453ea0ce99bea69a9f87163a500140b1d7b318a. --- osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index 9481ffc3e4..08bdd0487a 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -37,8 +37,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { public override string Title => "Lounge"; - public override bool? AllowTrackAdjustments => false; - protected override BackgroundScreen CreateBackground() => new LoungeBackgroundScreen { SelectedRoom = { BindTarget = SelectedRoom } From f524e913e1e456fa342f75d6d90b0174ae451940 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Sep 2021 13:23:02 +0900 Subject: [PATCH 093/109] Move `AllowTrackAdjustments` specification to `RoomSubScreen` --- osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs | 2 ++ osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 9095b78eb4..bcb793062b 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -29,6 +29,8 @@ namespace osu.Game.Screens.OnlinePlay.Match [Cached(typeof(IBindable))] protected readonly Bindable SelectedItem = new Bindable(); + public override bool? AllowTrackAdjustments => true; + protected override BackgroundScreen CreateBackground() => new RoomBackgroundScreen(Room.Playlist.FirstOrDefault()) { SelectedItem = { BindTarget = SelectedItem } diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs index 8c4f0c1394..3411c4afb1 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs @@ -11,8 +11,6 @@ namespace osu.Game.Screens.OnlinePlay { public override bool DisallowExternalBeatmapRulesetChanges => false; - public override bool? AllowTrackAdjustments => true; - public virtual string ShortTitle => Title; [Resolved(CanBeNull = true)] From 1b13b74740eb42050effc28b0da2f951a0468426 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Sep 2021 13:48:19 +0900 Subject: [PATCH 094/109] Fix skin editor potentially leaving game-wide masking in the wrong state Just going with the simplest way to solve this. Closes https://github.com/ppy/osu/issues/14769. --- osu.Game/Skinning/Editor/SkinEditorOverlay.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/Editor/SkinEditorOverlay.cs b/osu.Game/Skinning/Editor/SkinEditorOverlay.cs index 396852365f..a892ec1ca3 100644 --- a/osu.Game/Skinning/Editor/SkinEditorOverlay.cs +++ b/osu.Game/Skinning/Editor/SkinEditorOverlay.cs @@ -82,7 +82,7 @@ namespace osu.Game.Skinning.Editor { if (visibility.NewValue == Visibility.Visible) { - target.Masking = true; + updateMasking(); target.AllowScaling = false; target.RelativePositionAxes = Axes.Both; @@ -93,11 +93,14 @@ namespace osu.Game.Skinning.Editor { target.AllowScaling = true; - target.ScaleTo(1, SkinEditor.TRANSITION_DURATION, Easing.OutQuint).OnComplete(_ => target.Masking = false); + target.ScaleTo(1, SkinEditor.TRANSITION_DURATION, Easing.OutQuint).OnComplete(_ => updateMasking()); target.MoveToX(0f, SkinEditor.TRANSITION_DURATION, Easing.OutQuint); } } + private void updateMasking() => + target.Masking = skinEditor.State.Value == Visibility.Visible; + public void OnReleased(KeyBindingReleaseEvent e) { } From e0bbc677d26cec949720200038a09fd6e0c0331d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Sep 2021 16:23:09 +0900 Subject: [PATCH 095/109] Fix `TestRollbackOnFailure` not cleaning up after itself --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 5dc25d6643..b2bd60d342 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -424,14 +424,14 @@ namespace osu.Game.Tests.Beatmaps.IO checkBeatmapCount(osu, 12); checkSingleReferencedFileCount(osu, 18); - var breakTemp = TestResources.GetTestBeatmapForImport(); + var brokenTempFilename = TestResources.GetTestBeatmapForImport(); MemoryStream brokenOsu = new MemoryStream(); - MemoryStream brokenOsz = new MemoryStream(await File.ReadAllBytesAsync(breakTemp)); + MemoryStream brokenOsz = new MemoryStream(await File.ReadAllBytesAsync(brokenTempFilename)); - File.Delete(breakTemp); + File.Delete(brokenTempFilename); - using (var outStream = File.Open(breakTemp, FileMode.CreateNew)) + using (var outStream = File.Open(brokenTempFilename, FileMode.CreateNew)) using (var zip = ZipArchive.Open(brokenOsz)) { zip.AddEntry("broken.osu", brokenOsu, false); @@ -441,7 +441,7 @@ namespace osu.Game.Tests.Beatmaps.IO // this will trigger purging of the existing beatmap (online set id match) but should rollback due to broken osu. try { - await manager.Import(new ImportTask(breakTemp)); + await manager.Import(new ImportTask(brokenTempFilename)); } catch { @@ -456,6 +456,8 @@ namespace osu.Game.Tests.Beatmaps.IO checkSingleReferencedFileCount(osu, 18); Assert.AreEqual(1, loggedExceptionCount); + + File.Delete(brokenTempFilename); } finally { From 2ab235ebe72956b34844f1966b7fca7fa1a5861d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Sep 2021 16:24:21 +0900 Subject: [PATCH 096/109] Use new temporary folder storage for beatmap import tests --- osu.Game.Tests/Resources/TestResources.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index 7170a76b8b..839366d98e 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -1,9 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.IO; using NUnit.Framework; using osu.Framework.IO.Stores; +using osu.Framework.Testing; namespace osu.Game.Tests.Resources { @@ -11,6 +13,8 @@ namespace osu.Game.Tests.Resources { public const double QUICK_BEATMAP_LENGTH = 10000; + private static readonly TemporaryNativeStorage temp_storage = new TemporaryNativeStorage("TestResources"); + public static DllResourceStore GetStore() => new DllResourceStore(typeof(TestResources).Assembly); public static Stream OpenResource(string name) => GetStore().GetStream($"Resources/{name}"); @@ -25,7 +29,7 @@ namespace osu.Game.Tests.Resources /// A path to a copy of a beatmap archive (osz). Should be deleted after use. public static string GetQuickTestBeatmapForImport() { - var tempPath = Path.GetTempFileName() + ".osz"; + var tempPath = getTempFilename(); using (var stream = OpenResource("Archives/241526 Soleily - Renatus_virtual_quick.osz")) using (var newFile = File.Create(tempPath)) stream.CopyTo(newFile); @@ -41,7 +45,7 @@ namespace osu.Game.Tests.Resources /// A path to a copy of a beatmap archive (osz). Should be deleted after use. public static string GetTestBeatmapForImport(bool virtualTrack = false) { - var tempPath = Path.GetTempFileName() + ".osz"; + var tempPath = getTempFilename(); using (var stream = GetTestBeatmapStream(virtualTrack)) using (var newFile = File.Create(tempPath)) @@ -50,5 +54,7 @@ namespace osu.Game.Tests.Resources Assert.IsTrue(File.Exists(tempPath)); return tempPath; } + + private static string getTempFilename() => temp_storage.GetFullPath(Guid.NewGuid() + ".osz"); } } From f584d6593acbd028287049eed49f335832480a16 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Sep 2021 18:10:53 +0900 Subject: [PATCH 097/109] Fix flashlight alignment --- osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs index 1253b7c8ae..3578e3a734 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Taiko.Mods if (!flashlightProperties.IsValid) { - FlashlightPosition = taikoPlayfield.HitTarget.ToSpaceOfOtherDrawable(taikoPlayfield.HitTarget.OriginPosition, this); + FlashlightPosition = ToLocalSpace(taikoPlayfield.HitTarget.ScreenSpaceDrawQuad.Centre); flashlightProperties.Validate(); } } From 1c8e17cf11158720af08f0cda6e5999b68879815 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Sep 2021 18:14:39 +0900 Subject: [PATCH 098/109] Fix the default background parallax being set incorrectly when no screen is present --- osu.Game/Screens/OsuScreenStack.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OsuScreenStack.cs b/osu.Game/Screens/OsuScreenStack.cs index e2a0414df7..ebbcbd7650 100644 --- a/osu.Game/Screens/OsuScreenStack.cs +++ b/osu.Game/Screens/OsuScreenStack.cs @@ -51,6 +51,6 @@ namespace osu.Game.Screens } private void setParallax(IScreen next) => - parallaxContainer.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * ((IOsuScreen)next)?.BackgroundParallaxAmount ?? 1.0f; + parallaxContainer.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * (((IOsuScreen)next)?.BackgroundParallaxAmount ?? 1.0f); } } From a1f587f2c54436e5eff098dcf054085beeea928d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Sep 2021 18:25:23 +0900 Subject: [PATCH 099/109] Add failing test coverage of password entry textbox not regaining focus --- .../TestSceneMultiplayerLoungeSubScreen.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs index 4e2a91af78..b7da31a2b5 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs @@ -83,7 +83,7 @@ namespace osu.Game.Tests.Visual.Multiplayer } [Test] - public void TestJoinRoomWithIncorrectPassword() + public void TestJoinRoomWithIncorrectPasswordViaButton() { DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null; @@ -96,6 +96,24 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("room not joined", () => loungeScreen.IsCurrentScreen()); AddUntilStep("password prompt still visible", () => passwordEntryPopover.State.Value == Visibility.Visible); + AddAssert("textbox still focused", () => InputManager.FocusedDrawable is OsuPasswordTextBox); + } + + [Test] + public void TestJoinRoomWithIncorrectPasswordViaEnter() + { + DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null; + + AddStep("add room", () => RoomManager.AddRooms(1, withPassword: true)); + AddStep("select room", () => InputManager.Key(Key.Down)); + AddStep("attempt join room", () => InputManager.Key(Key.Enter)); + AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType().FirstOrDefault()) != null); + AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType().First().Text = "wrong"); + AddStep("press enter", () => InputManager.Key(Key.Enter)); + + AddAssert("room not joined", () => loungeScreen.IsCurrentScreen()); + AddUntilStep("password prompt still visible", () => passwordEntryPopover.State.Value == Visibility.Visible); + AddAssert("textbox still focused", () => InputManager.FocusedDrawable is OsuPasswordTextBox); } [Test] From 027912d4f666db7b7439d76f14294fb11d635a60 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Sep 2021 18:23:36 +0900 Subject: [PATCH 100/109] Refocus the multiplayer password entry textbox on failed join --- osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index d55cccd414..a823db282c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -234,6 +234,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { passwordTextbox.Text = string.Empty; + GetContainingInputManager().ChangeFocus(passwordTextbox); + errorText.Text = error; errorText .FadeIn() From 50f155e4b936e9858fde9d51054330804e94c6c7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Sep 2021 18:30:38 +0900 Subject: [PATCH 101/109] Move login panel related files to own namespace and tidy up class nesting --- osu.Game/Overlays/Login/LoginForm.cs | 108 +++++ osu.Game/Overlays/Login/LoginPanel.cs | 199 +++++++++ osu.Game/Overlays/Login/UserAction.cs | 18 + osu.Game/Overlays/Login/UserDropdown.cs | 121 +++++ osu.Game/Overlays/LoginOverlay.cs | 12 +- .../Sections/General/LoginSettings.cs | 421 ------------------ 6 files changed, 452 insertions(+), 427 deletions(-) create mode 100644 osu.Game/Overlays/Login/LoginForm.cs create mode 100644 osu.Game/Overlays/Login/LoginPanel.cs create mode 100644 osu.Game/Overlays/Login/UserAction.cs create mode 100644 osu.Game/Overlays/Login/UserDropdown.cs delete mode 100644 osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs diff --git a/osu.Game/Overlays/Login/LoginForm.cs b/osu.Game/Overlays/Login/LoginForm.cs new file mode 100644 index 0000000000..9d229c2b3e --- /dev/null +++ b/osu.Game/Overlays/Login/LoginForm.cs @@ -0,0 +1,108 @@ +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Configuration; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Overlays.Settings; +using osuTK; + +namespace osu.Game.Overlays.Login +{ + public class LoginForm : FillFlowContainer + { + private TextBox username; + private TextBox password; + private ShakeContainer shakeSignIn; + + [Resolved(CanBeNull = true)] + private IAPIProvider api { get; set; } + + public Action RequestHide; + + private void performLogin() + { + if (!string.IsNullOrEmpty(username.Text) && !string.IsNullOrEmpty(password.Text)) + api?.Login(username.Text, password.Text); + else + shakeSignIn.Shake(); + } + + [BackgroundDependencyLoader(permitNulls: true)] + private void load(OsuConfigManager config, AccountCreationOverlay accountCreation) + { + Direction = FillDirection.Vertical; + Spacing = new Vector2(0, 5); + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + Children = new Drawable[] + { + username = new OsuTextBox + { + PlaceholderText = "username", + RelativeSizeAxes = Axes.X, + Text = api?.ProvidedUsername ?? string.Empty, + TabbableContentContainer = this + }, + password = new OsuPasswordTextBox + { + PlaceholderText = "password", + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + }, + new SettingsCheckbox + { + LabelText = "Remember username", + Current = config.GetBindable(OsuSetting.SaveUsername), + }, + new SettingsCheckbox + { + LabelText = "Stay signed in", + Current = config.GetBindable(OsuSetting.SavePassword), + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + shakeSignIn = new ShakeContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = new SettingsButton + { + Text = "Sign in", + Action = performLogin + }, + } + } + }, + new SettingsButton + { + Text = "Register", + Action = () => + { + RequestHide(); + accountCreation.Show(); + } + } + }; + + password.OnCommit += (sender, newText) => performLogin(); + } + + public override bool AcceptsFocus => true; + + protected override bool OnClick(ClickEvent e) => true; + + protected override void OnFocus(FocusEvent e) + { + Schedule(() => { GetContainingInputManager().ChangeFocus(string.IsNullOrEmpty(username.Text) ? username : password); }); + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs new file mode 100644 index 0000000000..d1e5bfe809 --- /dev/null +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -0,0 +1,199 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Users; +using osuTK; +using RectangleF = osu.Framework.Graphics.Primitives.RectangleF; +using Container = osu.Framework.Graphics.Containers.Container; + +namespace osu.Game.Overlays.Login +{ + public class LoginPanel : FillFlowContainer + { + private bool bounding = true; + private LoginForm form; + + [Resolved] + private OsuColour colours { get; set; } + + private UserGridPanel panel; + private UserDropdown dropdown; + + /// + /// Called to request a hide of a parent displaying this container. + /// + public Action RequestHide; + + private readonly IBindable apiState = new Bindable(); + + [Resolved] + private IAPIProvider api { get; set; } + + public override RectangleF BoundingBox => bounding ? base.BoundingBox : RectangleF.Empty; + + public bool Bounding + { + get => bounding; + set + { + bounding = value; + Invalidate(Invalidation.MiscGeometry); + } + } + + public LoginPanel() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Direction = FillDirection.Vertical; + Spacing = new Vector2(0f, 5f); + } + + [BackgroundDependencyLoader] + private void load() + { + apiState.BindTo(api.State); + apiState.BindValueChanged(onlineStateChanged, true); + } + + private void onlineStateChanged(ValueChangedEvent state) => Schedule(() => + { + form = null; + + switch (state.NewValue) + { + case APIState.Offline: + Children = new Drawable[] + { + new OsuSpriteText + { + Text = "ACCOUNT", + Margin = new MarginPadding { Bottom = 5 }, + Font = OsuFont.GetFont(weight: FontWeight.Bold), + }, + form = new LoginForm + { + RequestHide = RequestHide + } + }; + break; + + case APIState.Failing: + case APIState.Connecting: + LinkFlowContainer linkFlow; + + Children = new Drawable[] + { + new LoadingSpinner + { + State = { Value = Visibility.Visible }, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }, + linkFlow = new LinkFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + TextAnchor = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + Text = state.NewValue == APIState.Failing ? "Connection is failing, will attempt to reconnect... " : "Attempting to connect... ", + Margin = new MarginPadding { Top = 10, Bottom = 10 }, + }, + }; + + linkFlow.AddLink("cancel", api.Logout, string.Empty); + break; + + case APIState.Online: + Children = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Left = 20, Right = 20 }, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0f, 10f), + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new[] + { + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = "Signed in", + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), + Margin = new MarginPadding { Top = 5, Bottom = 5 }, + }, + }, + }, + panel = new UserGridPanel(api.LocalUser.Value) + { + RelativeSizeAxes = Axes.X, + Action = RequestHide + }, + dropdown = new UserDropdown { RelativeSizeAxes = Axes.X }, + }, + }, + }; + + panel.Status.BindTo(api.LocalUser.Value.Status); + panel.Activity.BindTo(api.LocalUser.Value.Activity); + + dropdown.Current.BindValueChanged(action => + { + switch (action.NewValue) + { + case UserAction.Online: + api.LocalUser.Value.Status.Value = new UserStatusOnline(); + dropdown.StatusColour = colours.Green; + break; + + case UserAction.DoNotDisturb: + api.LocalUser.Value.Status.Value = new UserStatusDoNotDisturb(); + dropdown.StatusColour = colours.Red; + break; + + case UserAction.AppearOffline: + api.LocalUser.Value.Status.Value = new UserStatusOffline(); + dropdown.StatusColour = colours.Gray7; + break; + + case UserAction.SignOut: + api.Logout(); + break; + } + }, true); + break; + } + + if (form != null) GetContainingInputManager()?.ChangeFocus(form); + }); + + public override bool AcceptsFocus => true; + + protected override bool OnClick(ClickEvent e) => true; + + protected override void OnFocus(FocusEvent e) + { + if (form != null) GetContainingInputManager().ChangeFocus(form); + base.OnFocus(e); + } + } +} diff --git a/osu.Game/Overlays/Login/UserAction.cs b/osu.Game/Overlays/Login/UserAction.cs new file mode 100644 index 0000000000..440d6ea456 --- /dev/null +++ b/osu.Game/Overlays/Login/UserAction.cs @@ -0,0 +1,18 @@ +using System.ComponentModel; + +namespace osu.Game.Overlays.Login +{ + public enum UserAction + { + Online, + + [Description(@"Do not disturb")] + DoNotDisturb, + + [Description(@"Appear offline")] + AppearOffline, + + [Description(@"Sign out")] + SignOut, + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/Login/UserDropdown.cs b/osu.Game/Overlays/Login/UserDropdown.cs new file mode 100644 index 0000000000..80f6c7113b --- /dev/null +++ b/osu.Game/Overlays/Login/UserDropdown.cs @@ -0,0 +1,121 @@ +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Login +{ + public class UserDropdown : OsuEnumDropdown + { + protected override DropdownHeader CreateHeader() => new UserDropdownHeader(); + + protected override DropdownMenu CreateMenu() => new UserDropdownMenu(); + + public Color4 StatusColour + { + set + { + if (Header is UserDropdownHeader h) + h.StatusColour = value; + } + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AccentColour = colours.Gray5; + } + + protected class UserDropdownMenu : OsuDropdownMenu + { + public UserDropdownMenu() + { + Masking = true; + CornerRadius = 5; + + Margin = new MarginPadding { Bottom = 5 }; + + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(0.25f), + Radius = 4, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + BackgroundColour = colours.Gray3; + } + + protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new DrawableUserDropdownMenuItem(item); + + private class DrawableUserDropdownMenuItem : DrawableOsuDropdownMenuItem + { + public DrawableUserDropdownMenuItem(MenuItem item) + : base(item) + { + Foreground.Padding = new MarginPadding { Top = 5, Bottom = 5, Left = 10, Right = 5 }; + CornerRadius = 5; + } + + protected override Drawable CreateContent() => new Content + { + Label = { Margin = new MarginPadding { Left = UserDropdownHeader.LABEL_LEFT_MARGIN - 11 } } + }; + } + } + + private class UserDropdownHeader : OsuDropdownHeader + { + public const float LABEL_LEFT_MARGIN = 20; + + private readonly SpriteIcon statusIcon; + + public Color4 StatusColour + { + set => statusIcon.FadeColour(value, 500, Easing.OutQuint); + } + + public UserDropdownHeader() + { + Foreground.Padding = new MarginPadding { Left = 10, Right = 10 }; + Margin = new MarginPadding { Bottom = 5 }; + Masking = true; + CornerRadius = 5; + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(0.25f), + Radius = 4, + }; + + Icon.Size = new Vector2(14); + Icon.Margin = new MarginPadding(0); + + Foreground.Add(statusIcon = new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.Regular.Circle, + Size = new Vector2(14), + }); + + Text.Margin = new MarginPadding { Left = LABEL_LEFT_MARGIN }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + BackgroundColour = colours.Gray3; + } + } + } +} diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index e7caaa3aca..f3562aa6d9 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -5,17 +5,17 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; -using osu.Game.Overlays.Settings.Sections.General; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; +using osu.Game.Overlays.Login; namespace osu.Game.Overlays { public class LoginOverlay : OsuFocusedOverlayContainer { - private LoginSettings settingsSection; + private LoginPanel panel; private const float transition_time = 400; @@ -50,7 +50,7 @@ namespace osu.Game.Overlays AutoSizeEasing = Easing.OutQuint, Children = new Drawable[] { - settingsSection = new LoginSettings + panel = new LoginPanel { Padding = new MarginPadding(10), RequestHide = Hide, @@ -75,17 +75,17 @@ namespace osu.Game.Overlays { base.PopIn(); - settingsSection.Bounding = true; + panel.Bounding = true; this.FadeIn(transition_time, Easing.OutQuint); - GetContainingInputManager().ChangeFocus(settingsSection); + GetContainingInputManager().ChangeFocus(panel); } protected override void PopOut() { base.PopOut(); - settingsSection.Bounding = false; + panel.Bounding = false; this.FadeOut(transition_time); } } diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs deleted file mode 100644 index 8f757f7a36..0000000000 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ /dev/null @@ -1,421 +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 System; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.UserInterface; -using osu.Game.Configuration; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; -using osuTK; -using osu.Game.Users; -using System.ComponentModel; -using osu.Framework.Bindables; -using osu.Game.Graphics; -using osuTK.Graphics; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; -using osu.Game.Graphics.Containers; -using RectangleF = osu.Framework.Graphics.Primitives.RectangleF; -using Container = osu.Framework.Graphics.Containers.Container; - -namespace osu.Game.Overlays.Settings.Sections.General -{ - public class LoginSettings : FillFlowContainer - { - private bool bounding = true; - private LoginForm form; - - [Resolved] - private OsuColour colours { get; set; } - - private UserGridPanel panel; - private UserDropdown dropdown; - - /// - /// Called to request a hide of a parent displaying this container. - /// - public Action RequestHide; - - private readonly IBindable apiState = new Bindable(); - - [Resolved] - private IAPIProvider api { get; set; } - - public override RectangleF BoundingBox => bounding ? base.BoundingBox : RectangleF.Empty; - - public bool Bounding - { - get => bounding; - set - { - bounding = value; - Invalidate(Invalidation.MiscGeometry); - } - } - - public LoginSettings() - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - Direction = FillDirection.Vertical; - Spacing = new Vector2(0f, 5f); - } - - [BackgroundDependencyLoader] - private void load() - { - apiState.BindTo(api.State); - apiState.BindValueChanged(onlineStateChanged, true); - } - - private void onlineStateChanged(ValueChangedEvent state) => Schedule(() => - { - form = null; - - switch (state.NewValue) - { - case APIState.Offline: - Children = new Drawable[] - { - new OsuSpriteText - { - Text = "ACCOUNT", - Margin = new MarginPadding { Bottom = 5 }, - Font = OsuFont.GetFont(weight: FontWeight.Bold), - }, - form = new LoginForm - { - RequestHide = RequestHide - } - }; - break; - - case APIState.Failing: - case APIState.Connecting: - LinkFlowContainer linkFlow; - - Children = new Drawable[] - { - new LoadingSpinner - { - State = { Value = Visibility.Visible }, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - }, - linkFlow = new LinkFlowContainer - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - TextAnchor = Anchor.TopCentre, - AutoSizeAxes = Axes.Both, - Text = state.NewValue == APIState.Failing ? "Connection is failing, will attempt to reconnect... " : "Attempting to connect... ", - Margin = new MarginPadding { Top = 10, Bottom = 10 }, - }, - }; - - linkFlow.AddLink("cancel", api.Logout, string.Empty); - break; - - case APIState.Online: - Children = new Drawable[] - { - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = 20, Right = 20 }, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0f, 10f), - Children = new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new[] - { - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = "Signed in", - Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), - Margin = new MarginPadding { Top = 5, Bottom = 5 }, - }, - }, - }, - panel = new UserGridPanel(api.LocalUser.Value) - { - RelativeSizeAxes = Axes.X, - Action = RequestHide - }, - dropdown = new UserDropdown { RelativeSizeAxes = Axes.X }, - }, - }, - }; - - panel.Status.BindTo(api.LocalUser.Value.Status); - panel.Activity.BindTo(api.LocalUser.Value.Activity); - - dropdown.Current.BindValueChanged(action => - { - switch (action.NewValue) - { - case UserAction.Online: - api.LocalUser.Value.Status.Value = new UserStatusOnline(); - dropdown.StatusColour = colours.Green; - break; - - case UserAction.DoNotDisturb: - api.LocalUser.Value.Status.Value = new UserStatusDoNotDisturb(); - dropdown.StatusColour = colours.Red; - break; - - case UserAction.AppearOffline: - api.LocalUser.Value.Status.Value = new UserStatusOffline(); - dropdown.StatusColour = colours.Gray7; - break; - - case UserAction.SignOut: - api.Logout(); - break; - } - }, true); - break; - } - - if (form != null) GetContainingInputManager()?.ChangeFocus(form); - }); - - public override bool AcceptsFocus => true; - - protected override bool OnClick(ClickEvent e) => true; - - protected override void OnFocus(FocusEvent e) - { - if (form != null) GetContainingInputManager().ChangeFocus(form); - base.OnFocus(e); - } - - private class LoginForm : FillFlowContainer - { - private TextBox username; - private TextBox password; - private ShakeContainer shakeSignIn; - - [Resolved(CanBeNull = true)] - private IAPIProvider api { get; set; } - - public Action RequestHide; - - private void performLogin() - { - if (!string.IsNullOrEmpty(username.Text) && !string.IsNullOrEmpty(password.Text)) - api?.Login(username.Text, password.Text); - else - shakeSignIn.Shake(); - } - - [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuConfigManager config, AccountCreationOverlay accountCreation) - { - Direction = FillDirection.Vertical; - Spacing = new Vector2(0, 5); - AutoSizeAxes = Axes.Y; - RelativeSizeAxes = Axes.X; - Children = new Drawable[] - { - username = new OsuTextBox - { - PlaceholderText = "username", - RelativeSizeAxes = Axes.X, - Text = api?.ProvidedUsername ?? string.Empty, - TabbableContentContainer = this - }, - password = new OsuPasswordTextBox - { - PlaceholderText = "password", - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this, - }, - new SettingsCheckbox - { - LabelText = "Remember username", - Current = config.GetBindable(OsuSetting.SaveUsername), - }, - new SettingsCheckbox - { - LabelText = "Stay signed in", - Current = config.GetBindable(OsuSetting.SavePassword), - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - shakeSignIn = new ShakeContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = new SettingsButton - { - Text = "Sign in", - Action = performLogin - }, - } - } - }, - new SettingsButton - { - Text = "Register", - Action = () => - { - RequestHide(); - accountCreation.Show(); - } - } - }; - - password.OnCommit += (sender, newText) => performLogin(); - } - - public override bool AcceptsFocus => true; - - protected override bool OnClick(ClickEvent e) => true; - - protected override void OnFocus(FocusEvent e) - { - Schedule(() => { GetContainingInputManager().ChangeFocus(string.IsNullOrEmpty(username.Text) ? username : password); }); - } - } - - private class UserDropdown : OsuEnumDropdown - { - protected override DropdownHeader CreateHeader() => new UserDropdownHeader(); - - protected override DropdownMenu CreateMenu() => new UserDropdownMenu(); - - public Color4 StatusColour - { - set - { - if (Header is UserDropdownHeader h) - h.StatusColour = value; - } - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - AccentColour = colours.Gray5; - } - - private class UserDropdownMenu : OsuDropdownMenu - { - public UserDropdownMenu() - { - Masking = true; - CornerRadius = 5; - - Margin = new MarginPadding { Bottom = 5 }; - - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(0.25f), - Radius = 4, - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - BackgroundColour = colours.Gray3; - } - - protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new DrawableUserDropdownMenuItem(item); - - private class DrawableUserDropdownMenuItem : DrawableOsuDropdownMenuItem - { - public DrawableUserDropdownMenuItem(MenuItem item) - : base(item) - { - Foreground.Padding = new MarginPadding { Top = 5, Bottom = 5, Left = 10, Right = 5 }; - CornerRadius = 5; - } - - protected override Drawable CreateContent() => new Content - { - Label = { Margin = new MarginPadding { Left = UserDropdownHeader.LABEL_LEFT_MARGIN - 11 } } - }; - } - } - - private class UserDropdownHeader : OsuDropdownHeader - { - public const float LABEL_LEFT_MARGIN = 20; - - private readonly SpriteIcon statusIcon; - - public Color4 StatusColour - { - set => statusIcon.FadeColour(value, 500, Easing.OutQuint); - } - - public UserDropdownHeader() - { - Foreground.Padding = new MarginPadding { Left = 10, Right = 10 }; - Margin = new MarginPadding { Bottom = 5 }; - Masking = true; - CornerRadius = 5; - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(0.25f), - Radius = 4, - }; - - Icon.Size = new Vector2(14); - Icon.Margin = new MarginPadding(0); - - Foreground.Add(statusIcon = new SpriteIcon - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Icon = FontAwesome.Regular.Circle, - Size = new Vector2(14), - }); - - Text.Margin = new MarginPadding { Left = LABEL_LEFT_MARGIN }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - BackgroundColour = colours.Gray3; - } - } - } - - private enum UserAction - { - Online, - - [Description(@"Do not disturb")] - DoNotDisturb, - - [Description(@"Appear offline")] - AppearOffline, - - [Description(@"Sign out")] - SignOut, - } - } -} From e49d8d0878c9efc5faebad745171cf02e43a6152 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Sep 2021 17:36:17 +0900 Subject: [PATCH 102/109] Add test coverage of login dialog --- .../Visual/Menus/TestSceneLoginPanel.cs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs new file mode 100644 index 0000000000..5fdadfc2fb --- /dev/null +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs @@ -0,0 +1,41 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Testing; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Login; + +namespace osu.Game.Tests.Visual.Menus +{ + [TestFixture] + public class TestSceneLoginPanel : OsuManualInputManagerTestScene + { + private LoginPanel loginPanel; + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("create login dialog", () => + { + Add(loginPanel = new LoginPanel + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 0.5f, + }); + }); + } + + [Test] + public void TestBasicLogin() + { + AddStep("logout", () => API.Logout()); + + AddStep("enter password", () => loginPanel.ChildrenOfType().First().Text = "password"); + AddStep("submit", () => loginPanel.ChildrenOfType().First(b => b.Text.ToString() == "Sign in").TriggerClick()); + } + } +} From 2d3913120259fdb34311c423bc691828d2d99c58 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Sep 2021 18:41:03 +0900 Subject: [PATCH 103/109] Refactor taiko flashlight a bit --- .../Mods/TaikoModFlashlight.cs | 17 +++++++++-------- osu.Game/Rulesets/Mods/ModFlashlight.cs | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs index 3578e3a734..19ba99586b 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs @@ -36,24 +36,25 @@ namespace osu.Game.Rulesets.Taiko.Mods public TaikoFlashlight(TaikoPlayfield taikoPlayfield) { this.taikoPlayfield = taikoPlayfield; - FlashlightSize = new Vector2(0, getSizeFor(0)); + FlashlightSize = getSizeFor(0); AddLayout(flashlightProperties); } - private float getSizeFor(int combo) + private Vector2 getSizeFor(int combo) { if (combo > 200) - return default_flashlight_size * 0.8f; - else if (combo > 100) - return default_flashlight_size * 0.9f; - else - return default_flashlight_size; + return new Vector2(0, default_flashlight_size * 0.8f); + + if (combo > 100) + return new Vector2(0, default_flashlight_size * 0.9f); + + return new Vector2(0, default_flashlight_size); } protected override void OnComboChange(ValueChangedEvent e) { - this.TransformTo(nameof(FlashlightSize), new Vector2(0, getSizeFor(e.NewValue)), FLASHLIGHT_FADE_DURATION); + this.TransformTo(nameof(FlashlightSize), getSizeFor(e.NewValue), FLASHLIGHT_FADE_DURATION); } protected override string FragmentShader => "CircularFlashlight"; diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 7abae71273..f96f8a3c1b 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Mods public abstract class Flashlight : Drawable { - internal BindableInt Combo; + protected internal BindableInt Combo { get; internal set; } private IShader shader; protected override DrawNode CreateDrawNode() => new FlashlightDrawNode(this); From 35c3d75cb8d720583e7b010ff026fdd7885b773c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Sep 2021 18:51:43 +0900 Subject: [PATCH 104/109] Preserve flashlight size through aspect adjustment --- .../Mods/TaikoModFlashlight.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs index 19ba99586b..12f19a0086 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs @@ -43,13 +43,17 @@ namespace osu.Game.Rulesets.Taiko.Mods private Vector2 getSizeFor(int combo) { + Vector2 size; + if (combo > 200) - return new Vector2(0, default_flashlight_size * 0.8f); + size = new Vector2(0, default_flashlight_size * 0.8f); + else if (combo > 100) + size = new Vector2(0, default_flashlight_size * 0.9f); + else + size = new Vector2(0, default_flashlight_size); - if (combo > 100) - return new Vector2(0, default_flashlight_size * 0.9f); - - return new Vector2(0, default_flashlight_size); + // Preserve flashlight size through the playfield's aspect adjustment. + return size * taikoPlayfield.DrawHeight / TaikoPlayfield.DEFAULT_HEIGHT; } protected override void OnComboChange(ValueChangedEvent e) @@ -66,6 +70,10 @@ namespace osu.Game.Rulesets.Taiko.Mods if (!flashlightProperties.IsValid) { FlashlightPosition = ToLocalSpace(taikoPlayfield.HitTarget.ScreenSpaceDrawQuad.Centre); + + ClearTransforms(targetMember: nameof(FlashlightSize)); + FlashlightSize = getSizeFor(Combo.Value); + flashlightProperties.Validate(); } } From a743a3f3067e375516a0d1bd7c8a37b93400c7cf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Sep 2021 19:15:14 +0900 Subject: [PATCH 105/109] Change combo bind logic to be non-weird --- osu.Game/Rulesets/Mods/ModFlashlight.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index f96f8a3c1b..a77a83b36c 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -69,9 +69,11 @@ namespace osu.Game.Rulesets.Mods public virtual void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { var flashlight = CreateFlashlight(); - flashlight.Combo = Combo; + flashlight.RelativeSizeAxes = Axes.Both; flashlight.Colour = Color4.Black; + + flashlight.Combo.BindTo(Combo); drawableRuleset.KeyBindingInputManager.Add(flashlight); flashlight.Breaks = drawableRuleset.Beatmap.Breaks; @@ -81,7 +83,8 @@ namespace osu.Game.Rulesets.Mods public abstract class Flashlight : Drawable { - protected internal BindableInt Combo { get; internal set; } + public readonly BindableInt Combo = new BindableInt(); + private IShader shader; protected override DrawNode CreateDrawNode() => new FlashlightDrawNode(this); From be7346d0b76febd7e741e0fe6f97518d3140d2c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Sep 2021 19:18:37 +0900 Subject: [PATCH 106/109] Refactor `getSizeFor` to read a touch better --- osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs index 12f19a0086..0a325f174e 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs @@ -43,17 +43,15 @@ namespace osu.Game.Rulesets.Taiko.Mods private Vector2 getSizeFor(int combo) { - Vector2 size; + float size = default_flashlight_size; if (combo > 200) - size = new Vector2(0, default_flashlight_size * 0.8f); + size *= 0.8f; else if (combo > 100) - size = new Vector2(0, default_flashlight_size * 0.9f); - else - size = new Vector2(0, default_flashlight_size); + size *= 0.9f; // Preserve flashlight size through the playfield's aspect adjustment. - return size * taikoPlayfield.DrawHeight / TaikoPlayfield.DEFAULT_HEIGHT; + return new Vector2(0, size * taikoPlayfield.DrawHeight / TaikoPlayfield.DEFAULT_HEIGHT); } protected override void OnComboChange(ValueChangedEvent e) From 9485323a13755b5b9736525bb3a0d90a74f8d2c3 Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Fri, 17 Sep 2021 20:52:13 +0900 Subject: [PATCH 107/109] Add audio feedback for incorrect MP room password --- osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index a823db282c..70dc14951c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -189,9 +189,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge private OsuPasswordTextBox passwordTextbox; private TriangleButton joinButton; private OsuSpriteText errorText; + private Sample sampleJoinFail; [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, AudioManager audio) { Child = new FillFlowContainer { @@ -227,6 +228,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge } }; + sampleJoinFail = audio.Samples.Get(@"UI/password-fail"); + joinButton.Action = () => lounge?.Join(room, passwordTextbox.Text, null, joinFailed); } @@ -244,6 +247,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge .FadeOutFromOne(1000, Easing.In); Body.Shake(); + + Schedule(() => { sampleJoinFail?.Play(); }); } protected override void LoadComplete() From f868feae44044af55106fc9789fb4de637b427f8 Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Fri, 17 Sep 2021 21:12:39 +0900 Subject: [PATCH 108/109] Remove unnecessary Schedule --- osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 70dc14951c..fe7c7cc364 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -248,7 +248,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge Body.Shake(); - Schedule(() => { sampleJoinFail?.Play(); }); + sampleJoinFail?.Play(); } protected override void LoadComplete() From cc11532d9b48421b5dbbd6915134ef75115f597e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 18 Sep 2021 03:08:42 +0900 Subject: [PATCH 109/109] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 0e60a5a99e..4859510e6c 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -51,7 +51,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 390b026497..0460de6d72 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 2158772b83..51ca381b63 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -71,7 +71,7 @@ - +