diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index 7323c7a91a..09d1ff663d 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -114,6 +114,26 @@ namespace osu.Game.Rulesets.Catch.Edit { } + protected override bool OnKeyDown(KeyDownEvent e) + { + if (e.Repeat) + return false; + + handleToggleViaKey(e); + return base.OnKeyDown(e); + } + + protected override void OnKeyUp(KeyUpEvent e) + { + handleToggleViaKey(e); + base.OnKeyUp(e); + } + + private void handleToggleViaKey(KeyboardEvent key) + { + DistanceSnapProvider.HandleToggleViaKey(key); + } + public override SnapResult FindSnappedPositionAndTime(Vector2 screenSpacePosition, SnapType snapType = SnapType.All) { var result = base.FindSnappedPositionAndTime(screenSpacePosition, snapType); diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 4368a338b2..2b5de8a5d8 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -369,6 +369,8 @@ namespace osu.Game.Rulesets.Osu.Edit gridSnapMomentary = shiftPressed; rectangularGridSnapToggle.Value = rectangularGridSnapToggle.Value == TernaryState.False ? TernaryState.True : TernaryState.False; } + + DistanceSnapProvider.HandleToggleViaKey(key); } private DistanceSnapGrid createDistanceSnapGrid(IEnumerable selectedHitObjects) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs b/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs index 3884a3108f..cbc9088d04 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using NUnit.Framework; +using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; using osu.Framework.Testing; @@ -36,6 +37,9 @@ namespace osu.Game.Tests.Visual.Editing private ContextMenuContainer contextMenuContainer => Editor.ChildrenOfType().First(); + private SelectionBoxScaleHandle getScaleHandle(Anchor anchor) + => Editor.ChildrenOfType().First(it => it.Anchor == anchor); + private void moveMouseToObject(Func targetFunc) { AddStep("move mouse to object", () => @@ -519,5 +523,137 @@ namespace osu.Game.Tests.Visual.Editing AddStep("release shift", () => InputManager.ReleaseKey(Key.ShiftLeft)); } + + [Test] + public void TestShiftModifierMaintainsAspectRatio() + { + HitCircle[] addedObjects = null!; + + float aspectRatioBeforeDrag = 0; + + float getAspectRatio() => (addedObjects[1].X - addedObjects[0].X) / (addedObjects[1].Y - addedObjects[0].Y); + + AddStep("add hitobjects", () => + { + EditorBeatmap.AddRange(addedObjects = new[] + { + new HitCircle { StartTime = 100, Position = new Vector2(150, 150) }, + new HitCircle { StartTime = 200, Position = new Vector2(250, 200) }, + }); + + aspectRatioBeforeDrag = getAspectRatio(); + }); + + AddStep("select objects", () => EditorBeatmap.SelectedHitObjects.AddRange(addedObjects)); + + AddStep("move mouse to handle", () => InputManager.MoveMouseTo(getScaleHandle(Anchor.BottomRight).ScreenSpaceDrawQuad.Centre)); + + AddStep("begin drag", () => InputManager.PressButton(MouseButton.Left)); + + AddStep("move mouse", () => InputManager.MoveMouseTo(InputManager.CurrentState.Mouse.Position + new Vector2(50, 0))); + + AddStep("aspect ratio does not equal", () => Assert.AreNotEqual(aspectRatioBeforeDrag, getAspectRatio())); + + AddStep("press shift", () => InputManager.PressKey(Key.ShiftLeft)); + + AddStep("aspect ratio does equal", () => Assert.AreEqual(aspectRatioBeforeDrag, getAspectRatio())); + + AddStep("end drag", () => InputManager.ReleaseButton(MouseButton.Left)); + + AddStep("release shift", () => InputManager.ReleaseKey(Key.ShiftLeft)); + } + + [Test] + public void TestAltModifierScalesAroundCenter() + { + HitCircle[] addedObjects = null!; + + Vector2 centerBeforeDrag = Vector2.Zero; + + Vector2 getCenter() => (addedObjects[0].Position + addedObjects[1].Position) / 2; + + AddStep("add hitobjects", () => + { + EditorBeatmap.AddRange(addedObjects = new[] + { + new HitCircle { StartTime = 100, Position = new Vector2(150, 150) }, + new HitCircle { StartTime = 200, Position = new Vector2(250, 200) }, + }); + + centerBeforeDrag = getCenter(); + }); + + AddStep("select objects", () => EditorBeatmap.SelectedHitObjects.AddRange(addedObjects)); + + AddStep("move mouse to handle", () => InputManager.MoveMouseTo(getScaleHandle(Anchor.BottomRight).ScreenSpaceDrawQuad.Centre)); + + AddStep("begin drag", () => InputManager.PressButton(MouseButton.Left)); + + AddStep("move mouse", () => InputManager.MoveMouseTo(InputManager.CurrentState.Mouse.Position + new Vector2(50, 0))); + + AddStep("center does not equal", () => Assert.AreNotEqual(centerBeforeDrag, getCenter())); + + AddStep("press alt", () => InputManager.PressKey(Key.AltLeft)); + + AddStep("center does equal", () => Assert.AreEqual(centerBeforeDrag, getCenter())); + + AddStep("end drag", () => InputManager.ReleaseButton(MouseButton.Left)); + + AddStep("release alt", () => InputManager.ReleaseKey(Key.AltLeft)); + } + + [Test] + public void TestShiftAndAltModifierKeys() + { + HitCircle[] addedObjects = null!; + + float aspectRatioBeforeDrag = 0; + + Vector2 centerBeforeDrag = Vector2.Zero; + + float getAspectRatio() => (addedObjects[1].X - addedObjects[0].X) / (addedObjects[1].Y - addedObjects[0].Y); + + Vector2 getCenter() => (addedObjects[0].Position + addedObjects[1].Position) / 2; + + AddStep("add hitobjects", () => + { + EditorBeatmap.AddRange(addedObjects = new[] + { + new HitCircle { StartTime = 100, Position = new Vector2(150, 150) }, + new HitCircle { StartTime = 200, Position = new Vector2(250, 200) }, + }); + + aspectRatioBeforeDrag = getAspectRatio(); + centerBeforeDrag = getCenter(); + }); + + AddStep("select objects", () => EditorBeatmap.SelectedHitObjects.AddRange(addedObjects)); + + AddStep("move mouse to handle", () => InputManager.MoveMouseTo(getScaleHandle(Anchor.BottomRight).ScreenSpaceDrawQuad.Centre)); + + AddStep("begin drag", () => InputManager.PressButton(MouseButton.Left)); + + AddStep("move mouse", () => InputManager.MoveMouseTo(InputManager.CurrentState.Mouse.Position + new Vector2(50, 0))); + + AddStep("aspect ratio does not equal", () => Assert.AreNotEqual(aspectRatioBeforeDrag, getAspectRatio())); + + AddStep("center does not equal", () => Assert.AreNotEqual(centerBeforeDrag, getCenter())); + + AddStep("press shift", () => InputManager.PressKey(Key.ShiftLeft)); + + AddStep("aspect ratio does equal", () => Assert.AreEqual(aspectRatioBeforeDrag, getAspectRatio())); + + AddStep("center does not equal", () => Assert.AreNotEqual(centerBeforeDrag, getCenter())); + + AddStep("press alt", () => InputManager.PressKey(Key.AltLeft)); + + AddStep("center does equal", () => Assert.AreEqual(centerBeforeDrag, getCenter())); + + AddStep("end drag", () => InputManager.ReleaseButton(MouseButton.Left)); + + AddStep("release shift", () => InputManager.ReleaseKey(Key.ShiftLeft)); + + AddStep("release alt", () => InputManager.ReleaseKey(Key.AltLeft)); + } } } diff --git a/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs b/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs index b9850a94a3..979492fd8b 100644 --- a/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs +++ b/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs @@ -195,22 +195,7 @@ namespace osu.Game.Rulesets.Edit new TernaryButton(DistanceSnapToggle, "Distance Snap", () => new SpriteIcon { Icon = OsuIcon.EditorDistanceSnap }) }; - protected override bool OnKeyDown(KeyDownEvent e) - { - if (e.Repeat) - return false; - - handleToggleViaKey(e); - return base.OnKeyDown(e); - } - - protected override void OnKeyUp(KeyUpEvent e) - { - handleToggleViaKey(e); - base.OnKeyUp(e); - } - - private void handleToggleViaKey(KeyboardEvent key) + public void HandleToggleViaKey(KeyboardEvent key) { bool altPressed = key.AltPressed; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs index 7b0943c1d0..3b7e29cf3d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs @@ -50,14 +50,14 @@ namespace osu.Game.Screens.Edit.Compose.Components rawScale = convertDragEventToScaleMultiplier(e); - applyScale(shouldLockAspectRatio: isCornerAnchor(originalAnchor) && e.ShiftPressed); + applyScale(shouldLockAspectRatio: isCornerAnchor(originalAnchor) && e.ShiftPressed, useDefaultOrigin: e.AltPressed); } protected override bool OnKeyDown(KeyDownEvent e) { if (IsDragged) { - applyScale(shouldLockAspectRatio: isCornerAnchor(originalAnchor) && e.ShiftPressed); + applyScale(shouldLockAspectRatio: isCornerAnchor(originalAnchor) && e.ShiftPressed, useDefaultOrigin: e.AltPressed); return true; } @@ -69,7 +69,7 @@ namespace osu.Game.Screens.Edit.Compose.Components base.OnKeyUp(e); if (IsDragged) - applyScale(shouldLockAspectRatio: isCornerAnchor(originalAnchor) && e.ShiftPressed); + applyScale(shouldLockAspectRatio: isCornerAnchor(originalAnchor) && e.ShiftPressed, useDefaultOrigin: e.AltPressed); } protected override void OnDragEnd(DragEndEvent e) @@ -100,13 +100,13 @@ namespace osu.Game.Screens.Edit.Compose.Components if ((originalAnchor & Anchor.y0) > 0) scale.Y = -scale.Y; } - private void applyScale(bool shouldLockAspectRatio) + private void applyScale(bool shouldLockAspectRatio, bool useDefaultOrigin = false) { var newScale = shouldLockAspectRatio ? new Vector2((rawScale.X + rawScale.Y) * 0.5f) : rawScale; - var scaleOrigin = originalAnchor.Opposite().PositionOnQuad(scaleHandler!.OriginalSurroundingQuad!.Value); + Vector2? scaleOrigin = useDefaultOrigin ? null : originalAnchor.Opposite().PositionOnQuad(scaleHandler!.OriginalSurroundingQuad!.Value); scaleHandler!.Update(newScale, scaleOrigin, getAdjustAxis()); }