diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index 7ae0730e39..762c4a04e7 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; using osu.Framework.Utils; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose.Components; @@ -25,6 +26,7 @@ namespace osu.Game.Rulesets.Osu.Edit SelectionBox.CanRotate = canOperate; SelectionBox.CanScaleX = canOperate; SelectionBox.CanScaleY = canOperate; + SelectionBox.CanReverse = canOperate; } protected override void OnOperationEnded() @@ -41,6 +43,54 @@ namespace osu.Game.Rulesets.Osu.Edit /// private Vector2? referenceOrigin; + public override bool HandleReverse() + { + var hitObjects = selectedMovableObjects; + + double endTime = hitObjects.Max(h => h.GetEndTime()); + double startTime = hitObjects.Min(h => h.StartTime); + + bool moreThanOneObject = hitObjects.Length > 1; + + foreach (var h in hitObjects) + { + if (moreThanOneObject) + h.StartTime = endTime - (h.GetEndTime() - startTime); + + if (h is Slider slider) + { + var points = slider.Path.ControlPoints.ToArray(); + Vector2 endPos = points.Last().Position.Value; + + slider.Path.ControlPoints.Clear(); + + slider.Position += endPos; + + PathType? lastType = null; + + for (var i = 0; i < points.Length; i++) + { + var p = points[i]; + p.Position.Value -= endPos; + + // propagate types forwards to last null type + if (i == points.Length - 1) + p.Type.Value = lastType; + else if (p.Type.Value != null) + { + var newType = p.Type.Value; + p.Type.Value = lastType; + lastType = newType; + } + + slider.Path.ControlPoints.Insert(0, p); + } + } + } + + return true; + } + public override bool HandleFlip(Direction direction) { var hitObjects = selectedMovableObjects;