Browse Source

Added merge vectors

flabbet 8 months ago
parent
commit
e6cf04c699

+ 1 - 1
src/Drawie

@@ -1 +1 @@
-Subproject commit 53075856f14518af3f0b59910a9b9d8339368347
+Subproject commit fb6db35ce1214ea16d0dcc0391e6a422ccb4bf0a

+ 9 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/EllipseVectorData.cs

@@ -3,6 +3,7 @@ using Drawie.Backend.Core.ColorsImpl;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Backend.Core.Vector;
 using Drawie.Numerics;
 using Drawie.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
@@ -93,4 +94,12 @@ public class EllipseVectorData : ShapeVectorData, IReadOnlyEllipseData
             TransformationMatrix = TransformationMatrix
             TransformationMatrix = TransformationMatrix
         };
         };
     }
     }
+
+    public override VectorPath ToPath()
+    {
+        // TODO: Apply transformation matrix
+        VectorPath path = new VectorPath();
+        path.AddOval(RectD.FromCenterAndSize(Center, Radius * 2));
+        return path;
+    }
 }
 }

+ 11 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/LineVectorData.cs

@@ -4,6 +4,7 @@ using Drawie.Backend.Core.ColorsImpl;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Backend.Core.Vector;
 using Drawie.Numerics;
 using Drawie.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
@@ -107,4 +108,14 @@ public class LineVectorData(VecD startPos, VecD pos) : ShapeVectorData, IReadOnl
             StrokeColor = StrokeColor, StrokeWidth = StrokeWidth, TransformationMatrix = TransformationMatrix
             StrokeColor = StrokeColor, StrokeWidth = StrokeWidth, TransformationMatrix = TransformationMatrix
         };
         };
     }
     }
+
+    public override VectorPath ToPath()
+    {
+        // TODO: Apply transformation matrix
+        
+        VectorPath path = new VectorPath();
+        path.MoveTo((VecF)Start);
+        path.LineTo((VecF)End);
+        return path;
+    }
 }
 }

+ 5 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/PathVectorData.cs

@@ -91,4 +91,9 @@ public class PathVectorData : ShapeVectorData, IReadOnlyPathData
             TransformationMatrix = TransformationMatrix
             TransformationMatrix = TransformationMatrix
         };
         };
     }
     }
+
+    public override VectorPath ToPath()
+    {
+        return new VectorPath(Path);
+    }
 }
 }

+ 13 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/PointsVectorData.cs

@@ -1,6 +1,7 @@
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Backend.Core.Vector;
 using Drawie.Numerics;
 using Drawie.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
@@ -77,4 +78,16 @@ public class PointsVectorData : ShapeVectorData
             StrokeColor = StrokeColor, FillColor = FillColor, StrokeWidth = StrokeWidth
             StrokeColor = StrokeColor, FillColor = FillColor, StrokeWidth = StrokeWidth
         };
         };
     }
     }
+
+    public override VectorPath ToPath()
+    {
+        VectorPath path = new VectorPath();
+        
+        foreach (VecD point in Points)
+        {
+            path.LineTo((VecF)point);
+        }
+        
+        return path;
+    }
 }
 }

+ 8 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/RectangleVectorData.cs

@@ -3,6 +3,7 @@ using Drawie.Backend.Core;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Backend.Core.Vector;
 using Drawie.Numerics;
 using Drawie.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
@@ -99,4 +100,11 @@ public class RectangleVectorData : ShapeVectorData, IReadOnlyRectangleData
             TransformationMatrix = TransformationMatrix
             TransformationMatrix = TransformationMatrix
         };
         };
     }
     }
+
+    public override VectorPath ToPath()
+    {
+        VectorPath path = new VectorPath();
+        path.AddRect(RectD.FromCenterAndSize(Center, Size));
+        return path;
+    }
 }
 }

+ 3 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/ShapeVectorData.cs

@@ -4,6 +4,7 @@ using Drawie.Backend.Core.ColorsImpl;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Backend.Core.Vector;
 using Drawie.Numerics;
 using Drawie.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
@@ -41,4 +42,6 @@ public abstract class ShapeVectorData : ICacheable, ICloneable, IReadOnlyShapeVe
     {
     {
         return CalculateHash();
         return CalculateHash();
     }
     }
+
+    public abstract VectorPath ToPath();
 }
 }

+ 131 - 25
src/PixiEditor.ChangeableDocument/Changes/Drawing/CombineStructureMembersOnto_Change.cs

@@ -5,9 +5,12 @@ using PixiEditor.ChangeableDocument.Rendering;
 using Drawie.Backend.Core;
 using Drawie.Backend.Core;
 using Drawie.Backend.Core.Bridge;
 using Drawie.Backend.Core.Bridge;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Numerics;
+using Drawie.Backend.Core.Vector;
 using Drawie.Numerics;
 using Drawie.Numerics;
 using PixiEditor.ChangeableDocument.Changeables.Animations;
 using PixiEditor.ChangeableDocument.Changeables.Animations;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 using PixiEditor.ChangeableDocument.ChangeInfos.Animation;
 using PixiEditor.ChangeableDocument.ChangeInfos.Animation;
+using PixiEditor.ChangeableDocument.ChangeInfos.Vectors;
 
 
 namespace PixiEditor.ChangeableDocument.Changes.Drawing;
 namespace PixiEditor.ChangeableDocument.Changes.Drawing;
 
 
@@ -20,6 +23,8 @@ internal class CombineStructureMembersOnto_Change : Change
     private Guid targetLayerGuid;
     private Guid targetLayerGuid;
     private Dictionary<int, CommittedChunkStorage> originalChunks = new();
     private Dictionary<int, CommittedChunkStorage> originalChunks = new();
     
     
+    private Dictionary<int, VectorPath> originalPaths = new();
+
 
 
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
     public CombineStructureMembersOnto_Change(HashSet<Guid> membersToMerge, Guid targetLayer)
     public CombineStructureMembersOnto_Change(HashSet<Guid> membersToMerge, Guid targetLayer)
@@ -69,7 +74,6 @@ internal class CombineStructureMembersOnto_Change : Change
         List<IChangeInfo> changes = new();
         List<IChangeInfo> changes = new();
         var targetLayer = target.FindMemberOrThrow<LayerNode>(targetLayerGuid);
         var targetLayer = target.FindMemberOrThrow<LayerNode>(targetLayerGuid);
 
 
-        // TODO: add merging similar layers (vector -> vector)
         int maxFrame = GetMaxFrame(target, targetLayer);
         int maxFrame = GetMaxFrame(target, targetLayer);
 
 
         for (int frame = 0; frame < maxFrame || frame == 0; frame++)
         for (int frame = 0; frame < maxFrame || frame == 0; frame++)
@@ -82,6 +86,26 @@ internal class CombineStructureMembersOnto_Change : Change
         return changes;
         return changes;
     }
     }
 
 
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
+    {
+        var toDrawOn = target.FindMemberOrThrow<LayerNode>(targetLayerGuid);
+
+        List<IChangeInfo> changes = new();
+
+        int maxFrame = GetMaxFrame(target, toDrawOn);
+
+        for (int frame = 0; frame < maxFrame || frame == 0; frame++)
+        {
+            changes.Add(RevertFrame(toDrawOn, frame));
+        }
+
+        target.AnimationData.RemoveKeyFrame(targetLayerGuid);
+        originalChunks.Clear();
+        changes.Add(new DeleteKeyFrame_ChangeInfo(targetLayerGuid));
+
+        return changes;
+    }
+
     private List<IChangeInfo> ApplyToFrame(Document target, LayerNode targetLayer, int frame)
     private List<IChangeInfo> ApplyToFrame(Document target, LayerNode targetLayer, int frame)
     {
     {
         var chunksToCombine = new HashSet<VecI>();
         var chunksToCombine = new HashSet<VecI>();
@@ -94,7 +118,7 @@ internal class CombineStructureMembersOnto_Change : Change
             var layer = target.FindMemberOrThrow<LayerNode>(guid);
             var layer = target.FindMemberOrThrow<LayerNode>(guid);
 
 
             AddMissingKeyFrame(targetLayer, frame, layer, changes, target);
             AddMissingKeyFrame(targetLayer, frame, layer, changes, target);
-            
+
             if (layer is not IRasterizable or ImageLayerNode)
             if (layer is not IRasterizable or ImageLayerNode)
                 continue;
                 continue;
 
 
@@ -109,6 +133,75 @@ internal class CombineStructureMembersOnto_Change : Change
             }
             }
         }
         }
 
 
+        bool allVector = layersToCombine.All(x => target.FindMember(x) is VectorLayerNode);
+
+        AffectedArea affArea = new();
+
+        // TODO: add custom layer merge
+        if (!allVector)
+        {
+            affArea = RasterMerge(target, targetLayer, frame);
+        }
+        else
+        {
+            affArea = VectorMerge(target, targetLayer, frame, layersToCombine);
+        }
+
+        changes.Add(new LayerImageArea_ChangeInfo(targetLayerGuid, affArea));
+        return changes;
+    }
+
+    private AffectedArea VectorMerge(Document target, LayerNode targetLayer, int frame, HashSet<Guid> toCombine)
+    {
+        if (targetLayer is not VectorLayerNode vectorLayer)
+            throw new InvalidOperationException("Target layer is not a vector layer");
+
+        ShapeVectorData targetData = vectorLayer.ShapeData ?? null;
+        VectorPath? targetPath = targetData?.ToPath();
+
+        foreach (var guid in toCombine)
+        {
+            if (target.FindMember(guid) is not VectorLayerNode vectorNode)
+                continue;
+
+            if (vectorNode.ShapeData == null)
+                continue;
+
+            VectorPath path = vectorNode.ShapeData.ToPath();
+
+            if (targetData == null)
+            {
+                targetData = vectorNode.ShapeData;
+                targetPath = path;
+                
+                if(originalPaths.ContainsKey(frame))
+                    originalPaths[frame].Dispose();
+                
+                originalPaths[frame] = new VectorPath(path);
+            }
+            else
+            {
+                targetPath.AddPath(path, AddPathMode.Append);
+                path.Dispose();
+            }
+        }
+
+        targetPath.FillType = PathFillType.EvenOdd;
+
+        var pathData = new PathVectorData(targetPath)
+        {
+            StrokeWidth = targetData.StrokeWidth,
+            StrokeColor = targetData.StrokeColor,
+            FillColor = targetData.FillColor
+        };
+
+        vectorLayer.ShapeData = pathData;
+
+        return new AffectedArea(new HashSet<VecI>());
+    }
+
+    private AffectedArea RasterMerge(Document target, LayerNode targetLayer, int frame)
+    {
         var toDrawOnImage = ((ImageLayerNode)targetLayer).GetLayerImageAtFrame(frame);
         var toDrawOnImage = ((ImageLayerNode)targetLayer).GetLayerImageAtFrame(frame);
         toDrawOnImage.EnqueueClear();
         toDrawOnImage.EnqueueClear();
 
 
@@ -136,7 +229,7 @@ internal class CombineStructureMembersOnto_Change : Change
                         }
                         }
                     }
                     }
                 }
                 }
-                
+
                 renderer.RenderLayers(tempTexture.DrawingSurface, layersToRender, frame, ChunkResolution.Full);
                 renderer.RenderLayers(tempTexture.DrawingSurface, layersToRender, frame, ChunkResolution.Full);
             }
             }
 
 
@@ -148,11 +241,9 @@ internal class CombineStructureMembersOnto_Change : Change
 
 
             tempTexture.Dispose();
             tempTexture.Dispose();
         });
         });
-
-        changes.Add(new LayerImageArea_ChangeInfo(targetLayerGuid, affArea));
-        return changes;
+        return affArea;
     }
     }
-    
+
     private HashSet<Guid> OrderLayers(HashSet<Guid> layersToCombine, Document document)
     private HashSet<Guid> OrderLayers(HashSet<Guid> layersToCombine, Document document)
     {
     {
         HashSet<Guid> ordered = new();
         HashSet<Guid> ordered = new();
@@ -182,9 +273,9 @@ internal class CombineStructureMembersOnto_Change : Change
             return;
             return;
 
 
         var clonedData = keyFrameData.Clone(true);
         var clonedData = keyFrameData.Clone(true);
-        
+
         targetLayer.AddFrame(keyFrameData.KeyFrameGuid, clonedData);
         targetLayer.AddFrame(keyFrameData.KeyFrameGuid, clonedData);
-        
+
         changes.Add(new CreateRasterKeyFrame_ChangeInfo(targetLayerGuid, frame, clonedData.KeyFrameGuid, true));
         changes.Add(new CreateRasterKeyFrame_ChangeInfo(targetLayerGuid, frame, clonedData.KeyFrameGuid, true));
         changes.Add(new KeyFrameLength_ChangeInfo(targetLayerGuid, clonedData.StartFrame, clonedData.Duration));
         changes.Add(new KeyFrameLength_ChangeInfo(targetLayerGuid, clonedData.StartFrame, clonedData.Duration));
 
 
@@ -193,6 +284,9 @@ internal class CombineStructureMembersOnto_Change : Change
 
 
     private int GetMaxFrame(Document target, LayerNode targetLayer)
     private int GetMaxFrame(Document target, LayerNode targetLayer)
     {
     {
+        if (targetLayer.KeyFrames.Count == 0)
+            return 0;
+
         int maxFrame = targetLayer.KeyFrames.Max(x => x.StartFrame + x.Duration);
         int maxFrame = targetLayer.KeyFrames.Max(x => x.StartFrame + x.Duration);
         foreach (var toMerge in membersToMerge)
         foreach (var toMerge in membersToMerge)
         {
         {
@@ -224,27 +318,21 @@ internal class CombineStructureMembersOnto_Change : Change
         }
         }
     }
     }
 
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
+    private IChangeInfo RevertFrame(LayerNode targetLayer, int frame)
     {
     {
-        var toDrawOn = target.FindMemberOrThrow<ImageLayerNode>(targetLayerGuid);
-
-        List<IChangeInfo> changes = new();
-
-        int maxFrame = GetMaxFrame(target, toDrawOn);
-
-        for (int frame = 0; frame < maxFrame || frame == 0; frame++)
+        if (targetLayer is ImageLayerNode imageLayerNode)
         {
         {
-            changes.Add(RevertFrame(toDrawOn, frame));
+            return RasterRevert(imageLayerNode, frame);
+        }
+        else if (targetLayer is VectorLayerNode vectorLayerNode)
+        {
+            return VectorRevert(vectorLayerNode, frame);
         }
         }
         
         
-        target.AnimationData.RemoveKeyFrame(targetLayerGuid);
-        originalChunks.Clear();
-        changes.Add(new DeleteKeyFrame_ChangeInfo(targetLayerGuid));
-
-        return changes;
+        throw new InvalidOperationException("Layer type not supported");
     }
     }
 
 
-    private IChangeInfo RevertFrame(ImageLayerNode targetLayer, int frame)
+    private IChangeInfo RasterRevert(ImageLayerNode targetLayer, int frame)
     {
     {
         var toDrawOnImage = targetLayer.GetLayerImageAtFrame(frame);
         var toDrawOnImage = targetLayer.GetLayerImageAtFrame(frame);
         toDrawOnImage.EnqueueClear();
         toDrawOnImage.EnqueueClear();
@@ -255,10 +343,19 @@ internal class CombineStructureMembersOnto_Change : Change
             DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(
             DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(
                 targetLayer.GetLayerImageAtFrame(frame),
                 targetLayer.GetLayerImageAtFrame(frame),
                 ref storedChunks);
                 ref storedChunks);
-        
+
         toDrawOnImage.CommitChanges();
         toDrawOnImage.CommitChanges();
         return new LayerImageArea_ChangeInfo(targetLayerGuid, affectedArea);
         return new LayerImageArea_ChangeInfo(targetLayerGuid, affectedArea);
     }
     }
+    
+    private IChangeInfo VectorRevert(VectorLayerNode targetLayer, int frame)
+    {
+        if (!originalPaths.TryGetValue(frame, out var path))
+            throw new InvalidOperationException("Original path not found");
+
+        targetLayer.ShapeData = new PathVectorData(path);
+        return new VectorShape_ChangeInfo(targetLayer.Id, new AffectedArea(new HashSet<VecI>()));
+    }
 
 
     public override void Dispose()
     public override void Dispose()
     {
     {
@@ -266,5 +363,14 @@ internal class CombineStructureMembersOnto_Change : Change
         {
         {
             originalChunk.Value.Dispose();
             originalChunk.Value.Dispose();
         }
         }
+        
+        originalChunks.Clear();
+        
+        foreach (var originalPath in originalPaths)
+        {
+            originalPath.Value.Dispose();
+        }
+        
+        originalPaths.Clear();
     }
     }
 }
 }

+ 2 - 2
src/PixiEditor.ChangeableDocument/Changes/Drawing/FloodFill/FloodFillHelper.cs

@@ -201,7 +201,7 @@ public static class FloodFillHelper
         Surface surface = new Surface(document.Size);
         Surface surface = new Surface(document.Size);
 
 
         var inverse = new VectorPath();
         var inverse = new VectorPath();
-        inverse.AddRect(new RectI(new(0, 0), document.Size));
+        inverse.AddRect((RectD)new RectI(new(0, 0), document.Size));
 
 
         surface.DrawingSurface.Canvas.Clear(new Color(255, 255, 255, 255));
         surface.DrawingSurface.Canvas.Clear(new Color(255, 255, 255, 255));
         surface.DrawingSurface.Canvas.Flush();
         surface.DrawingSurface.Canvas.Flush();
@@ -220,7 +220,7 @@ public static class FloodFillHelper
         if (selection is null)
         if (selection is null)
         {
         {
             selection = new VectorPath();
             selection = new VectorPath();
-            selection.AddRect(globalBounds);
+            selection.AddRect((RectD)globalBounds);
         }
         }
 
 
         RectI localBounds = globalBounds.Offset(-chunkPos * chunkSize).Intersect(new(0, 0, chunkSize, chunkSize));
         RectI localBounds = globalBounds.Offset(-chunkPos * chunkSize).Intersect(new(0, 0, chunkSize, chunkSize));

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Drawing/TransformSelected_UpdateableChange.cs

@@ -147,7 +147,7 @@ internal class TransformSelected_UpdateableChange : InterruptableUpdateableChang
         {
         {
             RectD tightBounds = layer.GetTightBounds(frame).GetValueOrDefault();
             RectD tightBounds = layer.GetTightBounds(frame).GetValueOrDefault();
             pathToExtract = new VectorPath();
             pathToExtract = new VectorPath();
-            pathToExtract.AddRect((RectI)tightBounds);
+            pathToExtract.AddRect((RectD)(RectI)tightBounds);
         }
         }
 
 
         member.OriginalPath = pathToExtract;
         member.OriginalPath = pathToExtract;

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Selection/SelectEllipse_UpdateableChange.cs

@@ -29,7 +29,7 @@ internal class SelectEllipse_UpdateableChange : UpdateableChange
     {
     {
         originalPath = new VectorPath(target.Selection.SelectionPath);
         originalPath = new VectorPath(target.Selection.SelectionPath);
         documentConstraint = new VectorPath();
         documentConstraint = new VectorPath();
-        documentConstraint.AddRect(new RectI(VecI.Zero, target.Size));
+        documentConstraint.AddRect((RectD)new RectI(VecI.Zero, target.Size));
         return true;
         return true;
     }
     }
 
 

+ 4 - 2
src/PixiEditor/Models/DocumentModels/Public/DocumentOperationsModule.cs

@@ -515,8 +515,10 @@ internal class DocumentOperationsModule : IDocumentOperations
         Guid newGuid = Guid.NewGuid();
         Guid newGuid = Guid.NewGuid();
 
 
         //make a new layer, put combined image onto it, delete layers that were merged
         //make a new layer, put combined image onto it, delete layers that were merged
+        bool allVectorNodes = members.All(x => Document.StructureHelper.Find(x) is IVectorLayerHandler);
+        Type layerToCreate = allVectorNodes ? typeof(VectorLayerNode) : typeof(ImageLayerNode);
         Internals.ActionAccumulator.AddActions(
         Internals.ActionAccumulator.AddActions(
-            new CreateStructureMember_Action(parent.Id, newGuid, typeof(ImageLayerNode)),
+            new CreateStructureMember_Action(parent.Id, newGuid, layerToCreate),
             new StructureMemberName_Action(newGuid, node.NodeNameBindable),
             new StructureMemberName_Action(newGuid, node.NodeNameBindable),
             new CombineStructureMembersOnto_Action(members.ToHashSet(), newGuid));
             new CombineStructureMembersOnto_Action(members.ToHashSet(), newGuid));
         foreach (var member in members)
         foreach (var member in members)
@@ -783,7 +785,7 @@ internal class DocumentOperationsModule : IDocumentOperations
         
         
         var selection = Document.SelectionPathBindable;
         var selection = Document.SelectionPathBindable;
         var inverse = new VectorPath();
         var inverse = new VectorPath();
-        inverse.AddRect(new RectI(new(0, 0), Document.SizeBindable));
+        inverse.AddRect(new RectD(new(0, 0), Document.SizeBindable));
 
 
         Internals.ActionAccumulator.AddFinishedActions(
         Internals.ActionAccumulator.AddFinishedActions(
             new SetSelection_Action(inverse.Op(selection, VectorPathOp.Difference)));
             new SetSelection_Action(inverse.Op(selection, VectorPathOp.Difference)));