Selaa lähdekoodia

Added change blocks and fixed duplicate nodes undo

flabbet 8 kuukautta sitten
vanhempi
commit
45b7bc6684

+ 0 - 5
src/PixiEditor.ChangeableDocument/Changes/NodeGraph/DuplicateNode_Change.cs

@@ -44,9 +44,4 @@ internal class DuplicateNode_Change : Change
 
         return new DeleteNode_ChangeInfo(node.Id);
     }
-
-    public override bool IsMergeableWith(Change other)
-    {
-        return other is DuplicateNode_Change;
-    }
 }

+ 29 - 5
src/PixiEditor/Models/DocumentModels/ActionAccumulator.cs

@@ -23,6 +23,8 @@ internal class ActionAccumulator
     private CanvasUpdater canvasUpdater;
     private MemberPreviewUpdater previewUpdater;
 
+    private bool isChangeBlockActive = false;
+
     public ActionAccumulator(IDocument doc, DocumentInternalParts internals)
     {
         this.document = doc;
@@ -32,6 +34,21 @@ internal class ActionAccumulator
         previewUpdater = new(doc, internals);
     }
 
+    public void StartChangeBlock()
+    {
+        if (isChangeBlockActive)
+            throw new InvalidOperationException("Change block is already active");
+
+        isChangeBlockActive = true;
+    }
+
+    public void EndChangeBlock()
+    {
+        isChangeBlockActive = false;
+        queuedActions.Add((ActionSource.Automated, new ChangeBoundary_Action()));
+        TryExecuteAccumulatedActions();
+    }
+
     public void AddFinishedActions(params IAction[] actions)
     {
         foreach (var action in actions)
@@ -39,8 +56,11 @@ internal class ActionAccumulator
             queuedActions.Add((ActionSource.User, action));
         }
 
-        queuedActions.Add((ActionSource.Automated, new ChangeBoundary_Action()));
-        TryExecuteAccumulatedActions();
+        if (!isChangeBlockActive)
+        {
+            queuedActions.Add((ActionSource.Automated, new ChangeBoundary_Action()));
+            TryExecuteAccumulatedActions();
+        }
     }
 
     public void AddActions(params IAction[] actions)
@@ -50,7 +70,10 @@ internal class ActionAccumulator
             queuedActions.Add((ActionSource.User, action));
         }
 
-        TryExecuteAccumulatedActions();
+        if (!isChangeBlockActive)
+        {
+            TryExecuteAccumulatedActions();
+        }
     }
 
     public void AddActions(ActionSource source, IAction action)
@@ -59,7 +82,7 @@ internal class ActionAccumulator
         TryExecuteAccumulatedActions();
     }
 
-    private async void TryExecuteAccumulatedActions()
+    internal async Task TryExecuteAccumulatedActions()
     {
         if (executing || queuedActions.Count == 0)
             return;
@@ -114,7 +137,8 @@ internal class ActionAccumulator
                     undoBoundaryPassed || viewportRefreshRequest);
             }
 
-            previewUpdater.UpdatePreviews(undoBoundaryPassed, affectedAreas.ImagePreviewAreas.Keys, affectedAreas.MaskPreviewAreas.Keys,
+            previewUpdater.UpdatePreviews(undoBoundaryPassed, affectedAreas.ImagePreviewAreas.Keys,
+                affectedAreas.MaskPreviewAreas.Keys,
                 affectedAreas.ChangedNodes, affectedAreas.ChangedKeyFrames);
 
             // force refresh viewports for better responsiveness

+ 22 - 0
src/PixiEditor/Models/DocumentModels/Public/ChangeBlock.cs

@@ -0,0 +1,22 @@
+namespace PixiEditor.Models.DocumentModels.Public;
+
+public class ChangeBlock : IDisposable
+{
+    private ActionAccumulator Accumulator { get; }
+    
+    internal ChangeBlock(ActionAccumulator accumulator)
+    {
+        Accumulator = accumulator;
+        Accumulator.StartChangeBlock();
+    }
+    
+    public async Task ExecuteQueuedActions()
+    {
+        await Accumulator.TryExecuteAccumulatedActions();
+    }
+    
+    public void Dispose()
+    {
+        Accumulator.EndChangeBlock();
+    }
+}

+ 6 - 0
src/PixiEditor/Models/DocumentModels/Public/DocumentOperationsModule.cs

@@ -1,4 +1,5 @@
 using System.Collections.Immutable;
+using System.Reactive.Disposables;
 using ChunkyImageLib.DataHolders;
 using PixiEditor.ChangeableDocument;
 using PixiEditor.ChangeableDocument.Actions;
@@ -33,6 +34,11 @@ internal class DocumentOperationsModule : IDocumentOperations
         Document = document;
         Internals = internals;
     }
+    
+    public ChangeBlock StartChangeBlock()
+    {
+        return new ChangeBlock(Internals.ActionAccumulator);
+    }
 
     /// <summary>
     /// Creates a new selection with the size of the document

+ 6 - 1
src/PixiEditor/ViewModels/SubViewModels/ClipboardViewModel.cs

@@ -163,6 +163,8 @@ internal class ClipboardViewModel : SubViewModel<ViewModelMain>
 
         Dictionary<Guid, Guid> nodeMapping = new();
 
+        using var block = doc.Operations.StartChangeBlock();
+
         foreach (var nodeId in toDuplicate)
         {
             Guid? newId = doc.Operations.DuplicateNode(nodeId);
@@ -175,10 +177,13 @@ internal class ClipboardViewModel : SubViewModel<ViewModelMain>
 
         if (newIds.Count == 0)
             return;
+
+        await block.ExecuteQueuedActions();
         
+        ConnectRelatedNodes(doc, nodeMapping);
+
         doc.Operations.InvokeCustomAction(() =>
         {
-            ConnectRelatedNodes(doc, nodeMapping);
             foreach (var node in doc.NodeGraph.AllNodes)
             {
                 node.IsNodeSelected = false;