Browse Source

Fix PasteImage not respecting selection, symmetry, lock transparency, etc.

Equbuxu 3 years ago
parent
commit
2ecc7d0b0a

+ 11 - 0
src/ChunkyImageLib/DataHolders/ShapeCorners.cs

@@ -19,6 +19,17 @@ public struct ShapeCorners
     public VecD TopRight { get; set; }
     public VecD BottomLeft { get; set; }
     public VecD BottomRight { get; set; }
+    public bool IsInverted
+    {
+        get
+        {
+            var top = TopLeft - TopRight;
+            var right = TopRight - BottomRight;
+            var bottom = BottomRight - BottomLeft;
+            var left = BottomLeft - TopLeft;
+            return Math.Sign(top.Cross(right)) + Math.Sign(right.Cross(bottom)) + Math.Sign(bottom.Cross(left)) + Math.Sign(left.Cross(top)) < 0;
+        }
+    }
     public bool IsLegal
     {
         get

+ 4 - 0
src/ChunkyImageLib/Operations/OperationHelper.cs

@@ -66,6 +66,8 @@ public static class OperationHelper
             (corners.BottomLeft - corners.TopRight).Length > chunkSize * 40 * 20 ||
             (corners.TopLeft - corners.BottomRight).Length > chunkSize * 40 * 20)
             return new HashSet<VecI>();
+        if (corners.IsInverted)
+            corners = corners with { BottomLeft = corners.TopRight, TopRight = corners.BottomLeft };
         List<VecI>[] lines = new List<VecI>[] {
             FindChunksAlongLine(corners.TopRight, corners.TopLeft, chunkSize),
             FindChunksAlongLine(corners.BottomRight, corners.TopRight, chunkSize),
@@ -81,6 +83,8 @@ public static class OperationHelper
             (corners.BottomLeft - corners.TopRight).Length > chunkSize * 40 * 20 ||
             (corners.TopLeft - corners.BottomRight).Length > chunkSize * 40 * 20)
             return new HashSet<VecI>();
+        if (corners.IsInverted)
+            corners = corners with { BottomLeft = corners.TopRight, TopRight = corners.BottomLeft };
         List<VecI>[] lines = new List<VecI>[] {
             FindChunksAlongLine(corners.TopLeft, corners.TopRight, chunkSize),
             FindChunksAlongLine(corners.TopRight, corners.BottomRight, chunkSize),

+ 2 - 9
src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawRectangle_UpdateableChange.cs

@@ -26,17 +26,10 @@ internal class DrawRectangle_UpdateableChange : UpdateableChange
     private HashSet<VecI> UpdateRectangle(Document target, ChunkyImage targetImage)
     {
         var oldAffectedChunks = targetImage.FindAffectedChunks();
-        targetImage.CancelChanges();
-        if (!target.Selection.IsEmptyAndInactive)
-            targetImage.AddRasterClip(target.Selection.SelectionImage);
         var targetMember = target.FindMemberOrThrow(memberGuid);
-        if (targetMember is Layer layer && layer.LockTransparency)
-            targetImage.EnableLockTransparency();
-        if (target.HorizontalSymmetryAxisEnabled)
-            targetImage.SetHorizontalAxisOfSymmetry(target.HorizontalSymmetryAxisY);
-        if (target.VerticalSymmetryAxisEnabled)
-            targetImage.SetVerticalAxisOfSymmetry(target.VerticalSymmetryAxisX);
 
+        targetImage.CancelChanges();
+        DrawingChangeHelper.ApplyClipsSymmetriesEtc(target, targetImage, memberGuid, drawOnMask);
         targetImage.EnqueueDrawRectangle(rect);
 
         var affectedChunks = targetImage.FindAffectedChunks();

+ 16 - 0
src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawingChangeHelper.cs

@@ -23,6 +23,22 @@ internal static class DrawingChangeHelper
         return ((Layer)member).LayerImage;
     }
 
+    public static void ApplyClipsSymmetriesEtc(Document target, ChunkyImage targetImage, Guid targetMemberGuid, bool drawOnMask)
+    {
+        if (!target.Selection.IsEmptyAndInactive)
+            targetImage.AddRasterClip(target.Selection.SelectionImage);
+
+        var targetMember = target.FindMemberOrThrow(targetMemberGuid);
+        if (targetMember is Layer layer && layer.LockTransparency && !drawOnMask)
+            targetImage.EnableLockTransparency();
+
+        if (target.HorizontalSymmetryAxisEnabled)
+            targetImage.SetHorizontalAxisOfSymmetry(target.HorizontalSymmetryAxisY);
+        if (target.VerticalSymmetryAxisEnabled)
+            targetImage.SetVerticalAxisOfSymmetry(target.VerticalSymmetryAxisX);
+    }
+
+
     public static IChangeInfo CreateChunkChangeInfo(Guid memberGuid, HashSet<VecI> affectedChunks, bool drawOnMask)
     {
         return drawOnMask switch

+ 4 - 3
src/PixiEditor.ChangeableDocument/Changes/Drawing/PasteImage_UpdateableChange.cs

@@ -27,11 +27,12 @@ internal class PasteImage_UpdateableChange : UpdateableChange
         corners = newCorners;
     }
 
-    private HashSet<VecI> DrawImage(ChunkyImage targetImage)
+    private HashSet<VecI> DrawImage(Document target, ChunkyImage targetImage)
     {
         var prevChunks = targetImage.FindAffectedChunks();
 
         targetImage.CancelChanges();
+        DrawingChangeHelper.ApplyClipsSymmetriesEtc(target, targetImage, memberGuid, drawOnMask);
         targetImage.EnqueueDrawImage(corners, imageToPaste, false);
         hasEnqueudImage = true;
 
@@ -43,7 +44,7 @@ internal class PasteImage_UpdateableChange : UpdateableChange
     public override IChangeInfo? Apply(Document target, out bool ignoreInUndo)
     {
         ChunkyImage targetImage = DrawingChangeHelper.GetTargetImage(target, memberGuid, drawOnMask);
-        var chunks = DrawImage(targetImage);
+        var chunks = DrawImage(target, targetImage);
         savedChunks?.Dispose();
         savedChunks = new(targetImage, targetImage.FindAffectedChunks());
         targetImage.CommitChanges();
@@ -55,7 +56,7 @@ internal class PasteImage_UpdateableChange : UpdateableChange
     public override IChangeInfo? ApplyTemporarily(Document target)
     {
         ChunkyImage targetImage = DrawingChangeHelper.GetTargetImage(target, memberGuid, drawOnMask);
-        return DrawingChangeHelper.CreateChunkChangeInfo(memberGuid, DrawImage(targetImage), drawOnMask);
+        return DrawingChangeHelper.CreateChunkChangeInfo(memberGuid, DrawImage(target, targetImage), drawOnMask);
     }
 
     public override IChangeInfo? Revert(Document target)