diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs index ecd7732862..f2d27b9117 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs @@ -106,6 +106,49 @@ namespace osu.Game.Tests.Visual.Editing assertBeatSnap(16); } + [Test] + public void TestKeyboardNavigation() + { + pressKey(1); + assertBeatSnap(1); + assertPreset(BeatDivisorType.Common); + + pressKey(2); + assertBeatSnap(2); + assertPreset(BeatDivisorType.Common); + + pressKey(3); + assertBeatSnap(3); + assertPreset(BeatDivisorType.Triplets); + + pressKey(4); + assertBeatSnap(4); + assertPreset(BeatDivisorType.Common); + + pressKey(5); + assertBeatSnap(5); + assertPreset(BeatDivisorType.Custom, 5); + + pressKey(6); + assertBeatSnap(6); + assertPreset(BeatDivisorType.Triplets); + + pressKey(7); + assertBeatSnap(7); + assertPreset(BeatDivisorType.Custom, 7); + + pressKey(8); + assertBeatSnap(8); + assertPreset(BeatDivisorType.Common); + + void pressKey(int key) => AddStep($"press shift+{key}", () => + { + InputManager.PressKey(Key.ShiftLeft); + InputManager.Key(Key.Number0 + key); + InputManager.ReleaseKey(Key.ShiftLeft); + }); + } + [Test] public void TestBeatPresetNavigation() { diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBindings.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBindings.cs new file mode 100644 index 0000000000..5771d64775 --- /dev/null +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBindings.cs @@ -0,0 +1,32 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.Editing +{ + /// + /// Test editor hotkeys at a high level to ensure they all work well together. + /// + public class TestSceneEditorBindings : EditorTestScene + { + protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); + + [Test] + public void TestBeatDivisorChangeHotkeys() + { + AddStep("hold shift", () => InputManager.PressKey(Key.LShift)); + + AddStep("press 4", () => InputManager.Key(Key.Number4)); + AddAssert("snap updated to 4", () => EditorBeatmap.BeatmapInfo.BeatDivisor, () => Is.EqualTo(4)); + + AddStep("press 6", () => InputManager.Key(Key.Number6)); + AddAssert("snap updated to 6", () => EditorBeatmap.BeatmapInfo.BeatDivisor, () => Is.EqualTo(6)); + + AddStep("release shift", () => InputManager.ReleaseKey(Key.LShift)); + } + } +} diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 3bed835854..520fcb0290 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -238,7 +238,7 @@ namespace osu.Game.Rulesets.Edit protected override bool OnKeyDown(KeyDownEvent e) { - if (e.ControlPressed || e.AltPressed || e.SuperPressed) + if (e.ControlPressed || e.AltPressed || e.SuperPressed || e.ShiftPressed) return false; if (checkLeftToggleFromKey(e.Key, out int leftIndex)) diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index a7faf961cf..aa8e202e22 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -25,6 +25,26 @@ namespace osu.Game.Screens.Edit BindValueChanged(_ => ensureValidDivisor()); } + /// + /// Set a divisor, updating the valid divisor range appropriately. + /// + /// The intended divisor. + public void SetArbitraryDivisor(int divisor) + { + // If the current valid divisor range doesn't contain the proposed value, attempt to find one which does. + if (!ValidDivisors.Value.Presets.Contains(divisor)) + { + if (BeatDivisorPresetCollection.COMMON.Presets.Contains(divisor)) + ValidDivisors.Value = BeatDivisorPresetCollection.COMMON; + else if (BeatDivisorPresetCollection.TRIPLETS.Presets.Contains(divisor)) + ValidDivisors.Value = BeatDivisorPresetCollection.TRIPLETS; + else + ValidDivisors.Value = BeatDivisorPresetCollection.Custom(divisor); + } + + Value = divisor; + } + private void updateBindableProperties() { ensureValidDivisor(); diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 19ea2162a3..6dca799549 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -209,6 +209,17 @@ namespace osu.Game.Screens.Edit.Compose.Components } } + protected override bool OnKeyDown(KeyDownEvent e) + { + if (e.ShiftPressed && e.Key >= Key.Number1 && e.Key <= Key.Number9) + { + beatDivisor.SetArbitraryDivisor(e.Key - Key.Number0); + return true; + } + + return base.OnKeyDown(e); + } + internal class DivisorDisplay : OsuAnimatedButton, IHasPopover { public BindableBeatDivisor BeatDivisor { get; } = new BindableBeatDivisor(); @@ -306,17 +317,7 @@ namespace osu.Game.Screens.Edit.Compose.Components return; } - if (!BeatDivisor.ValidDivisors.Value.Presets.Contains(divisor)) - { - if (BeatDivisorPresetCollection.COMMON.Presets.Contains(divisor)) - BeatDivisor.ValidDivisors.Value = BeatDivisorPresetCollection.COMMON; - else if (BeatDivisorPresetCollection.TRIPLETS.Presets.Contains(divisor)) - BeatDivisor.ValidDivisors.Value = BeatDivisorPresetCollection.TRIPLETS; - else - BeatDivisor.ValidDivisors.Value = BeatDivisorPresetCollection.Custom(divisor); - } - - BeatDivisor.Value = divisor; + BeatDivisor.SetArbitraryDivisor(divisor); this.HidePopover(); }