Browse Source

Fixed corner snapping again

flabbet 8 months ago
parent
commit
22387a3875

+ 11 - 17
src/PixiEditor/Views/Overlays/TransformOverlay/TransformOverlay.cs

@@ -717,21 +717,15 @@ internal class TransformOverlay : Overlay
 
 
             ShapeCorners? newCorners = TransformUpdateHelper.UpdateShapeFromCorner
             ShapeCorners? newCorners = TransformUpdateHelper.UpdateShapeFromCorner
             ((Anchor)capturedAnchor, CornerFreedom, InternalState.ProportionalAngle1,
             ((Anchor)capturedAnchor, CornerFreedom, InternalState.ProportionalAngle1,
-                InternalState.ProportionalAngle2, cornersOnStartAnchorDrag, targetPos);
-
-            var snapped =
-                TrySnapAnchorAlongLine(TransformHelper.GetAnchorPosition(newCorners.Value, (Anchor)capturedAnchor),
-                    originOnStartAnchorDrag);
-
-            HighlightSnappedAxis(snapped.SnapAxisXName, snapped.SnapAxisYName);
+                InternalState.ProportionalAngle2, cornersOnStartAnchorDrag, targetPos, SnappingController, out string snapX, out string snapY);
+            HighlightSnappedAxis(snapX, snapY);
 
 
             if (newCorners is not null)
             if (newCorners is not null)
             {
             {
                 bool shouldAlign =
                 bool shouldAlign =
                     (CornerFreedom is TransformCornerFreedom.ScaleProportionally or TransformCornerFreedom.Scale) &&
                     (CornerFreedom is TransformCornerFreedom.ScaleProportionally or TransformCornerFreedom.Scale) &&
                     Corners.IsAlignedToPixels;
                     Corners.IsAlignedToPixels;
-
-                newCorners = SnapAnchorInCorners(capturedAnchor.Value, newCorners.Value, snapped.Delta);
+                
                 newCorners = shouldAlign
                 newCorners = shouldAlign
                     ? TransformHelper.AlignToPixels((ShapeCorners)newCorners)
                     ? TransformHelper.AlignToPixels((ShapeCorners)newCorners)
                     : (ShapeCorners)newCorners;
                     : (ShapeCorners)newCorners;
@@ -847,26 +841,26 @@ internal class TransformOverlay : Overlay
         if (anchor == Anchor.TopLeft)
         if (anchor == Anchor.TopLeft)
         {
         {
             topLeftPos = targetAnchorPos;
             topLeftPos = targetAnchorPos;
-            topRightPos = new VecD(topRightPos.X, targetAnchorPos.Y);
-            bottomLeftPos = new VecD(targetAnchorPos.X, bottomLeftPos.Y);
+            topRightPos = new VecD(topRightPos.X, topRightPos.Y + delta.Y);
+            bottomLeftPos = new VecD(bottomLeftPos.X + delta.X, bottomLeftPos.Y);
         }
         }
         else if (anchor == Anchor.TopRight)
         else if (anchor == Anchor.TopRight)
         {
         {
             topRightPos = targetAnchorPos;
             topRightPos = targetAnchorPos;
-            topLeftPos = new VecD(topLeftPos.X, targetAnchorPos.Y);
-            bottomRightPos = new VecD(targetAnchorPos.X, bottomRightPos.Y);
+            topLeftPos = new VecD(topLeftPos.X, topLeftPos.Y + delta.Y);
+            bottomRightPos = new VecD(bottomRightPos.X + delta.X, bottomRightPos.Y);
         }
         }
         else if (anchor == Anchor.BottomLeft)
         else if (anchor == Anchor.BottomLeft)
         {
         {
             bottomLeftPos = targetAnchorPos;
             bottomLeftPos = targetAnchorPos;
-            topLeftPos = new VecD(targetAnchorPos.X, topLeftPos.Y);
-            bottomRightPos = new VecD(bottomRightPos.X, targetAnchorPos.Y);
+            topLeftPos = new VecD(topLeftPos.X + delta.X, topLeftPos.Y);
+            bottomRightPos = new VecD(bottomRightPos.X, bottomRightPos.Y + delta.Y);
         }
         }
         else if (anchor == Anchor.BottomRight)
         else if (anchor == Anchor.BottomRight)
         {
         {
             bottomRightPos = targetAnchorPos;
             bottomRightPos = targetAnchorPos;
-            topRightPos = new VecD(targetAnchorPos.X, topRightPos.Y);
-            bottomLeftPos = new VecD(bottomLeftPos.X, targetAnchorPos.Y);
+            topRightPos = new VecD(topRightPos.X + delta.X, topRightPos.Y);
+            bottomLeftPos = new VecD(bottomLeftPos.X, bottomLeftPos.Y + delta.Y);
         }
         }
 
 
         return new ShapeCorners()
         return new ShapeCorners()

+ 55 - 13
src/PixiEditor/Views/Overlays/TransformOverlay/TransformUpdateHelper.cs

@@ -1,20 +1,27 @@
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.DataHolders;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Numerics;
 using Drawie.Numerics;
+using PixiEditor.Models.Controllers.InputDevice;
 
 
 namespace PixiEditor.Views.Overlays.TransformOverlay;
 namespace PixiEditor.Views.Overlays.TransformOverlay;
 #nullable enable
 #nullable enable
 internal static class TransformUpdateHelper
 internal static class TransformUpdateHelper
 {
 {
     private const double epsilon = 0.00001;
     private const double epsilon = 0.00001;
+
     public static ShapeCorners? UpdateShapeFromCorner
     public static ShapeCorners? UpdateShapeFromCorner
-        (Anchor targetCorner, TransformCornerFreedom freedom, double propAngle1, double propAngle2, ShapeCorners corners, VecD desiredPos)
+    (Anchor targetCorner, TransformCornerFreedom freedom, double propAngle1, double propAngle2, ShapeCorners corners,
+        VecD desiredPos,
+        SnappingController? snappingController, out string snapX, out string snapY)
     {
     {
         if (!TransformHelper.IsCorner(targetCorner))
         if (!TransformHelper.IsCorner(targetCorner))
             throw new ArgumentException($"{targetCorner} is not a corner");
             throw new ArgumentException($"{targetCorner} is not a corner");
 
 
         if (freedom == TransformCornerFreedom.Locked)
         if (freedom == TransformCornerFreedom.Locked)
+        {
+            snapX = snapY = "";
             return corners;
             return corners;
+        }
 
 
         if (freedom is TransformCornerFreedom.ScaleProportionally or TransformCornerFreedom.Scale)
         if (freedom is TransformCornerFreedom.ScaleProportionally or TransformCornerFreedom.Scale)
         {
         {
@@ -23,15 +30,36 @@ internal static class TransformUpdateHelper
             Anchor opposite = TransformHelper.GetOpposite(targetCorner);
             Anchor opposite = TransformHelper.GetOpposite(targetCorner);
             VecD oppositePos = TransformHelper.GetAnchorPosition(corners, opposite);
             VecD oppositePos = TransformHelper.GetAnchorPosition(corners, opposite);
 
 
+            snapX = snapY = "";
+
             // constrain desired pos to a "propotional" diagonal line if needed
             // constrain desired pos to a "propotional" diagonal line if needed
             if (freedom == TransformCornerFreedom.ScaleProportionally && corners.IsRect)
             if (freedom == TransformCornerFreedom.ScaleProportionally && corners.IsRect)
             {
             {
                 double correctAngle = targetCorner is Anchor.TopLeft or Anchor.BottomRight ? propAngle1 : propAngle2;
                 double correctAngle = targetCorner is Anchor.TopLeft or Anchor.BottomRight ? propAngle1 : propAngle2;
-                desiredPos = desiredPos.ProjectOntoLine(oppositePos, oppositePos + VecD.FromAngleAndLength(correctAngle, 1));
+                VecD direction = VecD.FromAngleAndLength(correctAngle, 1);
+                desiredPos = desiredPos.ProjectOntoLine(oppositePos, oppositePos + direction);
+
+                if (snappingController is not null)
+                {
+                    desiredPos = snappingController.GetSnapPoint(desiredPos, direction, out snapX, out snapY);
+                }
             }
             }
             else if (freedom == TransformCornerFreedom.ScaleProportionally)
             else if (freedom == TransformCornerFreedom.ScaleProportionally)
             {
             {
                 desiredPos = desiredPos.ProjectOntoLine(oppositePos, targetPos);
                 desiredPos = desiredPos.ProjectOntoLine(oppositePos, targetPos);
+                VecD direction = (targetPos - oppositePos);
+                
+                if (snappingController is not null)
+                {
+                    desiredPos = snappingController.GetSnapPoint(desiredPos, direction, out snapX, out snapY);
+                }
+            }
+            else
+            {
+                if (snappingController is not null)
+                {
+                    desiredPos = snappingController.GetSnapPoint(desiredPos, out snapX, out snapY);
+                } 
             }
             }
 
 
             // find neighboring corners
             // find neighboring corners
@@ -59,8 +87,10 @@ internal static class TransformUpdateHelper
             }
             }
             else
             else
             {
             {
-                VecD? newLeftPos = TransformHelper.TwoLineIntersection(VecD.Zero, leftNeighTrans, targetTrans + delta, leftNeighTrans + delta);
-                VecD? newRightPos = TransformHelper.TwoLineIntersection(VecD.Zero, rightNeighTrans, targetTrans + delta, rightNeighTrans + delta);
+                VecD? newLeftPos = TransformHelper.TwoLineIntersection(VecD.Zero, leftNeighTrans, targetTrans + delta,
+                    leftNeighTrans + delta);
+                VecD? newRightPos = TransformHelper.TwoLineIntersection(VecD.Zero, rightNeighTrans, targetTrans + delta,
+                    rightNeighTrans + delta);
                 if (newLeftPos is null || newRightPos is null)
                 if (newLeftPos is null || newRightPos is null)
                     return null;
                     return null;
                 leftNeighDelta = newLeftPos.Value - leftNeighTrans;
                 leftNeighDelta = newLeftPos.Value - leftNeighTrans;
@@ -83,7 +113,7 @@ internal static class TransformUpdateHelper
             {
             {
                 rightNeighDelta = TransferZeros(SwapAxes(leftNeighTrans), delta);
                 rightNeighDelta = TransferZeros(SwapAxes(leftNeighTrans), delta);
             }
             }
-            
+
             // move the corners, while reapplying the transform rotation
             // move the corners, while reapplying the transform rotation
             corners = TransformHelper.UpdateCorner(corners, targetCorner,
             corners = TransformHelper.UpdateCorner(corners, targetCorner,
                 (targetTrans + delta).Rotate(angle) + oppositePos);
                 (targetTrans + delta).Rotate(angle) + oppositePos);
@@ -100,9 +130,11 @@ internal static class TransformUpdateHelper
 
 
         if (freedom == TransformCornerFreedom.Free)
         if (freedom == TransformCornerFreedom.Free)
         {
         {
+            snapX = snapY = "";
             ShapeCorners newCorners = TransformHelper.UpdateCorner(corners, targetCorner, desiredPos);
             ShapeCorners newCorners = TransformHelper.UpdateCorner(corners, targetCorner, desiredPos);
             return newCorners.IsLegal ? newCorners : null;
             return newCorners.IsLegal ? newCorners : null;
         }
         }
+
         throw new ArgumentException($"Freedom degree {freedom} is not supported");
         throw new ArgumentException($"Freedom degree {freedom} is not supported");
     }
     }
 
 
@@ -118,7 +150,8 @@ internal static class TransformUpdateHelper
     }
     }
 
 
     public static ShapeCorners? UpdateShapeFromSide
     public static ShapeCorners? UpdateShapeFromSide
-        (Anchor targetSide, TransformSideFreedom freedom, double propAngle1, double propAngle2, ShapeCorners corners, VecD desiredPos)
+    (Anchor targetSide, TransformSideFreedom freedom, double propAngle1, double propAngle2, ShapeCorners corners,
+        VecD desiredPos)
     {
     {
         if (!TransformHelper.IsSide(targetSide))
         if (!TransformHelper.IsSide(targetSide))
             throw new ArgumentException($"{targetSide} is not a side");
             throw new ArgumentException($"{targetSide} is not a side");
@@ -154,12 +187,18 @@ internal static class TransformUpdateHelper
                 var leftOppCornPos = TransformHelper.GetAnchorPosition(corners, leftOppCorn);
                 var leftOppCornPos = TransformHelper.GetAnchorPosition(corners, leftOppCorn);
                 var rightOppCornPos = TransformHelper.GetAnchorPosition(corners, rightOppCorn);
                 var rightOppCornPos = TransformHelper.GetAnchorPosition(corners, rightOppCorn);
 
 
-                var (leftAngle, rightAngle) = leftCorn is Anchor.TopLeft or Anchor.BottomRight ? (propAngle1, propAngle2) : (propAngle2, propAngle1);
+                var (leftAngle, rightAngle) = leftCorn is Anchor.TopLeft or Anchor.BottomRight
+                    ? (propAngle1, propAngle2)
+                    : (propAngle2, propAngle1);
 
 
-                var updLeftCorn = TransformHelper.TwoLineIntersection(leftCornPos + delta, rightCornPos + delta, center, center + VecD.FromAngleAndLength(leftAngle, 1));
-                var updRightCorn = TransformHelper.TwoLineIntersection(leftCornPos + delta, rightCornPos + delta, center, center + VecD.FromAngleAndLength(rightAngle, 1));
-                var updLeftOppCorn = TransformHelper.TwoLineIntersection(leftOppCornPos, rightOppCornPos, center, center + VecD.FromAngleAndLength(rightAngle, 1));
-                var updRightOppCorn = TransformHelper.TwoLineIntersection(leftOppCornPos, rightOppCornPos, center, center + VecD.FromAngleAndLength(leftAngle, 1));
+                var updLeftCorn = TransformHelper.TwoLineIntersection(leftCornPos + delta, rightCornPos + delta, center,
+                    center + VecD.FromAngleAndLength(leftAngle, 1));
+                var updRightCorn = TransformHelper.TwoLineIntersection(leftCornPos + delta, rightCornPos + delta,
+                    center, center + VecD.FromAngleAndLength(rightAngle, 1));
+                var updLeftOppCorn = TransformHelper.TwoLineIntersection(leftOppCornPos, rightOppCornPos, center,
+                    center + VecD.FromAngleAndLength(rightAngle, 1));
+                var updRightOppCorn = TransformHelper.TwoLineIntersection(leftOppCornPos, rightOppCornPos, center,
+                    center + VecD.FromAngleAndLength(leftAngle, 1));
 
 
                 if (updLeftCorn is null || updRightCorn is null || updLeftOppCorn is null || updRightOppCorn is null)
                 if (updLeftCorn is null || updRightCorn is null || updLeftOppCorn is null || updRightOppCorn is null)
                     goto fallback;
                     goto fallback;
@@ -171,7 +210,8 @@ internal static class TransformUpdateHelper
 
 
                 return corners;
                 return corners;
             }
             }
-fallback:
+
+            fallback:
             corners.TopLeft = (corners.TopLeft - oppositePos) * scalingFactor + oppositePos;
             corners.TopLeft = (corners.TopLeft - oppositePos) * scalingFactor + oppositePos;
             corners.BottomRight = (corners.BottomRight - oppositePos) * scalingFactor + oppositePos;
             corners.BottomRight = (corners.BottomRight - oppositePos) * scalingFactor + oppositePos;
             corners.TopRight = (corners.TopRight - oppositePos) * scalingFactor + oppositePos;
             corners.TopRight = (corners.TopRight - oppositePos) * scalingFactor + oppositePos;
@@ -207,7 +247,8 @@ fallback:
                 if ((targetPos - oppPos).TaxicabLength > epsilon)
                 if ((targetPos - oppPos).TaxicabLength > epsilon)
                     desiredPos = desiredPos.ProjectOntoLine(targetPos, oppPos);
                     desiredPos = desiredPos.ProjectOntoLine(targetPos, oppPos);
                 else
                 else
-                    desiredPos = desiredPos.ProjectOntoLine(targetPos, (leftCornerPos - targetPos).Rotate(Math.PI / 2) + targetPos);
+                    desiredPos = desiredPos.ProjectOntoLine(targetPos,
+                        (leftCornerPos - targetPos).Rotate(Math.PI / 2) + targetPos);
             }
             }
 
 
             var delta = desiredPos - targetPos;
             var delta = desiredPos - targetPos;
@@ -216,6 +257,7 @@ fallback:
 
 
             return newCorners.IsLegal ? newCorners : null;
             return newCorners.IsLegal ? newCorners : null;
         }
         }
+
         throw new ArgumentException($"Freedom degree {freedom} is not supported");
         throw new ArgumentException($"Freedom degree {freedom} is not supported");
     }
     }