Browse Source

Fixed some pasting scenarios and added delete on cut other layer types

Krzysztof Krysiński 1 month ago
parent
commit
841ec375a8

+ 49 - 3
src/PixiEditor/Models/Controllers/ClipboardController.cs

@@ -249,22 +249,40 @@ internal static class ClipboardController
         if (targetDoc != null && !hadSelection && pasteAsNew && layerIds is { Length: > 0 } &&
             (!hasPos || await AllMatchesPos(layerIds, data, targetDoc)))
         {
-            foreach (var layerId in layerIds)
+            List<Guid> adjustedLayerIds = AdjustIdsForImport(layerIds, targetDoc, document);
+            List<Guid?> newIds = new();
+            using var block = document.Operations.StartChangeBlock();
+            foreach (var layerId in adjustedLayerIds)
             {
                 if (targetDoc.StructureHelper.Find(layerId) == null)
                     continue;
 
                 if (sourceDocument == document.Id)
                 {
-                    document.Operations.DuplicateMember(layerId);
+                    newIds.Add(document.Operations.DuplicateMember(layerId));
                 }
                 else
                 {
-                    document.Operations.ImportMember(layerId, targetDoc);
+                    newIds.Add(document.Operations.ImportMember(layerId, targetDoc));
                 }
             }
 
             manager.Owner.ToolsSubViewModel.SetActiveTool<MoveToolViewModel>(false);
+            Guid? mainGuid = newIds.FirstOrDefault(x => x != null);
+            if (mainGuid != null)
+            {
+                document.Operations.ClearSoftSelectedMembers();
+                document.Operations.SetSelectedMember(mainGuid.Value);
+
+                Guid[] restGuids = newIds.Where(x => x != null && x != mainGuid).Select(x => x.Value).ToArray();
+                if (restGuids.Length > 0)
+                {
+                    foreach (var guid in restGuids)
+                    {
+                        document.Operations.AddSoftSelectedMember(guid);
+                    }
+                }
+            }
 
             return true;
         }
@@ -316,6 +334,34 @@ internal static class ClipboardController
         return true;
     }
 
+    private static List<Guid> AdjustIdsForImport(Guid[] layerIds, IDocument targetDoc, DocumentViewModel document)
+    {
+        // This should only copy root level layers
+        List<Guid> adjustedIds = new();
+        foreach (var layerId in layerIds)
+        {
+           var parents = targetDoc.StructureHelper.GetParents(layerId);
+           if (parents.Count == 0)
+           {
+                adjustedIds.Add(layerId);
+                continue;
+           }
+
+           // only include if no parent is in layerIds
+           if (!parents.Any(x => layerIds.Contains(x.Id)))
+           {
+                adjustedIds.Add(layerId);
+           }
+        }
+
+        var all = targetDoc.StructureHelper.GetAllMembersInOrder();
+
+        // order by document order
+        adjustedIds = adjustedIds.OrderBy(x => all.FindIndex(y => y.Id == x)).ToList();
+
+        return adjustedIds;
+    }
+
     private static async Task<bool> AllMatchesPos(Guid[] layerIds, IImportObject[] dataFormats, IDocument doc)
     {
         var dataObjectWithPos = dataFormats.FirstOrDefault(x => x.Contains(ClipboardDataFormats.PositionFormat));

+ 36 - 7
src/PixiEditor/Models/DocumentModels/Public/DocumentOperationsModule.cs

@@ -82,8 +82,8 @@ internal class DocumentOperationsModule : IDocumentOperations
     /// <param name="lastTransformRect"></param>
     public void DeleteSelectedPixels(int frame, bool clearSelection = false, RectD? lastTransformRect = null)
     {
-        var member = Document.SelectedStructureMember;
-        if (Internals.ChangeController.IsBlockingChangeActive || member is null)
+        var members = Document.SelectedMembers;
+        if (Internals.ChangeController.IsBlockingChangeActive || members?.Count == 0)
             return;
 
         Internals.ChangeController.TryStopActiveExecutor();
@@ -99,11 +99,40 @@ internal class DocumentOperationsModule : IDocumentOperations
             }
         }
 
-        bool drawOnMask = member is not ILayerHandler layer || layer.ShouldDrawOnMask;
-        if (drawOnMask && !member.HasMaskBindable)
-            return;
-        Internals.ActionAccumulator.AddActions(new ClearSelectedArea_Action(member.Id,
-            selection, drawOnMask, frame));
+        foreach (var memberGuid in members)
+        {
+            var member = Document.StructureHelper.FindNode<IStructureMemberHandler>(memberGuid);
+            if (member is null)
+                continue;
+
+            bool drawOnMask = member is not ILayerHandler layer || layer.ShouldDrawOnMask;
+            if (drawOnMask && !member.HasMaskBindable)
+                return;
+
+            if (member is not IRasterLayerHandler)
+            {
+                var bounds = member.TightBounds;
+                if (bounds is null)
+                    continue;
+
+                using var rectPath = new VectorPath();
+                rectPath.AddRect(new RectD(bounds.Value.Pos, bounds.Value.Size));
+
+                using var opped = selection.Op(rectPath, VectorPathOp.Intersect);
+
+                if (!opped.IsEmpty)
+                {
+                    // TODO: Cut vectors
+                    Internals.ActionAccumulator.AddActions(new DeleteNode_Action(member.Id));
+                }
+            }
+            else
+            {
+                Internals.ActionAccumulator.AddActions(new ClearSelectedArea_Action(member.Id,
+                    selection, drawOnMask, frame));
+            }
+        }
+
         if (clearSelection)
             Internals.ActionAccumulator.AddActions(new ClearSelection_Action());
         Internals.ActionAccumulator.AddFinishedActions();

+ 23 - 0
src/PixiEditor/Models/DocumentModels/Public/DocumentStructureModule.cs

@@ -274,4 +274,27 @@ internal class DocumentStructureModule
 
         return children;
     }
+
+    public List<IStructureMemberHandler> GetAllMembersInOrder()
+    {
+        var allMembers = doc.NodeGraphHandler.StructureTree.Members;
+
+        List<IStructureMemberHandler> membersInOrder = new List<IStructureMemberHandler>();
+        for (var i = allMembers.Count - 1; i >= 0; i--)
+        {
+            var member = allMembers[i];
+            membersInOrder.Add(member);
+
+            if (member is IFolderHandler folder)
+            {
+                membersInOrder.AddRange(GetFolderChildren(folder.Id));
+            }
+            else
+            {
+                membersInOrder.Add(member);
+            }
+        }
+
+        return membersInOrder;
+    }
 }

+ 0 - 19
src/PixiEditor/ViewModels/SubViewModels/ClipboardViewModel.cs

@@ -96,26 +96,7 @@ internal class ClipboardViewModel : SubViewModel<ViewModelMain>
 
         Dispatcher.UIThread.InvokeAsync(async () =>
         {
-            Guid[] guids = doc.StructureHelper.GetAllLayers().Select(x => x.Id).ToArray();
             await ClipboardController.TryPasteFromClipboard(doc, Owner.DocumentManagerSubViewModel, pasteAsNewLayer);
-
-            doc.Operations.InvokeCustomAction(
-                () =>
-                {
-                    Guid[] newGuids = doc.StructureHelper.GetAllLayers().Select(x => x.Id).ToArray();
-
-                    var diff = newGuids.Except(guids).ToArray();
-                    if (diff.Length > 0)
-                    {
-                        doc.Operations.ClearSoftSelectedMembers();
-                        doc.Operations.SetSelectedMember(diff[0]);
-
-                        for (int i = 1; i < diff.Length; i++)
-                        {
-                            doc.Operations.AddSoftSelectedMember(diff[i]);
-                        }
-                    }
-                }, false);
         });
     }