diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index b3e0566a98..dd1a2d69fb 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -16,11 +16,9 @@ using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Framework.Utils; using osu.Game.Graphics; -using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Screens.Edit; using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -33,6 +31,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public class PathControlPointPiece : BlueprintPiece, IHasTooltip { public Action RequestSelection; + + public Action DragStarted; + public Action DragInProgress; + public Action DragEnded; + public List PointsInSegment; public readonly BindableBool IsSelected = new BindableBool(); @@ -42,12 +45,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private readonly Container marker; private readonly Drawable markerRing; - [Resolved(CanBeNull = true)] - private IEditorChangeHandler changeHandler { get; set; } - - [Resolved(CanBeNull = true)] - private IPositionSnapProvider snapProvider { get; set; } - [Resolved] private OsuColour colours { get; set; } @@ -160,9 +157,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components protected override bool OnClick(ClickEvent e) => RequestSelection != null; - private Vector2 dragStartPosition; - private PathType? dragPathType; - protected override bool OnDragStart(DragStartEvent e) { if (RequestSelection == null) @@ -170,54 +164,16 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components if (e.Button == MouseButton.Left) { - dragStartPosition = ControlPoint.Position; - dragPathType = PointsInSegment[0].Type; - - changeHandler?.BeginChange(); + DragStarted?.Invoke(ControlPoint); return true; } return false; } - protected override void OnDrag(DragEvent e) - { - Vector2[] oldControlPoints = slider.Path.ControlPoints.Select(cp => cp.Position).ToArray(); - var oldPosition = slider.Position; - double oldStartTime = slider.StartTime; + protected override void OnDrag(DragEvent e) => DragInProgress?.Invoke(ControlPoint, e); - if (ControlPoint == slider.Path.ControlPoints[0]) - { - // Special handling for the head control point - the position of the slider changes which means the snapped position and time have to be taken into account - var result = snapProvider?.SnapScreenSpacePositionToValidTime(e.ScreenSpaceMousePosition); - - Vector2 movementDelta = Parent.ToLocalSpace(result?.ScreenSpacePosition ?? e.ScreenSpaceMousePosition) - slider.Position; - - slider.Position += movementDelta; - slider.StartTime = result?.Time ?? slider.StartTime; - - // Since control points are relative to the position of the slider, they all need to be offset backwards by the delta - for (int i = 1; i < slider.Path.ControlPoints.Count; i++) - slider.Path.ControlPoints[i].Position -= movementDelta; - } - else - ControlPoint.Position = dragStartPosition + (e.MousePosition - e.MouseDownPosition); - - if (!slider.Path.HasValidLength) - { - for (int i = 0; i < slider.Path.ControlPoints.Count; i++) - slider.Path.ControlPoints[i].Position = oldControlPoints[i]; - - slider.Position = oldPosition; - slider.StartTime = oldStartTime; - return; - } - - // Maintain the path type in case it got defaulted to bezier at some point during the drag. - PointsInSegment[0].Type = dragPathType; - } - - protected override void OnDragEnd(DragEndEvent e) => changeHandler?.EndChange(); + protected override void OnDragEnd(DragEndEvent e) => DragEnded?.Invoke(); private void cachePoints(Slider slider) => PointsInSegment = slider.Path.PointsInSegment(ControlPoint); 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 1be9b5bf2e..017bc395f0 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -16,6 +16,7 @@ using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; @@ -40,6 +41,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public Action> RemoveControlPointsRequested; + [Resolved(CanBeNull = true)] + private IPositionSnapProvider snapProvider { get; set; } + public PathControlPointVisualiser(Slider slider, bool allowSelection) { this.slider = slider; @@ -88,6 +92,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { if (allowSelection) d.RequestSelection = selectPiece; + + d.DragStarted = dragStarted; + d.DragInProgress = dragInProgress; + d.DragEnded = dragEnded; })); Connections.Add(new PathControlPointConnectionPiece(slider, e.NewStartingIndex + i)); @@ -203,6 +211,60 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return true; } + #region Drag handling + + private Vector2 dragStartPosition; + private PathType? dragPathType; + + private void dragStarted(PathControlPoint controlPoint) + { + dragStartPosition = controlPoint.Position; + dragPathType = slider.Path.PointsInSegment(controlPoint).First().Type; + + changeHandler?.BeginChange(); + } + + private void dragInProgress(PathControlPoint controlPoint, DragEvent e) + { + Vector2[] oldControlPoints = slider.Path.ControlPoints.Select(cp => cp.Position).ToArray(); + var oldPosition = slider.Position; + double oldStartTime = slider.StartTime; + + if (controlPoint == slider.Path.ControlPoints[0]) + { + // Special handling for the head control point - the position of the slider changes which means the snapped position and time have to be taken into account + var result = snapProvider?.SnapScreenSpacePositionToValidTime(e.ScreenSpaceMousePosition); + + Vector2 movementDelta = Parent.ToLocalSpace(result?.ScreenSpacePosition ?? e.ScreenSpaceMousePosition) - slider.Position; + + slider.Position += movementDelta; + slider.StartTime = result?.Time ?? slider.StartTime; + + // Since control points are relative to the position of the slider, they all need to be offset backwards by the delta + for (int i = 1; i < slider.Path.ControlPoints.Count; i++) + slider.Path.ControlPoints[i].Position -= movementDelta; + } + else + controlPoint.Position = dragStartPosition + (e.MousePosition - e.MouseDownPosition); + + if (!slider.Path.HasValidLength) + { + for (int i = 0; i < slider.Path.ControlPoints.Count; i++) + slider.Path.ControlPoints[i].Position = oldControlPoints[i]; + + slider.Position = oldPosition; + slider.StartTime = oldStartTime; + return; + } + + // Maintain the path type in case it got defaulted to bezier at some point during the drag. + slider.Path.PointsInSegment(controlPoint).First().Type = dragPathType; + } + + private void dragEnded() => changeHandler?.EndChange(); + + #endregion + public MenuItem[] ContextMenuItems { get