From 65f7ecec835da17236201a96cd9182e791981529 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 20 Aug 2022 00:26:04 +0200 Subject: [PATCH 1/4] moving all controlpoints at once for slider --- .../Edit/OsuSelectionHandler.cs | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index f3c0a05bc2..bb78db68da 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -127,13 +127,14 @@ namespace osu.Game.Rulesets.Osu.Edit { didFlip = true; - foreach (var point in slider.Path.ControlPoints) - { - point.Position = new Vector2( - (direction == Direction.Horizontal ? -1 : 1) * point.Position.X, - (direction == Direction.Vertical ? -1 : 1) * point.Position.Y - ); - } + var controlPoints = slider.Path.ControlPoints.Select(p => + new PathControlPoint(new Vector2( + (direction == Direction.Horizontal ? -1 : 1) * p.Position.X, + (direction == Direction.Vertical ? -1 : 1) * p.Position.Y + ), p.Type)).ToArray(); + + slider.Path.ControlPoints.Clear(); + slider.Path.ControlPoints.AddRange(controlPoints); } } @@ -183,8 +184,11 @@ namespace osu.Game.Rulesets.Osu.Edit if (h is IHasPath path) { - foreach (var point in path.Path.ControlPoints) - point.Position = RotatePointAroundOrigin(point.Position, Vector2.Zero, delta); + var controlPoints = path.Path.ControlPoints.Select(p => + new PathControlPoint(RotatePointAroundOrigin(p.Position, Vector2.Zero, delta), p.Type)).ToArray(); + + path.Path.ControlPoints.Clear(); + path.Path.ControlPoints.AddRange(controlPoints); } } From 36e202c70ec33051b28d36be48b53d914d71ee05 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 20 Aug 2022 11:38:43 +0900 Subject: [PATCH 2/4] Add inline comment explaining necessity to use `AddRange` for slider transform operations --- osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index bb78db68da..061c5008c5 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -133,6 +133,8 @@ namespace osu.Game.Rulesets.Osu.Edit (direction == Direction.Vertical ? -1 : 1) * p.Position.Y ), p.Type)).ToArray(); + // Importantly, update as a single operation so automatic adjustment of control points to different + // curve types does not unexpectedly trigger and change the slider's shape. slider.Path.ControlPoints.Clear(); slider.Path.ControlPoints.AddRange(controlPoints); } @@ -187,6 +189,8 @@ namespace osu.Game.Rulesets.Osu.Edit var controlPoints = path.Path.ControlPoints.Select(p => new PathControlPoint(RotatePointAroundOrigin(p.Position, Vector2.Zero, delta), p.Type)).ToArray(); + // Importantly, update as a single operation so automatic adjustment of control points to different + // curve types does not unexpectedly trigger and change the slider's shape. path.Path.ControlPoints.Clear(); path.Path.ControlPoints.AddRange(controlPoints); } From 614ae815c0f1a5ae6315507fd40c7aedf418c7e7 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 20 Aug 2022 15:57:03 +0200 Subject: [PATCH 3/4] Added tests for making sure flipping and rotating retains perfect control point type --- .../Editor/TestSceneSliderSnapping.cs | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs index a72f2031c9..59f40894e0 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs @@ -12,6 +12,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Input.Bindings; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Objects; @@ -55,9 +56,9 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor { ControlPoints = { - new PathControlPoint(Vector2.Zero), - new PathControlPoint(OsuPlayfield.BASE_SIZE * 2 / 5), - new PathControlPoint(OsuPlayfield.BASE_SIZE * 3 / 5) + new PathControlPoint(Vector2.Zero, PathType.PerfectCurve), + new PathControlPoint(new Vector2(136, 205)), + new PathControlPoint(new Vector2(-4, 226)) } } })); @@ -99,8 +100,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor AddStep("move mouse to new point location", () => { var firstPiece = this.ChildrenOfType().Single(piece => piece.ControlPoint == slider.Path.ControlPoints[0]); - var secondPiece = this.ChildrenOfType().Single(piece => piece.ControlPoint == slider.Path.ControlPoints[1]); - InputManager.MoveMouseTo((firstPiece.ScreenSpaceDrawQuad.Centre + secondPiece.ScreenSpaceDrawQuad.Centre) / 2); + var pos = slider.Path.PositionAt(0.25d) + slider.Position; + InputManager.MoveMouseTo(firstPiece.Parent.ToScreenSpace(pos)); }); AddStep("move slider end", () => { @@ -175,6 +176,23 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor assertSliderSnapped(false); } + [Test] + public void TestRotatingSliderRetainsPerfectControlPointType() + { + OsuSelectionHandler selectionHandler = null; + + AddAssert("first control point perfect", () => slider.Path.ControlPoints[0].Type == PathType.PerfectCurve); + + AddStep("select slider", () => EditorBeatmap.SelectedHitObjects.Add(slider)); + AddStep("rotate 90 degrees ccw", () => + { + selectionHandler = this.ChildrenOfType().Single(); + selectionHandler.HandleRotation(-90); + }); + + AddAssert("first control point still perfect", () => slider.Path.ControlPoints[0].Type == PathType.PerfectCurve); + } + [Test] public void TestFlippingSliderDoesNotSnap() { @@ -200,6 +218,23 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor assertSliderSnapped(false); } + [Test] + public void TestFlippingSliderRetainsPerfectControlPointType() + { + OsuSelectionHandler selectionHandler = null; + + AddAssert("first control point perfect", () => slider.Path.ControlPoints[0].Type == PathType.PerfectCurve); + + AddStep("select slider", () => EditorBeatmap.SelectedHitObjects.Add(slider)); + AddStep("flip slider horizontally", () => + { + selectionHandler = this.ChildrenOfType().Single(); + selectionHandler.OnPressed(new KeyBindingPressEvent(InputManager.CurrentState, GlobalAction.EditorFlipVertically)); + }); + + AddAssert("first control point still perfect", () => slider.Path.ControlPoints[0].Type == PathType.PerfectCurve); + } + [Test] public void TestReversingSliderDoesNotSnap() { From 7732fb21d5de1873483c713e3a8a70354b616bdb Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 20 Aug 2022 16:09:02 +0200 Subject: [PATCH 4/4] fix code quality --- osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs index 59f40894e0..e864afe056 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs @@ -179,7 +179,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor [Test] public void TestRotatingSliderRetainsPerfectControlPointType() { - OsuSelectionHandler selectionHandler = null; + OsuSelectionHandler selectionHandler; AddAssert("first control point perfect", () => slider.Path.ControlPoints[0].Type == PathType.PerfectCurve); @@ -221,7 +221,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor [Test] public void TestFlippingSliderRetainsPerfectControlPointType() { - OsuSelectionHandler selectionHandler = null; + OsuSelectionHandler selectionHandler; AddAssert("first control point perfect", () => slider.Path.ControlPoints[0].Type == PathType.PerfectCurve);