From 804671ca74995c1be6f429523b1b673dc00df184 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 May 2023 21:41:19 +0900 Subject: [PATCH 1/4] Split out grid snapping modes into "relative" and "global" types --- .../Edit/CatchHitObjectComposer.cs | 2 +- .../Edit/OsuHitObjectComposer.cs | 7 +++++-- .../Editing/TestSceneDistanceSnapGrid.cs | 2 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 2 +- osu.Game/Rulesets/Edit/SnapType.cs | 20 +++++++++++++++++-- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index cd8894753f..611e69d614 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Catch.Edit result.ScreenSpacePosition.X = screenSpacePosition.X; - if (snapType.HasFlagFast(SnapType.Grids)) + if (snapType.HasFlagFast(SnapType.GlobalGrids)) { if (distanceSnapGrid.IsPresent && distanceSnapGrid.GetSnappedPosition(result.ScreenSpacePosition) is SnapResult snapResult && Vector2.Distance(snapResult.ScreenSpacePosition, result.ScreenSpacePosition) < distance_snap_radius) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index ff1e208186..ad6af6d74e 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Osu.Edit // We want to ensure that in this particular case, the time-snapping component of distance snap is still applied. // The easiest way to ensure this is to attempt application of distance snap after a nearby object is found, and copy over // the time value if the proposed positions are roughly the same. - if (snapType.HasFlagFast(SnapType.Grids) && DistanceSnapToggle.Value == TernaryState.True && distanceSnapGrid != null) + if (snapType.HasFlagFast(SnapType.RelativeGrids) && DistanceSnapToggle.Value == TernaryState.True && distanceSnapGrid != null) { (Vector2 distanceSnappedPosition, double distanceSnappedTime) = distanceSnapGrid.GetSnappedPosition(distanceSnapGrid.ToLocalSpace(snapResult.ScreenSpacePosition)); if (Precision.AlmostEquals(distanceSnapGrid.ToScreenSpace(distanceSnappedPosition), snapResult.ScreenSpacePosition, 1)) @@ -155,7 +155,7 @@ namespace osu.Game.Rulesets.Osu.Edit SnapResult result = base.FindSnappedPositionAndTime(screenSpacePosition, snapType); - if (snapType.HasFlagFast(SnapType.Grids)) + if (snapType.HasFlagFast(SnapType.RelativeGrids)) { if (DistanceSnapToggle.Value == TernaryState.True && distanceSnapGrid != null) { @@ -164,7 +164,10 @@ namespace osu.Game.Rulesets.Osu.Edit result.ScreenSpacePosition = distanceSnapGrid.ToScreenSpace(pos); result.Time = time; } + } + if (snapType.HasFlagFast(SnapType.GlobalGrids)) + { if (rectangularGridSnapToggle.Value == TernaryState.True) { Vector2 pos = rectangularPositionSnapGrid.GetSnappedPosition(rectangularPositionSnapGrid.ToLocalSpace(result.ScreenSpacePosition)); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs index 21b925a257..70e4420a45 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs @@ -187,7 +187,7 @@ namespace osu.Game.Tests.Visual.Editing private class SnapProvider : IDistanceSnapProvider { - public SnapResult FindSnappedPositionAndTime(Vector2 screenSpacePosition, SnapType snapType = SnapType.Grids) => new SnapResult(screenSpacePosition, 0); + public SnapResult FindSnappedPositionAndTime(Vector2 screenSpacePosition, SnapType snapType = SnapType.AllGrids) => new SnapResult(screenSpacePosition, 0); public Bindable DistanceSpacingMultiplier { get; } = new BindableDouble(1); diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index e2dbd2acdc..9ce6d957fc 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -428,7 +428,7 @@ namespace osu.Game.Rulesets.Edit var playfield = PlayfieldAtScreenSpacePosition(screenSpacePosition); double? targetTime = null; - if (snapType.HasFlagFast(SnapType.Grids)) + if (snapType.HasFlagFast(SnapType.GlobalGrids)) { if (playfield is ScrollingPlayfield scrollingPlayfield) { diff --git a/osu.Game/Rulesets/Edit/SnapType.cs b/osu.Game/Rulesets/Edit/SnapType.cs index 6eb46457c8..f5f9ab0437 100644 --- a/osu.Game/Rulesets/Edit/SnapType.cs +++ b/osu.Game/Rulesets/Edit/SnapType.cs @@ -11,8 +11,24 @@ namespace osu.Game.Rulesets.Edit public enum SnapType { None = 0, + + /// + /// Snapping to visible nearby objects. + /// NearbyObjects = 1 << 0, - Grids = 1 << 1, - All = NearbyObjects | Grids, + + /// + /// Grids which are global to the playfield. + /// + GlobalGrids = 1 << 1, + + /// + /// Grids which are relative to other nearby hit objects. + /// + RelativeGrids = 1 << 2, + + AllGrids = RelativeGrids | GlobalGrids, + + All = NearbyObjects | GlobalGrids | RelativeGrids, } } From 1cd69220ef640424b79f19784c557ac183333c2d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 May 2023 21:41:42 +0900 Subject: [PATCH 2/4] Fix slider path placement snapping non-head nodes to distanced snapping grid As discussed at https://github.com/ppy/osu/discussions/23531. --- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 17d0fc457a..c56ffcb140 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -309,7 +309,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components } else { - var result = snapProvider?.FindSnappedPositionAndTime(Parent.ToScreenSpace(e.MousePosition)); + var result = snapProvider?.FindSnappedPositionAndTime(Parent.ToScreenSpace(e.MousePosition), SnapType.GlobalGrids); Vector2 movementDelta = Parent.ToLocalSpace(result?.ScreenSpacePosition ?? Parent.ToScreenSpace(e.MousePosition)) - dragStartPositions[draggedControlPointIndex] - hitObject.Position; From 3c69956b55e29484888e9ec3564d1df30267aae4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 May 2023 10:41:29 +0900 Subject: [PATCH 3/4] Fix incorrect catch grid specification --- osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index 611e69d614..8afeca3e51 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Catch.Edit result.ScreenSpacePosition.X = screenSpacePosition.X; - if (snapType.HasFlagFast(SnapType.GlobalGrids)) + if (snapType.HasFlagFast(SnapType.RelativeGrids)) { if (distanceSnapGrid.IsPresent && distanceSnapGrid.GetSnappedPosition(result.ScreenSpacePosition) is SnapResult snapResult && Vector2.Distance(snapResult.ScreenSpacePosition, result.ScreenSpacePosition) < distance_snap_radius) From e35201cb991aac8b27d68cb3dd49eb431d68d844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 26 May 2023 19:51:20 +0200 Subject: [PATCH 4/4] Don't snap non-head slider nodes to distance grid during placement either 1cd69220ef640424b79f19784c557ac183333c2d only disabled snapping the aforementioned nodes to distance grid for already-placed sliders. `SliderPlacementBlueprint` has its own logic for placement, so the fix needs to be mirrored there too. --- .../Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 28ceb80627..966092c6fe 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -198,7 +198,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders } // Update the cursor position. - var result = snapProvider?.FindSnappedPositionAndTime(inputManager.CurrentState.Mouse.Position); + var result = snapProvider?.FindSnappedPositionAndTime(inputManager.CurrentState.Mouse.Position, state == SliderPlacementState.Body ? SnapType.GlobalGrids : SnapType.All); cursor.Position = ToLocalSpace(result?.ScreenSpacePosition ?? inputManager.CurrentState.Mouse.Position) - HitObject.Position; } else if (cursor != null)