Browse Source

Added multiple layer manipulation for ShiftTool

flabbet 2 years ago
parent
commit
1332255ef0

+ 57 - 20
src/PixiEditor.ChangeableDocument/Changes/Drawing/ShiftLayer_UpdateableChange.cs

@@ -1,24 +1,39 @@
-using PixiEditor.DrawingApi.Core.Numerics;
+using System.Runtime.InteropServices;
+using PixiEditor.DrawingApi.Core.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changes.Drawing;
 namespace PixiEditor.ChangeableDocument.Changes.Drawing;
 internal class ShiftLayer_UpdateableChange : UpdateableChange
 internal class ShiftLayer_UpdateableChange : UpdateableChange
 {
 {
-    private readonly Guid layerGuid;
+    private List<Guid> layerGuids;
     private bool keepOriginal;
     private bool keepOriginal;
     private VecI delta;
     private VecI delta;
-    private CommittedChunkStorage? originalLayerChunks;
+    private Dictionary<Guid, CommittedChunkStorage?> originalLayerChunks = new();
+    
+    private List<IChangeInfo> _tempChanges = new();
 
 
     [GenerateUpdateableChangeActions]
     [GenerateUpdateableChangeActions]
-    public ShiftLayer_UpdateableChange(Guid layerGuid, VecI delta, bool keepOriginal)
+    public ShiftLayer_UpdateableChange(List<Guid> layerGuids, VecI delta, bool keepOriginal)
     {
     {
         this.delta = delta;
         this.delta = delta;
-        this.layerGuid = layerGuid;
+        this.layerGuids = layerGuids;
         this.keepOriginal = keepOriginal;
         this.keepOriginal = keepOriginal;
     }
     }
 
 
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
     {
     {
-        return target.HasMember<Layer>(layerGuid);
+        if (layerGuids.Count == 0)
+        {
+            return false;
+        }
+
+        layerGuids = target.ExtractLayers(layerGuids);
+
+        foreach (var layer in layerGuids)
+        {
+            if (!target.HasMember(layer)) return false;
+        }
+        
+        return true;
     }
     }
 
 
     [UpdateChangeMethod]
     [UpdateChangeMethod]
@@ -30,33 +45,55 @@ internal class ShiftLayer_UpdateableChange : UpdateableChange
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
     {
-        var chunks = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, keepOriginal, delta);
-        var image = target.FindMemberOrThrow<Layer>(layerGuid).LayerImage;
-
-        if (originalLayerChunks is not null)
-            throw new InvalidOperationException("saved chunks is not null even though we are trying to save them again");
-        originalLayerChunks = new(image, image.FindAffectedChunks());
-        image.CommitChanges();
+        originalLayerChunks = new Dictionary<Guid, CommittedChunkStorage?>();
+        List<IChangeInfo> changes = new List<IChangeInfo>();
+        foreach (var layerGuid in layerGuids)
+        {
+            var chunks = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, keepOriginal, delta);
+            var image = target.FindMemberOrThrow<Layer>(layerGuid).LayerImage;
+            
+            changes.Add(new LayerImageChunks_ChangeInfo(layerGuid, chunks));
+            
+            originalLayerChunks[layerGuid] = new(image, image.FindAffectedChunks());
+            image.CommitChanges();
+        }
 
 
         ignoreInUndo = delta.TaxicabLength == 0;
         ignoreInUndo = delta.TaxicabLength == 0;
-        return new LayerImageChunks_ChangeInfo(layerGuid, chunks);
+        return changes;
     }
     }
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     {
     {
-        var chunks = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, keepOriginal, delta);
-        return new LayerImageChunks_ChangeInfo(layerGuid, chunks);
+        _tempChanges.Clear();
+
+        foreach (var layerGuid in layerGuids)
+        {
+            var chunks = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, keepOriginal, delta);
+            _tempChanges.Add(new LayerImageChunks_ChangeInfo(layerGuid, chunks));
+        }
+        
+        return _tempChanges;
     }
     }
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
     {
-        var image = target.FindMemberOrThrow<Layer>(layerGuid).LayerImage;
-        var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(image, ref originalLayerChunks);
-        return new LayerImageChunks_ChangeInfo(layerGuid, affected);
+        List<IChangeInfo> changes = new List<IChangeInfo>();
+        foreach (var layerGuid in layerGuids)
+        {
+            var image = target.FindMemberOrThrow<Layer>(layerGuid).LayerImage;
+            CommittedChunkStorage? originalChunks = originalLayerChunks[layerGuid];
+            var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(image, ref originalChunks);
+            changes.Add(new LayerImageChunks_ChangeInfo(layerGuid, affected));
+        }
+        
+        return changes;
     }
     }
 
 
     public override void Dispose()
     public override void Dispose()
     {
     {
-        originalLayerChunks?.Dispose();
+        foreach (var (_, value) in originalLayerChunks)
+        {
+            value?.Dispose();
+        }
     }
     }
 }
 }

+ 23 - 6
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/ShiftLayerExecutor.cs

@@ -9,7 +9,7 @@ namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 #nullable enable
 #nullable enable
 internal class ShiftLayerExecutor : UpdateableChangeExecutor
 internal class ShiftLayerExecutor : UpdateableChangeExecutor
 {
 {
-    private Guid guidValue;
+    private List<Guid> _affectedMemberGuids = new List<Guid>();
     private VecI startPos;
     private VecI startPos;
     private MoveToolViewModel? tool;
     private MoveToolViewModel? tool;
 
 
@@ -17,22 +17,39 @@ internal class ShiftLayerExecutor : UpdateableChangeExecutor
     {
     {
         ViewModelMain? vm = ViewModelMain.Current;
         ViewModelMain? vm = ViewModelMain.Current;
         StructureMemberViewModel? member = document!.SelectedStructureMember;
         StructureMemberViewModel? member = document!.SelectedStructureMember;
+        if(member != null)
+            _affectedMemberGuids.Add(member.GuidValue);
+        _affectedMemberGuids.AddRange(document!.SoftSelectedStructureMembers.Select(x => x.GuidValue));
         tool = ViewModelMain.Current?.ToolsSubViewModel.GetTool<MoveToolViewModel>();
         tool = ViewModelMain.Current?.ToolsSubViewModel.GetTool<MoveToolViewModel>();
-        if (vm is null || member is not LayerViewModel layer || layer.ShouldDrawOnMask || tool is null)
+        if (vm is null || tool is null)
             return ExecutionState.Error;
             return ExecutionState.Error;
-
-        guidValue = member.GuidValue;
+        
+        RemoveDrawOnMaskLayers(_affectedMemberGuids);
+        
         startPos = controller!.LastPixelPosition;
         startPos = controller!.LastPixelPosition;
 
 
-        ShiftLayer_Action action = new(guidValue, VecI.Zero, tool.KeepOriginalImage);
+        ShiftLayer_Action action = new(_affectedMemberGuids, VecI.Zero, tool.KeepOriginalImage);
         internals!.ActionAccumulator.AddActions(action);
         internals!.ActionAccumulator.AddActions(action);
 
 
         return ExecutionState.Success;
         return ExecutionState.Success;
     }
     }
 
 
+    private void RemoveDrawOnMaskLayers(List<Guid> affectedMemberGuids)
+    {
+        for (var i = 0; i < affectedMemberGuids.Count; i++)
+        {
+            var guid = affectedMemberGuids[i];
+            if (document!.StructureHelper.FindOrThrow(guid) is LayerViewModel { ShouldDrawOnMask: true })
+            {
+                _affectedMemberGuids.Remove(guid);
+                i--;
+            }
+        }
+    }
+
     public override void OnPixelPositionChange(VecI pos)
     public override void OnPixelPositionChange(VecI pos)
     {
     {
-        ShiftLayer_Action action = new(guidValue, pos - startPos, tool!.KeepOriginalImage);
+        ShiftLayer_Action action = new(_affectedMemberGuids, pos - startPos, tool!.KeepOriginalImage);
         internals!.ActionAccumulator.AddActions(action);
         internals!.ActionAccumulator.AddActions(action);
     }
     }