diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs
index c2c1f6d602..aaf3517c9c 100644
--- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs
+++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs
@@ -12,12 +12,23 @@ using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Screens.Edit.Compose.Components;
-using osuTK;
+using Vector2 = osuTK.Vector2;
namespace osu.Game.Rulesets.Osu.Edit
{
public class OsuSelectionHandler : EditorSelectionHandler
{
+ ///
+ /// During a transform, the initial origin is stored so it can be used throughout the operation.
+ ///
+ private Vector2? referenceOrigin;
+
+ ///
+ /// During a transform, the initial path types of a single selected slider are stored so they
+ /// can be maintained throughout the operation.
+ ///
+ private List referencePathTypes;
+
protected override void OnSelectionChanged()
{
base.OnSelectionChanged();
@@ -50,17 +61,6 @@ namespace osu.Game.Rulesets.Osu.Edit
return true;
}
- ///
- /// During a transform, the initial origin is stored so it can be used throughout the operation.
- ///
- private Vector2? referenceOrigin;
-
- ///
- /// During a transform, the initial path types of a single selected slider are stored so they
- /// can be maintained throughout the operation.
- ///
- private List referencePathTypes;
-
public override bool HandleReverse()
{
var hitObjects = EditorBeatmap.SelectedHitObjects;
@@ -114,24 +114,10 @@ namespace osu.Game.Rulesets.Osu.Edit
var hitObjects = selectedMovableObjects;
var selectedObjectsQuad = getSurroundingQuad(hitObjects);
- var centre = selectedObjectsQuad.Centre;
foreach (var h in hitObjects)
{
- var pos = h.Position;
-
- switch (direction)
- {
- case Direction.Horizontal:
- pos.X = centre.X - (pos.X - centre.X);
- break;
-
- case Direction.Vertical:
- pos.Y = centre.Y - (pos.Y - centre.Y);
- break;
- }
-
- h.Position = pos;
+ h.Position = GetFlippedPosition(direction, selectedObjectsQuad, h.Position);
if (h is Slider slider)
{
@@ -204,7 +190,7 @@ namespace osu.Game.Rulesets.Osu.Edit
{
referencePathTypes ??= slider.Path.ControlPoints.Select(p => p.Type.Value).ToList();
- Quad sliderQuad = getSurroundingQuad(slider.Path.ControlPoints.Select(p => p.Position.Value));
+ Quad sliderQuad = GetSurroundingQuad(slider.Path.ControlPoints.Select(p => p.Position.Value));
// Limit minimum distance between control points after scaling to almost 0. Less than 0 causes the slider to flip, exactly 0 causes a crash through division by 0.
scale = Vector2.ComponentMax(new Vector2(Precision.FLOAT_EPSILON), sliderQuad.Size + scale) - sliderQuad.Size;
@@ -333,7 +319,7 @@ namespace osu.Game.Rulesets.Osu.Edit
///
/// The hit objects to calculate a quad for.
private Quad getSurroundingQuad(OsuHitObject[] hitObjects) =>
- getSurroundingQuad(hitObjects.SelectMany(h =>
+ GetSurroundingQuad(hitObjects.SelectMany(h =>
{
if (h is IHasPath path)
{
@@ -348,30 +334,6 @@ namespace osu.Game.Rulesets.Osu.Edit
return new[] { h.Position };
}));
- ///
- /// Returns a gamefield-space quad surrounding the provided points.
- ///
- /// The points to calculate a quad for.
- private Quad getSurroundingQuad(IEnumerable points)
- {
- if (!EditorBeatmap.SelectedHitObjects.Any())
- return new Quad();
-
- Vector2 minPosition = new Vector2(float.MaxValue, float.MaxValue);
- Vector2 maxPosition = new Vector2(float.MinValue, float.MinValue);
-
- // Go through all hitobjects to make sure they would remain in the bounds of the editor after movement, before any movement is attempted
- foreach (var p in points)
- {
- minPosition = Vector2.ComponentMin(minPosition, p);
- maxPosition = Vector2.ComponentMax(maxPosition, p);
- }
-
- Vector2 size = maxPosition - minPosition;
-
- return new Quad(minPosition.X, minPosition.Y, size.X, size.Y);
- }
-
///
/// All osu! hitobjects which can be moved/rotated/scaled.
///
diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs
index 6d8ae69812..bfd5ab7afa 100644
--- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs
+++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs
@@ -350,5 +350,55 @@ namespace osu.Game.Screens.Edit.Compose.Components
=> Enumerable.Empty