Browse Source

Rounded move handle

Krzysztof Krysiński 1 year ago
parent
commit
50783eb161

+ 1 - 1
src/PixiEditor.AvaloniaUI/Views/Overlays/Handles/AnchorHandle.cs

@@ -5,7 +5,7 @@ namespace PixiEditor.AvaloniaUI.Views.Overlays.Handles;
 
 public class AnchorHandle : RectangleHandle
 {
-    public AnchorHandle(Control owner, VecD position) : base(owner, position)
+    public AnchorHandle(Control owner) : base(owner)
     {
         Size = new VecD(GetResource<double>("AnchorHandleSize"));
     }

+ 2 - 2
src/PixiEditor.AvaloniaUI/Views/Overlays/Handles/Handle.cs

@@ -31,10 +31,10 @@ public abstract class Handle : IHandle
     private bool isPressed;
     private bool isHovered;
 
-    public Handle(Control owner, VecD position)
+    public Handle(Control owner)
     {
         Owner = owner;
-        Position = position;
+        Position = VecD.Zero;
         Size = Application.Current.TryGetResource("HandleSize", out object size) ? new VecD((double)size) : new VecD(16);
 
         Owner.PointerPressed += OnPointerPressed;

+ 1 - 1
src/PixiEditor.AvaloniaUI/Views/Overlays/Handles/OriginAnchor.cs

@@ -10,7 +10,7 @@ public class OriginAnchor : Handle
 {
     public IPen? SecondaryHandlePen { get; set; } = new Pen(Brushes.White, 1);
 
-    public OriginAnchor(Control owner, VecD position) : base(owner, position)
+    public OriginAnchor(Control owner) : base(owner)
     {
 
     }

+ 1 - 1
src/PixiEditor.AvaloniaUI/Views/Overlays/Handles/RectangleHandle.cs

@@ -8,7 +8,7 @@ namespace PixiEditor.AvaloniaUI.Views.Overlays.Handles;
 public class RectangleHandle : Handle
 {
     public double AnchorRadius { get; set; } = GetResource<double>("AnchorRadius");
-    public RectangleHandle(Control owner, VecD position) : base(owner, position)
+    public RectangleHandle(Control owner) : base(owner)
     {
     }
 

+ 6 - 2
src/PixiEditor.AvaloniaUI/Views/Overlays/Handles/TransformHandle.cs

@@ -9,18 +9,22 @@ namespace PixiEditor.AvaloniaUI.Views.Overlays.Handles;
 
 public class TransformHandle : Handle
 {
+    public double AnchorRadius { get; set; } = GetResource<double>("AnchorRadius");
     public IBrush GlyphBrush { get; set; } = GetBrush("HandleGlyphBrush");
 
     private Geometry handleGeometry = GetHandleGeometry("MoveHandle");
 
-    public TransformHandle(Control owner, VecD position) : base(owner, position)
+    public TransformHandle(Control owner) : base(owner)
     {
         Cursor = new Cursor(StandardCursorType.SizeAll);
     }
 
     public override void Draw(DrawingContext context)
     {
-        context.DrawRectangle(HandleBrush, HandlePen, TransformHelper.ToHandleRect(Position, Size, ZoomboxScale));
+        double scaleMultiplier = (1.0 / ZoomboxScale);
+        double radius = AnchorRadius * scaleMultiplier;
+
+        context.DrawRectangle(HandleBrush, HandlePen, TransformHelper.ToHandleRect(Position, Size, ZoomboxScale), radius, radius);
         double crossSize = HandleRect.Size.X - 1;
 
         handleGeometry.Transform = new MatrixTransform(

+ 3 - 3
src/PixiEditor.AvaloniaUI/Views/Overlays/LineToolOverlay/LineToolOverlay.cs

@@ -66,17 +66,17 @@ internal class LineToolOverlay : Overlay
     {
         Cursor = new Cursor(StandardCursorType.Arrow);
 
-        startHandle = new AnchorHandle(this, LineStart);
+        startHandle = new AnchorHandle(this);
         startHandle.HandlePen = blackPen;
         startHandle.OnDrag += StartHandleOnDrag;
         AddHandle(startHandle);
 
-        endHandle = new AnchorHandle(this, LineEnd);
+        endHandle = new AnchorHandle(this);
         startHandle.HandlePen = blackPen;
         endHandle.OnDrag += EndHandleOnDrag;
         AddHandle(endHandle);
 
-        moveHandle = new TransformHandle(this, LineStart);
+        moveHandle = new TransformHandle(this);
         moveHandle.HandlePen = blackPen;
         moveHandle.OnDrag += MoveHandleOnDrag;
         AddHandle(moveHandle);

+ 66 - 44
src/PixiEditor.AvaloniaUI/Views/Overlays/TransformOverlay/TransformOverlay.cs

@@ -148,6 +148,7 @@ internal class TransformOverlay : Overlay
     private AnchorHandle rightHandle;
     private RectangleHandle centerHandle;
     private OriginAnchor originHandle;
+    private TransformHandle moveHandle;
 
     private Dictionary<Handle, Anchor> anchorMap = new();
     private List<Handle> snapPoints = new();
@@ -159,18 +160,19 @@ internal class TransformOverlay : Overlay
 
     public TransformOverlay()
     {
-        topLeftHandle = new AnchorHandle(this, VecD.Zero);
-        topRightHandle = new AnchorHandle(this, VecD.Zero);
-        bottomLeftHandle = new AnchorHandle(this, VecD.Zero);
-        bottomRightHandle = new AnchorHandle(this, VecD.Zero);
-        topHandle = new AnchorHandle(this, VecD.Zero);
-        bottomHandle = new AnchorHandle(this, VecD.Zero);
-        leftHandle = new AnchorHandle(this, VecD.Zero);
-        rightHandle = new AnchorHandle(this, VecD.Zero);
-        centerHandle = new RectangleHandle(this, VecD.Zero);
+        topLeftHandle = new AnchorHandle(this);
+        topRightHandle = new AnchorHandle(this);
+        bottomLeftHandle = new AnchorHandle(this);
+        bottomRightHandle = new AnchorHandle(this);
+        topHandle = new AnchorHandle(this);
+        bottomHandle = new AnchorHandle(this);
+        leftHandle = new AnchorHandle(this);
+        rightHandle = new AnchorHandle(this);
+        moveHandle = new(this);
+        centerHandle = new RectangleHandle(this);
         centerHandle.Size = rightHandle.Size;
 
-        originHandle = new(this, VecD.Zero)
+        originHandle = new(this)
         {
             HandlePen = blackFreqDashedPen, SecondaryHandlePen = whiteFreqDashedPen, HandleBrush = Brushes.Transparent
         };
@@ -185,6 +187,7 @@ internal class TransformOverlay : Overlay
         AddHandle(leftHandle);
         AddHandle(rightHandle);
         AddHandle(centerHandle);
+        AddHandle(moveHandle);
 
         anchorMap.Add(topLeftHandle, Anchor.TopLeft);
         anchorMap.Add(topRightHandle, Anchor.TopRight);
@@ -206,6 +209,9 @@ internal class TransformOverlay : Overlay
 
         originHandle.OnPress += OnAnchorHandlePressed;
         originHandle.OnRelease += OnAnchorHandleReleased;
+
+        moveHandle.OnPress += OnMoveHandlePressed;
+        moveHandle.OnRelease += OnMoveHandleReleased;
     }
 
     public override void Render(DrawingContext drawingContext)
@@ -236,14 +242,6 @@ internal class TransformOverlay : Overlay
         }
 
         context.DrawGeometry(Brushes.Transparent, null, geometry);
-        if (LockRotation)
-            return;
-
-        /*double ellipseSize = (TransformHelper.AnchorSize * anchorSizeMultiplierForRotation - 2) / (ZoomboxScale * 2);
-        foreach (var point in points)
-        {
-            context.DrawEllipse(Brushes.Transparent, null, point, ellipseSize, ellipseSize);
-        }*/
     }
 
     private void DrawOverlay
@@ -289,6 +287,7 @@ internal class TransformOverlay : Overlay
         leftHandle.Position = left;
         rightHandle.Position = right;
         originHandle.Position = InternalState.Origin;
+        moveHandle.Position = TransformHelper.GetHandlePos(Corners, ZoomboxScale, moveHandle.Size);
 
         topLeftHandle.Draw(context);
         topRightHandle.Draw(context);
@@ -299,6 +298,7 @@ internal class TransformOverlay : Overlay
         leftHandle.Draw(context);
         rightHandle.Draw(context);
         originHandle.Draw(context);
+        moveHandle.Draw(context);
 
         if (capturedAnchor == Anchor.Origin)
         {
@@ -329,6 +329,11 @@ internal class TransformOverlay : Overlay
         }
     }
 
+    private void OnMoveHandlePressed(Handle source, VecD position)
+    {
+        StartMoving(position);
+    }
+
     protected override void OnPointerPressed(PointerPressedEventArgs e)
     {
         base.OnPointerPressed(e);
@@ -337,12 +342,11 @@ internal class TransformOverlay : Overlay
 
         VecD pos = TransformHelper.ToVecD(e.GetPosition(this));
 
-        if (!CanRotate(pos) && Handles.All(x => !x.IsWithinHandle(x.Position, pos, ZoomboxScale)))
+        if(Handles.Any(x => x.IsWithinHandle(x.Position, pos, ZoomboxScale))) return;
+
+        if (!CanRotate(pos))
         {
-            isMoving = true;
-            mousePosOnStartMove = pos;
-            originOnStartMove = InternalState.Origin;
-            cornersOnStartMove = Corners;
+            StartMoving(pos);
         }
         else if (!LockRotation)
         {
@@ -405,6 +409,45 @@ internal class TransformOverlay : Overlay
         InvalidateVisual();
     }
 
+    protected override void OnPointerReleased(PointerReleasedEventArgs e)
+    {
+        base.OnPointerReleased(e);
+        if (e.InitialPressMouseButton != MouseButton.Left)
+            return;
+
+        if (isRotating)
+        {
+            isRotating = false;
+            e.Pointer.Capture(null);
+            Cursor = new Cursor(StandardCursorType.Arrow);
+            var pos = TransformHelper.ToVecD(e.GetPosition(this));
+            UpdateRotationCursor(pos);
+        }
+
+        StopMoving();
+    }
+
+    private void OnMoveHandleReleased(Handle obj)
+    {
+        StopMoving();
+    }
+
+    private void StopMoving()
+    {
+        isMoving = false;
+
+        if (ActionCompleted is not null && ActionCompleted.CanExecute(null))
+            ActionCompleted.Execute(null);
+    }
+
+    private void StartMoving(VecD position)
+    {
+        isMoving = true;
+        mousePosOnStartMove = position;
+        originOnStartMove = InternalState.Origin;
+        cornersOnStartMove = Corners;
+    }
+
     private void HandleTransform(VecD pos)
     {
         VecD delta = pos - mousePosOnStartMove;
@@ -566,27 +609,6 @@ internal class TransformOverlay : Overlay
         return null;
     }
 
-    protected override void OnPointerReleased(PointerReleasedEventArgs e)
-    {
-        base.OnPointerReleased(e);
-        if (e.InitialPressMouseButton != MouseButton.Left)
-            return;
-
-        if (isRotating)
-        {
-            isRotating = false;
-            e.Pointer.Capture(null);
-            Cursor = new Cursor(StandardCursorType.Arrow);
-            var pos = TransformHelper.ToVecD(e.GetPosition(this));
-            UpdateRotationCursor(pos);
-        }
-
-        isMoving = false;
-
-        if (ActionCompleted is not null && ActionCompleted.CanExecute(null))
-            ActionCompleted.Execute(null);
-    }
-
     private static void OnRequestedCorners(AvaloniaPropertyChangedEventArgs<ShapeCorners> args)
     {
         TransformOverlay overlay = (TransformOverlay)args.Sender;