Browse Source

Added frame to most changes

flabbet 1 year ago
parent
commit
60e6cf94b1
33 changed files with 251 additions and 153 deletions
  1. 1 0
      src/PixiEditor.ChangeableDocument/Changeables/Interfaces/IReadOnlyRasterLayer.cs
  2. 15 0
      src/PixiEditor.ChangeableDocument/Changeables/RasterLayer.cs
  3. 11 5
      src/PixiEditor.ChangeableDocument/Changes/Animation/CreateRasterKeyFrame_Change.cs
  4. 15 9
      src/PixiEditor.ChangeableDocument/Changes/Drawing/ApplyLayerMask_Change.cs
  5. 20 12
      src/PixiEditor.ChangeableDocument/Changes/Drawing/ChangeBrightness_UpdateableChange.cs
  6. 5 3
      src/PixiEditor.ChangeableDocument/Changes/Drawing/ClearSelectedArea_Change.cs
  7. 9 7
      src/PixiEditor.ChangeableDocument/Changes/Drawing/CombineStructureMembersOnto_Change.cs
  8. 6 4
      src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawEllipse_UpdateableChange.cs
  9. 6 4
      src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawLine_UpdateableChange.cs
  10. 7 5
      src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawRectangle_UpdateableChange.cs
  11. 2 2
      src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawingChangeHelper.cs
  12. 7 6
      src/PixiEditor.ChangeableDocument/Changes/Drawing/FloodFill/FloodFillHelper.cs
  13. 6 4
      src/PixiEditor.ChangeableDocument/Changes/Drawing/FloodFill/FloodFill_Change.cs
  14. 9 6
      src/PixiEditor.ChangeableDocument/Changes/Drawing/LineBasedPen_UpdateableChange.cs
  15. 5 4
      src/PixiEditor.ChangeableDocument/Changes/Drawing/PasteImage_UpdateableChange.cs
  16. 7 5
      src/PixiEditor.ChangeableDocument/Changes/Drawing/PathBasedPen_UpdateableChange.cs
  17. 7 5
      src/PixiEditor.ChangeableDocument/Changes/Drawing/PixelPerfectPen_UpdateableChange.cs
  18. 10 7
      src/PixiEditor.ChangeableDocument/Changes/Drawing/ReplaceColor_Change.cs
  19. 5 3
      src/PixiEditor.ChangeableDocument/Changes/Drawing/SelectionToMask_Change.cs
  20. 2 2
      src/PixiEditor.ChangeableDocument/Changes/Drawing/ShiftLayerHelper.cs
  21. 7 5
      src/PixiEditor.ChangeableDocument/Changes/Drawing/ShiftLayer_UpdateableChange.cs
  22. 8 5
      src/PixiEditor.ChangeableDocument/Changes/Drawing/TransformSelectedArea_UpdateableChange.cs
  23. 9 6
      src/PixiEditor.ChangeableDocument/Changes/Root/CenterContent_Change.cs
  24. 5 3
      src/PixiEditor.ChangeableDocument/Changes/Root/ClipCanvas_Change.cs
  25. 3 2
      src/PixiEditor.ChangeableDocument/Changes/Root/Crop_Change.cs
  26. 7 4
      src/PixiEditor.ChangeableDocument/Changes/Root/FlipImage_Change.cs
  27. 10 3
      src/PixiEditor.ChangeableDocument/Changes/Root/ResizeBasedChangeBase.cs
  28. 2 2
      src/PixiEditor.ChangeableDocument/Changes/Root/ResizeCanvas_Change.cs
  29. 13 9
      src/PixiEditor.ChangeableDocument/Changes/Root/ResizeImage_Change.cs
  30. 11 8
      src/PixiEditor.ChangeableDocument/Changes/Root/RotateImage_Change.cs
  31. 2 2
      src/PixiEditor.ChangeableDocument/Changes/Selection/MagicWand/MagicWandHelper.cs
  32. 4 2
      src/PixiEditor.ChangeableDocument/Changes/Selection/MagicWand/MagicWand_Change.cs
  33. 15 9
      src/PixiEditor.ChangeableDocument/Changes/Structure/ApplyMask_Change.cs

+ 1 - 0
src/PixiEditor.ChangeableDocument/Changeables/Interfaces/IReadOnlyRasterLayer.cs

@@ -6,4 +6,5 @@ public interface IReadOnlyRasterLayer : ITransparencyLockable
     /// The chunky image of the layer
     /// The chunky image of the layer
     /// </summary>
     /// </summary>
     IReadOnlyChunkyImage GetLayerImageAtFrame(int frame);
     IReadOnlyChunkyImage GetLayerImageAtFrame(int frame);
+    void SetLayerImageAtFrame(int frame, IReadOnlyChunkyImage image);
 }
 }

+ 15 - 0
src/PixiEditor.ChangeableDocument/Changeables/RasterLayer.cs

@@ -36,6 +36,7 @@ internal class RasterLayer : Layer, IReadOnlyRasterLayer
     }
     }
 
 
     IReadOnlyChunkyImage IReadOnlyRasterLayer.GetLayerImageAtFrame(int frame) => GetLayerImageAtFrame(frame);
     IReadOnlyChunkyImage IReadOnlyRasterLayer.GetLayerImageAtFrame(int frame) => GetLayerImageAtFrame(frame);
+    void IReadOnlyRasterLayer.SetLayerImageAtFrame(int frame, IReadOnlyChunkyImage newLayerImage) => SetLayerImageAtFrame(frame, (ChunkyImage)newLayerImage);
     
     
     public ChunkyImage GetLayerImageAtFrame(int frame)
     public ChunkyImage GetLayerImageAtFrame(int frame)
     {
     {
@@ -83,6 +84,20 @@ internal class RasterLayer : Layer, IReadOnlyRasterLayer
             LockTransparency = LockTransparency
             LockTransparency = LockTransparency
         };
         };
     }
     }
+
+    public void SetLayerImageAtFrame(int frame, ChunkyImage newLayerImage)
+    {
+        ImageFrame existingFrame = frameImages.FirstOrDefault(x => x.IsInFrame(frame));
+        if (existingFrame is not null)
+        {
+            existingFrame.Image.Dispose();
+            existingFrame.Image = newLayerImage;
+        }
+        else
+        {
+            frameImages.Add(new ImageFrame(frame, frame, newLayerImage));
+        }
+    }
 }
 }
 
 
 class ImageFrame
 class ImageFrame

+ 11 - 5
src/PixiEditor.ChangeableDocument/Changes/Animation/CreateRasterKeyFrame_Change.cs

@@ -7,18 +7,21 @@ internal class CreateRasterKeyFrame_Change : Change
 {
 {
     private readonly Guid _targetLayerGuid;
     private readonly Guid _targetLayerGuid;
     private readonly int _frame;
     private readonly int _frame;
-    private readonly bool _cloneFromExisting;
+    private readonly Guid? cloneFrom;
+    private int? cloneFromFrame;
     private RasterLayer? _layer;
     private RasterLayer? _layer;
     private Guid createdKeyFrameId;
     private Guid createdKeyFrameId;
 
 
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
     public CreateRasterKeyFrame_Change(Guid targetLayerGuid, Guid newKeyFrameGuid, int frame,
     public CreateRasterKeyFrame_Change(Guid targetLayerGuid, Guid newKeyFrameGuid, int frame,
-        bool cloneFromExisting = false)
+        int? cloneFromFrame = null,
+        Guid? cloneFromExisting = null)
     {
     {
         _targetLayerGuid = targetLayerGuid;
         _targetLayerGuid = targetLayerGuid;
         _frame = frame;
         _frame = frame;
-        _cloneFromExisting = cloneFromExisting;
+        cloneFrom = cloneFromExisting;
         createdKeyFrameId = newKeyFrameGuid;
         createdKeyFrameId = newKeyFrameGuid;
+        this.cloneFromFrame = cloneFromFrame;
     }
     }
 
 
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
@@ -29,12 +32,15 @@ internal class CreateRasterKeyFrame_Change : Change
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply,
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply,
         out bool ignoreInUndo)
         out bool ignoreInUndo)
     {
     {
+        var cloneFromImage = cloneFrom.HasValue
+            ? target.FindMemberOrThrow<RasterLayer>(cloneFrom.Value).GetLayerImageAtFrame(cloneFromFrame ?? 0)
+            : null;
         var keyFrame =
         var keyFrame =
-            new RasterKeyFrame(_targetLayerGuid, _frame, target, _cloneFromExisting ? _layer.LayerImage : null);
+            new RasterKeyFrame(_targetLayerGuid, _frame, target, cloneFromImage);
         keyFrame.Id = createdKeyFrameId;
         keyFrame.Id = createdKeyFrameId;
         target.AnimationData.AddKeyFrame(keyFrame);
         target.AnimationData.AddKeyFrame(keyFrame);
         ignoreInUndo = false;
         ignoreInUndo = false;
-        return new CreateRasterKeyFrame_ChangeInfo(_targetLayerGuid, _frame, createdKeyFrameId, _cloneFromExisting);
+        return new CreateRasterKeyFrame_ChangeInfo(_targetLayerGuid, _frame, createdKeyFrameId, cloneFrom.HasValue);
     }
     }
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)

+ 15 - 9
src/PixiEditor.ChangeableDocument/Changes/Drawing/ApplyLayerMask_Change.cs

@@ -8,11 +8,13 @@ internal class ApplyLayerMask_Change : Change
     private readonly Guid layerGuid;
     private readonly Guid layerGuid;
     private CommittedChunkStorage? savedMask;
     private CommittedChunkStorage? savedMask;
     private CommittedChunkStorage? savedLayer;
     private CommittedChunkStorage? savedLayer;
+    private int frame;
 
 
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
-    public ApplyLayerMask_Change(Guid layerGuid)
+    public ApplyLayerMask_Change(Guid layerGuid, int frame)
     {
     {
         this.layerGuid = layerGuid;
         this.layerGuid = layerGuid;
+        this.frame = frame;
     }
     }
 
 
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
@@ -21,7 +23,8 @@ internal class ApplyLayerMask_Change : Change
         if (!target.TryFindMember<RasterLayer>(layerGuid, out var layer) || layer.Mask is null)
         if (!target.TryFindMember<RasterLayer>(layerGuid, out var layer) || layer.Mask is null)
             return false;
             return false;
 
 
-        savedLayer = new CommittedChunkStorage(layer.LayerImage, layer.LayerImage.FindCommittedChunks());
+        var layerImage = layer.GetLayerImageAtFrame(frame);
+        savedLayer = new CommittedChunkStorage(layerImage, layerImage.FindCommittedChunks());
         savedMask = new CommittedChunkStorage(layer.Mask, layer.Mask.FindCommittedChunks());
         savedMask = new CommittedChunkStorage(layer.Mask, layer.Mask.FindCommittedChunks());
         return true;
         return true;
     }
     }
@@ -32,15 +35,16 @@ internal class ApplyLayerMask_Change : Change
         if (layer.Mask is null)
         if (layer.Mask is null)
             throw new InvalidOperationException("Cannot apply layer mask, no mask");
             throw new InvalidOperationException("Cannot apply layer mask, no mask");
 
 
+        var layerImage = layer.GetLayerImageAtFrame(frame);
         ChunkyImage newLayerImage = new ChunkyImage(target.Size);
         ChunkyImage newLayerImage = new ChunkyImage(target.Size);
         newLayerImage.AddRasterClip(layer.Mask);
         newLayerImage.AddRasterClip(layer.Mask);
-        newLayerImage.EnqueueDrawChunkyImage(VecI.Zero, layer.LayerImage);
+        newLayerImage.EnqueueDrawChunkyImage(VecI.Zero, layerImage);
         newLayerImage.CommitChanges();
         newLayerImage.CommitChanges();
 
 
-        var affectedChunks = layer.LayerImage.FindAllChunks();
+        var affectedChunks = layerImage.FindAllChunks();
         // use a temp value to ensure that LayerImage always stays in a valid state
         // use a temp value to ensure that LayerImage always stays in a valid state
-        var toDispose = layer.LayerImage;
-        layer.LayerImage = newLayerImage;
+        var toDispose = layerImage;
+        layer.SetLayerImageAtFrame(frame, newLayerImage);
         toDispose.Dispose();
         toDispose.Dispose();
 
 
         var toDisposeMask = layer.Mask;
         var toDisposeMask = layer.Mask;
@@ -69,9 +73,11 @@ internal class ApplyLayerMask_Change : Change
         newMask.CommitChanges();
         newMask.CommitChanges();
         layer.Mask = newMask;
         layer.Mask = newMask;
 
 
-        savedLayer.ApplyChunksToImage(layer.LayerImage);
-        var affectedChunksLayer = layer.LayerImage.FindAffectedArea();
-        layer.LayerImage.CommitChanges();
+        var layerImage = layer.GetLayerImageAtFrame(frame);
+        
+        savedLayer.ApplyChunksToImage(layerImage);
+        var affectedChunksLayer = layerImage.FindAffectedArea();
+        layerImage.CommitChanges();
 
 
         return new List<IChangeInfo>
         return new List<IChangeInfo>
         {
         {

+ 20 - 12
src/PixiEditor.ChangeableDocument/Changes/Drawing/ChangeBrightness_UpdateableChange.cs

@@ -15,19 +15,22 @@ internal class ChangeBrightness_UpdateableChange : UpdateableChange
     private readonly List<VecI> positions = new();
     private readonly List<VecI> positions = new();
     private bool ignoreUpdate = false;
     private bool ignoreUpdate = false;
     private readonly bool repeat;
     private readonly bool repeat;
+    private int frame;
 
 
     private List<VecI> ellipseLines;
     private List<VecI> ellipseLines;
     
     
     private CommittedChunkStorage? savedChunks;
     private CommittedChunkStorage? savedChunks;
 
 
     [GenerateUpdateableChangeActions]
     [GenerateUpdateableChangeActions]
-    public ChangeBrightness_UpdateableChange(Guid layerGuid, VecI pos, float correctionFactor, int strokeWidth, bool repeat)
+    public ChangeBrightness_UpdateableChange(Guid layerGuid, VecI pos, float correctionFactor, int strokeWidth, bool repeat, int frame)
     {
     {
         this.layerGuid = layerGuid;
         this.layerGuid = layerGuid;
         this.correctionFactor = correctionFactor;
         this.correctionFactor = correctionFactor;
         this.strokeWidth = strokeWidth;
         this.strokeWidth = strokeWidth;
         this.repeat = repeat;
         this.repeat = repeat;
-
+        this.frame = frame;
+        // TODO: pos is unused, check if it should be added to positions
+        
         ellipseLines = EllipseHelper.SplitEllipseIntoLines((EllipseHelper.GenerateEllipseFromRect(new RectI(0, 0, strokeWidth, strokeWidth))));
         ellipseLines = EllipseHelper.SplitEllipseIntoLines((EllipseHelper.GenerateEllipseFromRect(new RectI(0, 0, strokeWidth, strokeWidth))));
     }
     }
 
 
@@ -44,7 +47,8 @@ internal class ChangeBrightness_UpdateableChange : UpdateableChange
         if (!DrawingChangeHelper.IsValidForDrawing(target, layerGuid, false))
         if (!DrawingChangeHelper.IsValidForDrawing(target, layerGuid, false))
             return false;
             return false;
         RasterLayer layer = target.FindMemberOrThrow<RasterLayer>(layerGuid);
         RasterLayer layer = target.FindMemberOrThrow<RasterLayer>(layerGuid);
-        DrawingChangeHelper.ApplyClipsSymmetriesEtc(target, layer.LayerImage, layerGuid, false);
+        var layerImage = layer.GetLayerImageAtFrame(frame);
+        DrawingChangeHelper.ApplyClipsSymmetriesEtc(target, layerImage, layerGuid, false);
         return true;
         return true;
     }
     }
 
 
@@ -55,11 +59,12 @@ internal class ChangeBrightness_UpdateableChange : UpdateableChange
         VecI pos = positions[^1];
         VecI pos = positions[^1];
         RasterLayer layer = target.FindMemberOrThrow<RasterLayer>(layerGuid);
         RasterLayer layer = target.FindMemberOrThrow<RasterLayer>(layerGuid);
 
 
-        int queueLength = layer.LayerImage.QueueLength;
+        var layerImage = layer.GetLayerImageAtFrame(frame);
+        int queueLength = layerImage.QueueLength;
         
         
-        ChangeBrightness(ellipseLines, strokeWidth, pos + new VecI(-strokeWidth / 2), correctionFactor, repeat, layer.LayerImage);
+        ChangeBrightness(ellipseLines, strokeWidth, pos + new VecI(-strokeWidth / 2), correctionFactor, repeat, layerImage);
         
         
-        var affected = layer.LayerImage.FindAffectedArea(queueLength);
+        var affected = layerImage.FindAffectedArea(queueLength);
         
         
         return new LayerImageArea_ChangeInfo(layerGuid, affected);
         return new LayerImageArea_ChangeInfo(layerGuid, affected);
     }
     }
@@ -67,6 +72,7 @@ internal class ChangeBrightness_UpdateableChange : UpdateableChange
     private static void ChangeBrightness(
     private static void ChangeBrightness(
         List<VecI> circleLines, int circleDiameter, VecI offset, float correctionFactor, bool repeat, ChunkyImage layerImage)
         List<VecI> circleLines, int circleDiameter, VecI offset, float correctionFactor, bool repeat, ChunkyImage layerImage)
     {
     {
+        // TODO: Circle diameter is unused, check if it should be used
 
 
         for (var i = 0; i < circleLines.Count - 1; i++)
         for (var i = 0; i < circleLines.Count - 1; i++)
         {
         {
@@ -96,18 +102,20 @@ internal class ChangeBrightness_UpdateableChange : UpdateableChange
         if (savedChunks is not null)
         if (savedChunks is not null)
             throw new InvalidOperationException("Trying to apply while there are saved chunks");
             throw new InvalidOperationException("Trying to apply while there are saved chunks");
         
         
+        var layerImage = layer.GetLayerImageAtFrame(frame);
+        
         if (!firstApply)
         if (!firstApply)
         {
         {
-            DrawingChangeHelper.ApplyClipsSymmetriesEtc(target, layer.LayerImage, layerGuid, false);
+            DrawingChangeHelper.ApplyClipsSymmetriesEtc(target, layerImage, layerGuid, false);
             foreach (VecI pos in positions)
             foreach (VecI pos in positions)
             {
             {
-                ChangeBrightness(ellipseLines, strokeWidth, pos + new VecI(-strokeWidth / 2), correctionFactor, repeat, layer.LayerImage);
+                ChangeBrightness(ellipseLines, strokeWidth, pos + new VecI(-strokeWidth / 2), correctionFactor, repeat, layerImage);
             }
             }
         }
         }
 
 
-        var affArea = layer.LayerImage.FindAffectedArea();
-        savedChunks = new CommittedChunkStorage(layer.LayerImage, affArea.Chunks);
-        layer.LayerImage.CommitChanges();
+        var affArea = layerImage.FindAffectedArea();
+        savedChunks = new CommittedChunkStorage(layerImage, affArea.Chunks);
+        layerImage.CommitChanges();
         if (firstApply)
         if (firstApply)
             return new None();
             return new None();
         return new LayerImageArea_ChangeInfo(layerGuid, affArea);
         return new LayerImageArea_ChangeInfo(layerGuid, affArea);
@@ -115,7 +123,7 @@ internal class ChangeBrightness_UpdateableChange : UpdateableChange
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
     {
-        var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, layerGuid, false, ref savedChunks);
+        var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, layerGuid, false, frame, ref savedChunks);
         return new LayerImageArea_ChangeInfo(layerGuid, affected);
         return new LayerImageArea_ChangeInfo(layerGuid, affected);
     }
     }
 }
 }

+ 5 - 3
src/PixiEditor.ChangeableDocument/Changes/Drawing/ClearSelectedArea_Change.cs

@@ -7,12 +7,14 @@ internal class ClearSelectedArea_Change : Change
     private readonly Guid memberGuid;
     private readonly Guid memberGuid;
     private readonly bool drawOnMask;
     private readonly bool drawOnMask;
     private CommittedChunkStorage? savedChunks;
     private CommittedChunkStorage? savedChunks;
+    private int frame;
 
 
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
-    public ClearSelectedArea_Change(Guid memberGuid, bool drawOnMask)
+    public ClearSelectedArea_Change(Guid memberGuid, bool drawOnMask, int frame)
     {
     {
         this.memberGuid = memberGuid;
         this.memberGuid = memberGuid;
         this.drawOnMask = drawOnMask;
         this.drawOnMask = drawOnMask;
+        this.frame = frame;
     }
     }
 
 
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
@@ -25,7 +27,7 @@ internal class ClearSelectedArea_Change : Change
         if (savedChunks is not null)
         if (savedChunks is not null)
             throw new InvalidOperationException("trying to save chunks while they are already saved");
             throw new InvalidOperationException("trying to save chunks while they are already saved");
 
 
-        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
 
 
         RectD bounds = target.Selection.SelectionPath.Bounds;
         RectD bounds = target.Selection.SelectionPath.Bounds;
         RectI intBounds = (RectI)bounds.Intersect(new RectD(0, 0, target.Size.X, target.Size.Y)).RoundOutwards();
         RectI intBounds = (RectI)bounds.Intersect(new RectD(0, 0, target.Size.X, target.Size.Y)).RoundOutwards();
@@ -40,7 +42,7 @@ internal class ClearSelectedArea_Change : Change
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
     {
-        var affArea = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, ref savedChunks);
+        var affArea = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, frame, ref savedChunks);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, affArea, drawOnMask);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, affArea, drawOnMask);
     }
     }
 
 

+ 9 - 7
src/PixiEditor.ChangeableDocument/Changes/Drawing/CombineStructureMembersOnto_Change.cs

@@ -60,22 +60,24 @@ internal class CombineStructureMembersOnto_Change : Change
         foreach (var guid in layersToCombine)
         foreach (var guid in layersToCombine)
         {
         {
             var layer = target.FindMemberOrThrow<RasterLayer>(guid);
             var layer = target.FindMemberOrThrow<RasterLayer>(guid);
-            chunksToCombine.UnionWith(layer.LayerImage.FindAllChunks());
+            var layerImage = layer.GetLayerImageAtFrame(frame);
+            chunksToCombine.UnionWith(layerImage.FindAllChunks());
         }
         }
 
 
-        toDrawOn.LayerImage.EnqueueClear();
+        var toDrawOnImage = toDrawOn.GetLayerImageAtFrame(frame);
+        toDrawOnImage.EnqueueClear();
         foreach (var chunk in chunksToCombine)
         foreach (var chunk in chunksToCombine)
         {
         {
             OneOf<Chunk, EmptyChunk> combined = ChunkRenderer.MergeChosenMembers(chunk, ChunkResolution.Full, target.StructureRoot, frame, layersToCombine);
             OneOf<Chunk, EmptyChunk> combined = ChunkRenderer.MergeChosenMembers(chunk, ChunkResolution.Full, target.StructureRoot, frame, layersToCombine);
             if (combined.IsT0)
             if (combined.IsT0)
             {
             {
-                toDrawOn.LayerImage.EnqueueDrawImage(chunk * ChunkyImage.FullChunkSize, combined.AsT0.Surface);
+                toDrawOnImage.EnqueueDrawImage(chunk * ChunkyImage.FullChunkSize, combined.AsT0.Surface);
                 combined.AsT0.Dispose();
                 combined.AsT0.Dispose();
             }
             }
         }
         }
-        var affArea = toDrawOn.LayerImage.FindAffectedArea();
-        originalChunks = new CommittedChunkStorage(toDrawOn.LayerImage, affArea.Chunks);
-        toDrawOn.LayerImage.CommitChanges();
+        var affArea = toDrawOnImage.FindAffectedArea();
+        originalChunks = new CommittedChunkStorage(toDrawOnImage, affArea.Chunks);
+        toDrawOnImage.CommitChanges();
 
 
         ignoreInUndo = false;
         ignoreInUndo = false;
         return new LayerImageArea_ChangeInfo(targetLayer, affArea);
         return new LayerImageArea_ChangeInfo(targetLayer, affArea);
@@ -84,7 +86,7 @@ internal class CombineStructureMembersOnto_Change : Change
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
     {
         var toDrawOn = target.FindMemberOrThrow<RasterLayer>(targetLayer);
         var toDrawOn = target.FindMemberOrThrow<RasterLayer>(targetLayer);
-        var affectedArea = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(toDrawOn.LayerImage, ref originalChunks);
+        var affectedArea = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(toDrawOn.GetLayerImageAtFrame(frame), ref originalChunks);
         return new LayerImageArea_ChangeInfo(targetLayer, affectedArea);
         return new LayerImageArea_ChangeInfo(targetLayer, affectedArea);
     }
     }
 
 

+ 6 - 4
src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawEllipse_UpdateableChange.cs

@@ -11,11 +11,12 @@ internal class DrawEllipse_UpdateableChange : UpdateableChange
     private readonly Color fillColor;
     private readonly Color fillColor;
     private readonly int strokeWidth;
     private readonly int strokeWidth;
     private readonly bool drawOnMask;
     private readonly bool drawOnMask;
+    private int frame;
 
 
     private CommittedChunkStorage? storedChunks;
     private CommittedChunkStorage? storedChunks;
 
 
     [GenerateUpdateableChangeActions]
     [GenerateUpdateableChangeActions]
-    public DrawEllipse_UpdateableChange(Guid memberGuid, RectI location, Color strokeColor, Color fillColor, int strokeWidth, bool drawOnMask)
+    public DrawEllipse_UpdateableChange(Guid memberGuid, RectI location, Color strokeColor, Color fillColor, int strokeWidth, bool drawOnMask, int frame)
     {
     {
         this.memberGuid = memberGuid;
         this.memberGuid = memberGuid;
         this.location = location;
         this.location = location;
@@ -23,6 +24,7 @@ internal class DrawEllipse_UpdateableChange : UpdateableChange
         this.fillColor = fillColor;
         this.fillColor = fillColor;
         this.strokeWidth = strokeWidth;
         this.strokeWidth = strokeWidth;
         this.drawOnMask = drawOnMask;
         this.drawOnMask = drawOnMask;
+        this.frame = frame;
     }
     }
 
 
     [UpdateChangeMethod]
     [UpdateChangeMethod]
@@ -62,7 +64,7 @@ internal class DrawEllipse_UpdateableChange : UpdateableChange
             return new None();
             return new None();
         }
         }
 
 
-        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
         var area = UpdateEllipse(target, image);
         var area = UpdateEllipse(target, image);
         storedChunks = new CommittedChunkStorage(image, image.FindAffectedArea().Chunks);
         storedChunks = new CommittedChunkStorage(image, image.FindAffectedArea().Chunks);
         image.CommitChanges();
         image.CommitChanges();
@@ -72,14 +74,14 @@ internal class DrawEllipse_UpdateableChange : UpdateableChange
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     {
     {
-        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
         var area = UpdateEllipse(target, image);
         var area = UpdateEllipse(target, image);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, area, drawOnMask);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, area, drawOnMask);
     }
     }
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
     {
-        var affArea = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, ref storedChunks);
+        var affArea = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, frame, ref storedChunks);
         var changes = DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, affArea, drawOnMask);
         var changes = DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, affArea, drawOnMask);
         return changes;
         return changes;
     }
     }

+ 6 - 4
src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawLine_UpdateableChange.cs

@@ -15,10 +15,11 @@ internal class DrawLine_UpdateableChange : UpdateableChange
     private StrokeCap caps;
     private StrokeCap caps;
     private readonly bool drawOnMask;
     private readonly bool drawOnMask;
     private CommittedChunkStorage? savedChunks;
     private CommittedChunkStorage? savedChunks;
+    private int frame;
 
 
     [GenerateUpdateableChangeActions]
     [GenerateUpdateableChangeActions]
     public DrawLine_UpdateableChange
     public DrawLine_UpdateableChange
-        (Guid memberGuid, VecI from, VecI to, int strokeWidth, Color color, StrokeCap caps, bool drawOnMask)
+        (Guid memberGuid, VecI from, VecI to, int strokeWidth, Color color, StrokeCap caps, bool drawOnMask, int frame)
     {
     {
         this.memberGuid = memberGuid;
         this.memberGuid = memberGuid;
         this.from = from;
         this.from = from;
@@ -27,6 +28,7 @@ internal class DrawLine_UpdateableChange : UpdateableChange
         this.color = color;
         this.color = color;
         this.caps = caps;
         this.caps = caps;
         this.drawOnMask = drawOnMask;
         this.drawOnMask = drawOnMask;
+        this.frame = frame;
     }
     }
 
 
     [UpdateChangeMethod]
     [UpdateChangeMethod]
@@ -46,7 +48,7 @@ internal class DrawLine_UpdateableChange : UpdateableChange
 
 
     private AffectedArea CommonApply(Document target)
     private AffectedArea CommonApply(Document target)
     {
     {
-        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
         var oldAffected = image.FindAffectedArea();
         var oldAffected = image.FindAffectedArea();
         image.CancelChanges();
         image.CancelChanges();
         if (from != to)
         if (from != to)
@@ -75,7 +77,7 @@ internal class DrawLine_UpdateableChange : UpdateableChange
             return new None();
             return new None();
         }
         }
 
 
-        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
         var affected = CommonApply(target);
         var affected = CommonApply(target);
         if (savedChunks is not null)
         if (savedChunks is not null)
             throw new InvalidOperationException("Trying to save chunks while there are saved chunks already");
             throw new InvalidOperationException("Trying to save chunks while there are saved chunks already");
@@ -89,7 +91,7 @@ internal class DrawLine_UpdateableChange : UpdateableChange
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
     {
         var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull
         var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull
-            (target, memberGuid, drawOnMask, ref savedChunks);
+            (target, memberGuid, drawOnMask, frame, ref savedChunks);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, affected, drawOnMask);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, affected, drawOnMask);
     }
     }
 
 

+ 7 - 5
src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawRectangle_UpdateableChange.cs

@@ -8,13 +8,15 @@ internal class DrawRectangle_UpdateableChange : UpdateableChange
     private ShapeData rect;
     private ShapeData rect;
     private readonly bool drawOnMask;
     private readonly bool drawOnMask;
     private CommittedChunkStorage? storedChunks;
     private CommittedChunkStorage? storedChunks;
-
+    private int frame;
+    
     [GenerateUpdateableChangeActions]
     [GenerateUpdateableChangeActions]
-    public DrawRectangle_UpdateableChange(Guid memberGuid, ShapeData rectangle, bool drawOnMask)
+    public DrawRectangle_UpdateableChange(Guid memberGuid, ShapeData rectangle, bool drawOnMask, int frame)
     {
     {
         this.memberGuid = memberGuid;
         this.memberGuid = memberGuid;
         this.rect = rectangle;
         this.rect = rectangle;
         this.drawOnMask = drawOnMask;
         this.drawOnMask = drawOnMask;
+        this.frame = frame;
     }
     }
 
 
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
@@ -48,7 +50,7 @@ internal class DrawRectangle_UpdateableChange : UpdateableChange
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     {
     {
-        ChunkyImage targetImage = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        ChunkyImage targetImage = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
         var area = UpdateRectangle(target, targetImage);
         var area = UpdateRectangle(target, targetImage);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, area, drawOnMask);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, area, drawOnMask);
     }
     }
@@ -61,7 +63,7 @@ internal class DrawRectangle_UpdateableChange : UpdateableChange
             return new None();
             return new None();
         }
         }
 
 
-        ChunkyImage targetImage = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        ChunkyImage targetImage = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
         var area = UpdateRectangle(target, targetImage);
         var area = UpdateRectangle(target, targetImage);
         storedChunks = new CommittedChunkStorage(targetImage, area.Chunks);
         storedChunks = new CommittedChunkStorage(targetImage, area.Chunks);
         targetImage.CommitChanges();
         targetImage.CommitChanges();
@@ -72,7 +74,7 @@ internal class DrawRectangle_UpdateableChange : UpdateableChange
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
     {
-        var area = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, ref storedChunks);
+        var area = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, frame, ref storedChunks);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, area, drawOnMask);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, area, drawOnMask);
     }
     }
 
 

+ 2 - 2
src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawingChangeHelper.cs

@@ -4,9 +4,9 @@ using PixiEditor.DrawingApi.Core.Numerics;
 namespace PixiEditor.ChangeableDocument.Changes.Drawing;
 namespace PixiEditor.ChangeableDocument.Changes.Drawing;
 internal static class DrawingChangeHelper
 internal static class DrawingChangeHelper
 {
 {
-    public static AffectedArea ApplyStoredChunksDisposeAndSetToNull(Document target, Guid memberGuid, bool drawOnMask, ref CommittedChunkStorage? storage)
+    public static AffectedArea ApplyStoredChunksDisposeAndSetToNull(Document target, Guid memberGuid, bool drawOnMask, int frame, ref CommittedChunkStorage? storage)
     {
     {
-        var image = GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
         return ApplyStoredChunksDisposeAndSetToNull(image, ref storage);
         return ApplyStoredChunksDisposeAndSetToNull(image, ref storage);
     }
     }
 
 

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

@@ -19,19 +19,19 @@ public static class FloodFillHelper
     private static readonly VecI Left = new VecI(-1, 0);
     private static readonly VecI Left = new VecI(-1, 0);
     private static readonly VecI Right = new VecI(1, 0);
     private static readonly VecI Right = new VecI(1, 0);
 
 
-    internal static FloodFillChunkCache CreateCache(HashSet<Guid> membersToFloodFill, IReadOnlyDocument document)
+    internal static FloodFillChunkCache CreateCache(HashSet<Guid> membersToFloodFill, IReadOnlyDocument document, int frame)
     {
     {
         if (membersToFloodFill.Count == 1)
         if (membersToFloodFill.Count == 1)
         {
         {
             Guid guid = membersToFloodFill.First();
             Guid guid = membersToFloodFill.First();
             var member = document.FindMemberOrThrow(guid);
             var member = document.FindMemberOrThrow(guid);
             if (member is IReadOnlyFolder)
             if (member is IReadOnlyFolder)
-                return new FloodFillChunkCache(membersToFloodFill, document.StructureRoot);
+                return new FloodFillChunkCache(membersToFloodFill, document.StructureRoot, frame);
             if (member is not IReadOnlyRasterLayer rasterLayer)
             if (member is not IReadOnlyRasterLayer rasterLayer)
                 throw new InvalidOperationException("Member is not a raster layer");
                 throw new InvalidOperationException("Member is not a raster layer");
-            return new FloodFillChunkCache(rasterLayer.LayerImage);
+            return new FloodFillChunkCache(rasterLayer.GetLayerImageAtFrame(frame));
         }
         }
-        return new FloodFillChunkCache(membersToFloodFill, document.StructureRoot);
+        return new FloodFillChunkCache(membersToFloodFill, document.StructureRoot, frame);
     }
     }
 
 
     public static Dictionary<VecI, Chunk> FloodFill(
     public static Dictionary<VecI, Chunk> FloodFill(
@@ -39,14 +39,15 @@ public static class FloodFillHelper
         IReadOnlyDocument document,
         IReadOnlyDocument document,
         VectorPath? selection,
         VectorPath? selection,
         VecI startingPos,
         VecI startingPos,
-        Color drawingColor)
+        Color drawingColor,
+        int frame)
     {
     {
         if (selection is not null && !selection.Contains(startingPos.X + 0.5f, startingPos.Y + 0.5f))
         if (selection is not null && !selection.Contains(startingPos.X + 0.5f, startingPos.Y + 0.5f))
             return new();
             return new();
 
 
         int chunkSize = ChunkResolution.Full.PixelSize();
         int chunkSize = ChunkResolution.Full.PixelSize();
 
 
-        FloodFillChunkCache cache = CreateCache(membersToFloodFill, document);
+        FloodFillChunkCache cache = CreateCache(membersToFloodFill, document, frame);
 
 
         VecI initChunkPos = OperationHelper.GetChunkPos(startingPos, chunkSize);
         VecI initChunkPos = OperationHelper.GetChunkPos(startingPos, chunkSize);
         VecI imageSizeInChunks = (VecI)(document.Size / (double)chunkSize).Ceiling();
         VecI imageSizeInChunks = (VecI)(document.Size / (double)chunkSize).Ceiling();

+ 6 - 4
src/PixiEditor.ChangeableDocument/Changes/Drawing/FloodFill/FloodFill_Change.cs

@@ -13,15 +13,17 @@ internal class FloodFill_Change : Change
     private readonly bool referenceAll;
     private readonly bool referenceAll;
     private readonly bool drawOnMask;
     private readonly bool drawOnMask;
     private CommittedChunkStorage? chunkStorage = null;
     private CommittedChunkStorage? chunkStorage = null;
+    private int frame;
 
 
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
-    public FloodFill_Change(Guid memberGuid, VecI pos, Color color, bool referenceAll, bool drawOnMask)
+    public FloodFill_Change(Guid memberGuid, VecI pos, Color color, bool referenceAll, bool drawOnMask, int frame)
     {
     {
         this.memberGuid = memberGuid;
         this.memberGuid = memberGuid;
         this.pos = pos;
         this.pos = pos;
         this.color = color;
         this.color = color;
         this.referenceAll = referenceAll;
         this.referenceAll = referenceAll;
         this.drawOnMask = drawOnMask;
         this.drawOnMask = drawOnMask;
+        this.frame = frame;
     }
     }
 
 
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
@@ -34,7 +36,7 @@ internal class FloodFill_Change : Change
 
 
     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 image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
 
 
         VectorPath? selection = target.Selection.SelectionPath.IsEmpty ? null : target.Selection.SelectionPath;
         VectorPath? selection = target.Selection.SelectionPath.IsEmpty ? null : target.Selection.SelectionPath;
         HashSet<Guid> membersToReference = new();
         HashSet<Guid> membersToReference = new();
@@ -42,7 +44,7 @@ internal class FloodFill_Change : Change
             target.ForEveryReadonlyMember(member => membersToReference.Add(member.GuidValue));
             target.ForEveryReadonlyMember(member => membersToReference.Add(member.GuidValue));
         else
         else
             membersToReference.Add(memberGuid);
             membersToReference.Add(memberGuid);
-        var floodFilledChunks = FloodFillHelper.FloodFill(membersToReference, target, selection, pos, color);
+        var floodFilledChunks = FloodFillHelper.FloodFill(membersToReference, target, selection, pos, color, frame);
         if (floodFilledChunks.Count == 0)
         if (floodFilledChunks.Count == 0)
         {
         {
             ignoreInUndo = true;
             ignoreInUndo = true;
@@ -65,7 +67,7 @@ internal class FloodFill_Change : Change
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
     {
-        var affArea = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, ref chunkStorage);
+        var affArea = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, frame, ref chunkStorage);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, affArea, drawOnMask);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, affArea, drawOnMask);
     }
     }
 
 

+ 9 - 6
src/PixiEditor.ChangeableDocument/Changes/Drawing/LineBasedPen_UpdateableChange.cs

@@ -16,9 +16,11 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
 
 
     private CommittedChunkStorage? storedChunks;
     private CommittedChunkStorage? storedChunks;
     private readonly List<VecI> points = new();
     private readonly List<VecI> points = new();
+    private int frame;
 
 
     [GenerateUpdateableChangeActions]
     [GenerateUpdateableChangeActions]
-    public LineBasedPen_UpdateableChange(Guid memberGuid, Color color, VecI pos, int strokeWidth, bool replacing, bool drawOnMask)
+    public LineBasedPen_UpdateableChange(Guid memberGuid, Color color, VecI pos, int strokeWidth, bool replacing,
+        bool drawOnMask, int frame)
     {
     {
         this.memberGuid = memberGuid;
         this.memberGuid = memberGuid;
         this.color = color;
         this.color = color;
@@ -26,7 +28,8 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
         this.replacing = replacing;
         this.replacing = replacing;
         this.drawOnMask = drawOnMask;
         this.drawOnMask = drawOnMask;
         points.Add(pos);
         points.Add(pos);
-    }
+        this.frame = frame;
+}
 
 
     [UpdateChangeMethod]
     [UpdateChangeMethod]
     public void Update(VecI pos)
     public void Update(VecI pos)
@@ -40,7 +43,7 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
             return false;
             return false;
         if (strokeWidth < 1)
         if (strokeWidth < 1)
             return false;
             return false;
-        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
         if (!replacing)
         if (!replacing)
             image.SetBlendMode(BlendMode.SrcOver);
             image.SetBlendMode(BlendMode.SrcOver);
         DrawingChangeHelper.ApplyClipsSymmetriesEtc(target, image, memberGuid, drawOnMask);
         DrawingChangeHelper.ApplyClipsSymmetriesEtc(target, image, memberGuid, drawOnMask);
@@ -49,7 +52,7 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     {
     {
-        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
 
 
         var (from, to) = points.Count > 1 ? (points[^2], points[^1]) : (points[0], points[0]);
         var (from, to) = points.Count > 1 ? (points[^2], points[^1]) : (points[0], points[0]);
 
 
@@ -108,7 +111,7 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
     {
     {
         if (storedChunks is not null)
         if (storedChunks is not null)
             throw new InvalidOperationException("Trying to save chunks while there are saved chunks already");
             throw new InvalidOperationException("Trying to save chunks while there are saved chunks already");
-        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
 
 
         ignoreInUndo = false;
         ignoreInUndo = false;
         if (firstApply)
         if (firstApply)
@@ -136,7 +139,7 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
     {
-        var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, ref storedChunks);
+        var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, frame, ref storedChunks);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, affected, drawOnMask);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, affected, drawOnMask);
     }
     }
 
 

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

@@ -11,12 +11,13 @@ internal class PasteImage_UpdateableChange : UpdateableChange
     private readonly bool drawOnMask;
     private readonly bool drawOnMask;
     private readonly Surface imageToPaste;
     private readonly Surface imageToPaste;
     private CommittedChunkStorage? savedChunks;
     private CommittedChunkStorage? savedChunks;
+    private int frame;
     private static Paint RegularPaint { get; } = new Paint() { BlendMode = BlendMode.SrcOver };
     private static Paint RegularPaint { get; } = new Paint() { BlendMode = BlendMode.SrcOver };
 
 
     private bool hasEnqueudImage = false;
     private bool hasEnqueudImage = false;
 
 
     [GenerateUpdateableChangeActions]
     [GenerateUpdateableChangeActions]
-    public PasteImage_UpdateableChange(Surface image, ShapeCorners corners, Guid memberGuid, bool ignoreClipsSymmetriesEtc, bool isDrawingOnMask)
+    public PasteImage_UpdateableChange(Surface image, ShapeCorners corners, Guid memberGuid, bool ignoreClipsSymmetriesEtc, bool isDrawingOnMask, int frame)
     {
     {
         this.corners = corners;
         this.corners = corners;
         this.memberGuid = memberGuid;
         this.memberGuid = memberGuid;
@@ -53,7 +54,7 @@ internal class PasteImage_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)
     {
     {
-        ChunkyImage targetImage = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        ChunkyImage targetImage = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
         var chunks = DrawImage(target, targetImage);
         var chunks = DrawImage(target, targetImage);
         savedChunks?.Dispose();
         savedChunks?.Dispose();
         savedChunks = new(targetImage, targetImage.FindAffectedArea().Chunks);
         savedChunks = new(targetImage, targetImage.FindAffectedArea().Chunks);
@@ -65,13 +66,13 @@ internal class PasteImage_UpdateableChange : UpdateableChange
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     {
     {
-        ChunkyImage targetImage = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        ChunkyImage targetImage = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, DrawImage(target, targetImage), drawOnMask);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, DrawImage(target, targetImage), drawOnMask);
     }
     }
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
     {
-        var chunks = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, ref savedChunks);
+        var chunks = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, frame, ref savedChunks);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, chunks, drawOnMask);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, chunks, drawOnMask);
     }
     }
 
 

+ 7 - 5
src/PixiEditor.ChangeableDocument/Changes/Drawing/PathBasedPen_UpdateableChange.cs

@@ -16,15 +16,17 @@ internal class PathBasedPen_UpdateableChange : UpdateableChange
     private VectorPath tempPath = new();
     private VectorPath tempPath = new();
 
 
     private List<VecD> points = new();
     private List<VecD> points = new();
+    private int frame;
 
 
     [GenerateUpdateableChangeActions]
     [GenerateUpdateableChangeActions]
-    public PathBasedPen_UpdateableChange(Guid memberGuid, VecD pos, Color color, float strokeWidth, bool drawOnMask)
+    public PathBasedPen_UpdateableChange(Guid memberGuid, VecD pos, Color color, float strokeWidth, bool drawOnMask, int frame)
     {
     {
         this.memberGuid = memberGuid;
         this.memberGuid = memberGuid;
         this.color = color;
         this.color = color;
         this.strokeWidth = strokeWidth;
         this.strokeWidth = strokeWidth;
         this.drawOnMask = drawOnMask;
         this.drawOnMask = drawOnMask;
         points.Add(pos);
         points.Add(pos);
+        this.frame = frame;
     }
     }
 
 
     [UpdateChangeMethod]
     [UpdateChangeMethod]
@@ -37,7 +39,7 @@ internal class PathBasedPen_UpdateableChange : UpdateableChange
     {
     {
         if (!DrawingChangeHelper.IsValidForDrawing(target, memberGuid, drawOnMask))
         if (!DrawingChangeHelper.IsValidForDrawing(target, memberGuid, drawOnMask))
             return false;
             return false;
-        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
         image.SetBlendMode(BlendMode.SrcOver);
         image.SetBlendMode(BlendMode.SrcOver);
         DrawingChangeHelper.ApplyClipsSymmetriesEtc(target, image, memberGuid, drawOnMask);
         DrawingChangeHelper.ApplyClipsSymmetriesEtc(target, image, memberGuid, drawOnMask);
         return true;
         return true;
@@ -104,7 +106,7 @@ internal class PathBasedPen_UpdateableChange : UpdateableChange
     {
     {
         if (storedChunks is not null)
         if (storedChunks is not null)
             throw new InvalidOperationException("Trying to save chunks while there are saved chunks already");
             throw new InvalidOperationException("Trying to save chunks while there are saved chunks already");
-        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
 
 
         ignoreInUndo = false;
         ignoreInUndo = false;
         if (firstApply)
         if (firstApply)
@@ -135,7 +137,7 @@ internal class PathBasedPen_UpdateableChange : UpdateableChange
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     {
     {
         UpdateTempPath(points.Count);
         UpdateTempPath(points.Count);
-        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
 
 
         int opCount = image.QueueLength;
         int opCount = image.QueueLength;
         image.EnqueueDrawPath(tempPath, color, strokeWidth, StrokeCap.Round, BlendMode.Src);
         image.EnqueueDrawPath(tempPath, color, strokeWidth, StrokeCap.Round, BlendMode.Src);
@@ -146,7 +148,7 @@ internal class PathBasedPen_UpdateableChange : UpdateableChange
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
     {
-        var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, ref storedChunks);
+        var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, frame, ref storedChunks);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, affected, drawOnMask);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, affected, drawOnMask);
     }
     }
 
 

+ 7 - 5
src/PixiEditor.ChangeableDocument/Changes/Drawing/PixelPerfectPen_UpdateableChange.cs

@@ -16,13 +16,15 @@ internal class PixelPerfectPen_UpdateableChange : UpdateableChange
     private HashSet<VecI> pixelsToConfirm2 = new();
     private HashSet<VecI> pixelsToConfirm2 = new();
     private List<VecI>? incomingPoints = new();
     private List<VecI>? incomingPoints = new();
     private CommittedChunkStorage? chunkStorage;
     private CommittedChunkStorage? chunkStorage;
+    private int frame;
 
 
     [GenerateUpdateableChangeActions]
     [GenerateUpdateableChangeActions]
-    public PixelPerfectPen_UpdateableChange(Guid memberGuid, VecI pos, Color color, bool drawOnMask)
+    public PixelPerfectPen_UpdateableChange(Guid memberGuid, VecI pos, Color color, bool drawOnMask, int frame)
     {
     {
         this.memberGuid = memberGuid;
         this.memberGuid = memberGuid;
         this.color = color;
         this.color = color;
         this.drawOnMask = drawOnMask;
         this.drawOnMask = drawOnMask;
+        this.frame = frame;
     }
     }
 
 
     [UpdateChangeMethod]
     [UpdateChangeMethod]
@@ -35,7 +37,7 @@ internal class PixelPerfectPen_UpdateableChange : UpdateableChange
     {
     {
         if (!DrawingChangeHelper.IsValidForDrawing(target, memberGuid, drawOnMask))
         if (!DrawingChangeHelper.IsValidForDrawing(target, memberGuid, drawOnMask))
             return false;
             return false;
-        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
         image.SetBlendMode(BlendMode.SrcOver);
         image.SetBlendMode(BlendMode.SrcOver);
         DrawingChangeHelper.ApplyClipsSymmetriesEtc(target, image, memberGuid, drawOnMask);
         DrawingChangeHelper.ApplyClipsSymmetriesEtc(target, image, memberGuid, drawOnMask);
         return true;
         return true;
@@ -90,7 +92,7 @@ internal class PixelPerfectPen_UpdateableChange : UpdateableChange
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     {
     {
-        ChunkyImage image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        ChunkyImage image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
 
 
         int changeCount = image.QueueLength;
         int changeCount = image.QueueLength;
         DoDrawingIteration(image, incomingPoints!.Count);
         DoDrawingIteration(image, incomingPoints!.Count);
@@ -104,7 +106,7 @@ internal class PixelPerfectPen_UpdateableChange : UpdateableChange
             throw new InvalidOperationException("Trying to save chunks while a saved one already exist");
             throw new InvalidOperationException("Trying to save chunks while a saved one already exist");
 
 
         ignoreInUndo = false;
         ignoreInUndo = false;
-        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask, frame);
         if (firstApply)
         if (firstApply)
         {
         {
             incomingPoints = null;
             incomingPoints = null;
@@ -126,7 +128,7 @@ internal class PixelPerfectPen_UpdateableChange : UpdateableChange
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
     {
-        var chunks = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, ref chunkStorage);
+        var chunks = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, memberGuid, drawOnMask, frame, ref chunkStorage);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, chunks, drawOnMask);
         return DrawingChangeHelper.CreateAreaChangeInfo(memberGuid, chunks, drawOnMask);
     }
     }
 }
 }

+ 10 - 7
src/PixiEditor.ChangeableDocument/Changes/Drawing/ReplaceColor_Change.cs

@@ -8,14 +8,16 @@ internal class ReplaceColor_Change : Change
     private readonly Color newColor;
     private readonly Color newColor;
 
 
     private Dictionary<Guid, CommittedChunkStorage>? savedChunks;
     private Dictionary<Guid, CommittedChunkStorage>? savedChunks;
+    private int frame;
 
 
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
-    public ReplaceColor_Change(Color oldColor, Color newColor)
+    public ReplaceColor_Change(Color oldColor, Color newColor, int frame)
     {
     {
         this.oldColor = oldColor;
         this.oldColor = oldColor;
         this.newColor = newColor;
         this.newColor = newColor;
+        this.frame = frame;
     }
     }
-
+   
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
     {
     {
         return true;
         return true;
@@ -32,11 +34,12 @@ internal class ReplaceColor_Change : Change
             if (member is not RasterLayer layer)
             if (member is not RasterLayer layer)
                 return;
                 return;
             //TODO: Add support for replacing in different Layer types
             //TODO: Add support for replacing in different Layer types
-            layer.LayerImage.EnqueueReplaceColor(oldColor, newColor);
-            var affArea = layer.LayerImage.FindAffectedArea();
-            CommittedChunkStorage storage = new(layer.LayerImage, affArea.Chunks);
+            var layerImage = layer.GetLayerImageAtFrame(frame);
+            layerImage.EnqueueReplaceColor(oldColor, newColor);
+            var affArea = layerImage.FindAffectedArea();
+            CommittedChunkStorage storage = new(layerImage, affArea.Chunks);
             savedChunks[layer.GuidValue] = storage;
             savedChunks[layer.GuidValue] = storage;
-            layer.LayerImage.CommitChanges();
+            layerImage.CommitChanges();
             infos.Add(new LayerImageArea_ChangeInfo(layer.GuidValue, affArea));
             infos.Add(new LayerImageArea_ChangeInfo(layer.GuidValue, affArea));
         });
         });
         ignoreInUndo = !savedChunks.Any();
         ignoreInUndo = !savedChunks.Any();
@@ -53,7 +56,7 @@ internal class ReplaceColor_Change : Change
             if (member is not RasterLayer layer)
             if (member is not RasterLayer layer)
                 return;
                 return;
             CommittedChunkStorage? storage = savedChunks[member.GuidValue];
             CommittedChunkStorage? storage = savedChunks[member.GuidValue];
-            var affArea = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(layer.LayerImage, ref storage);
+            var affArea = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(layer.GetLayerImageAtFrame(frame), ref storage);
             infos.Add(new LayerImageArea_ChangeInfo(layer.GuidValue, affArea));
             infos.Add(new LayerImageArea_ChangeInfo(layer.GuidValue, affArea));
         });
         });
         savedChunks = null;
         savedChunks = null;

+ 5 - 3
src/PixiEditor.ChangeableDocument/Changes/Drawing/SelectionToMask_Change.cs

@@ -16,12 +16,14 @@ internal class SelectionToMask_Change : Change
     private readonly Guid targetMember;
     private readonly Guid targetMember;
     private Changeables.Selection? selection;
     private Changeables.Selection? selection;
     private CommittedChunkStorage? chunkStorage = null;
     private CommittedChunkStorage? chunkStorage = null;
+    private int frame;
     
     
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
-    public SelectionToMask_Change(Guid targetMember, SelectionMode mode)
+    public SelectionToMask_Change(Guid targetMember, SelectionMode mode, int frame)
     {
     {
         this.targetMember = targetMember;
         this.targetMember = targetMember;
         this.mode = mode;
         this.mode = mode;
+        this.frame = frame;
     }
     }
     
     
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
@@ -32,7 +34,7 @@ internal class SelectionToMask_Change : Change
 
 
     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 image = DrawingChangeHelper.GetTargetImageOrThrow(target, targetMember, true);
+        var image = DrawingChangeHelper.GetTargetImageOrThrow(target, targetMember, true, frame);
         
         
         VectorPath? selection = target.Selection.SelectionPath.IsEmpty ? null : target.Selection.SelectionPath;
         VectorPath? selection = target.Selection.SelectionPath.IsEmpty ? null : target.Selection.SelectionPath;
         HashSet<Guid> membersToReference = new();
         HashSet<Guid> membersToReference = new();
@@ -62,7 +64,7 @@ internal class SelectionToMask_Change : Change
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
     {
-        var affArea = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, targetMember, true, ref chunkStorage);
+        var affArea = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, targetMember, true, frame, ref chunkStorage);
         return DrawingChangeHelper.CreateAreaChangeInfo(targetMember, affArea, true);
         return DrawingChangeHelper.CreateAreaChangeInfo(targetMember, affArea, true);
     }
     }
 }
 }

+ 2 - 2
src/PixiEditor.ChangeableDocument/Changes/Drawing/ShiftLayerHelper.cs

@@ -5,9 +5,9 @@ namespace PixiEditor.ChangeableDocument.Changes.Drawing;
 
 
 internal static class ShiftLayerHelper
 internal static class ShiftLayerHelper
 {
 {
-    public static AffectedArea DrawShiftedLayer(Document target, Guid layerGuid, bool keepOriginal, VecI delta)
+    public static AffectedArea DrawShiftedLayer(Document target, Guid layerGuid, bool keepOriginal, VecI delta, int frame)
     {
     {
-        var targetImage = target.FindMemberOrThrow<RasterLayer>(layerGuid).LayerImage;
+        var targetImage = target.FindMemberOrThrow<RasterLayer>(layerGuid).GetLayerImageAtFrame(frame);
         var prevArea = targetImage.FindAffectedArea();
         var prevArea = targetImage.FindAffectedArea();
         targetImage.CancelChanges();
         targetImage.CancelChanges();
         if (!keepOriginal)
         if (!keepOriginal)

+ 7 - 5
src/PixiEditor.ChangeableDocument/Changes/Drawing/ShiftLayer_UpdateableChange.cs

@@ -11,13 +11,15 @@ internal class ShiftLayer_UpdateableChange : UpdateableChange
     private Dictionary<Guid, CommittedChunkStorage?> originalLayerChunks = new();
     private Dictionary<Guid, CommittedChunkStorage?> originalLayerChunks = new();
     
     
     private List<IChangeInfo> _tempChanges = new();
     private List<IChangeInfo> _tempChanges = new();
+    private int frame;
 
 
     [GenerateUpdateableChangeActions]
     [GenerateUpdateableChangeActions]
-    public ShiftLayer_UpdateableChange(List<Guid> layerGuids, VecI delta, bool keepOriginal)
+    public ShiftLayer_UpdateableChange(List<Guid> layerGuids, VecI delta, bool keepOriginal, int frame)
     {
     {
         this.delta = delta;
         this.delta = delta;
         this.layerGuids = layerGuids;
         this.layerGuids = layerGuids;
         this.keepOriginal = keepOriginal;
         this.keepOriginal = keepOriginal;
+        this.frame = frame;
     }
     }
 
 
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
@@ -50,9 +52,9 @@ internal class ShiftLayer_UpdateableChange : UpdateableChange
         List<IChangeInfo> changes = new List<IChangeInfo>();
         List<IChangeInfo> changes = new List<IChangeInfo>();
         foreach (var layerGuid in layerGuids)
         foreach (var layerGuid in layerGuids)
         {
         {
-            var area = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, keepOriginal, delta);
+            var area = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, keepOriginal, delta, frame);
             // TODO: Add support for different Layer types
             // TODO: Add support for different Layer types
-            var image = target.FindMemberOrThrow<RasterLayer>(layerGuid).LayerImage;
+            var image = target.FindMemberOrThrow<RasterLayer>(layerGuid).GetLayerImageAtFrame(frame);
             
             
             changes.Add(new LayerImageArea_ChangeInfo(layerGuid, area));
             changes.Add(new LayerImageArea_ChangeInfo(layerGuid, area));
             
             
@@ -70,7 +72,7 @@ internal class ShiftLayer_UpdateableChange : UpdateableChange
 
 
         foreach (var layerGuid in layerGuids)
         foreach (var layerGuid in layerGuids)
         {
         {
-            var chunks = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, keepOriginal, delta);
+            var chunks = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, keepOriginal, delta, frame);
             _tempChanges.Add(new LayerImageArea_ChangeInfo(layerGuid, chunks));
             _tempChanges.Add(new LayerImageArea_ChangeInfo(layerGuid, chunks));
         }
         }
         
         
@@ -82,7 +84,7 @@ internal class ShiftLayer_UpdateableChange : UpdateableChange
         List<IChangeInfo> changes = new List<IChangeInfo>();
         List<IChangeInfo> changes = new List<IChangeInfo>();
         foreach (var layerGuid in layerGuids)
         foreach (var layerGuid in layerGuids)
         {
         {
-            var image = target.FindMemberOrThrow<RasterLayer>(layerGuid).LayerImage;
+            var image = target.FindMemberOrThrow<RasterLayer>(layerGuid).GetLayerImageAtFrame(frame);
             CommittedChunkStorage? originalChunks = originalLayerChunks[layerGuid];
             CommittedChunkStorage? originalChunks = originalLayerChunks[layerGuid];
             var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(image, ref originalChunks);
             var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(image, ref originalChunks);
             changes.Add(new LayerImageArea_ChangeInfo(layerGuid, affected));
             changes.Add(new LayerImageArea_ChangeInfo(layerGuid, affected));

+ 8 - 5
src/PixiEditor.ChangeableDocument/Changes/Drawing/TransformSelectedArea_UpdateableChange.cs

@@ -23,6 +23,7 @@ internal class TransformSelectedArea_UpdateableChange : UpdateableChange
     private VectorPath? originalPath;
     private VectorPath? originalPath;
 
 
     private bool hasEnqueudImages = false;
     private bool hasEnqueudImages = false;
+    private int frame;
 
 
     private static Paint RegularPaint { get; } = new () { BlendMode = BlendMode.SrcOver };
     private static Paint RegularPaint { get; } = new () { BlendMode = BlendMode.SrcOver };
 
 
@@ -31,12 +32,14 @@ internal class TransformSelectedArea_UpdateableChange : UpdateableChange
         IEnumerable<Guid> membersToTransform,
         IEnumerable<Guid> membersToTransform,
         ShapeCorners corners,
         ShapeCorners corners,
         bool keepOriginal,
         bool keepOriginal,
-        bool transformMask)
+        bool transformMask,
+        int frame)
     {
     {
         this.membersToTransform = membersToTransform.Select(static a => a).ToArray();
         this.membersToTransform = membersToTransform.Select(static a => a).ToArray();
         this.corners = corners;
         this.corners = corners;
         this.keepOriginal = keepOriginal;
         this.keepOriginal = keepOriginal;
         this.drawOnMask = transformMask;
         this.drawOnMask = transformMask;
+        this.frame = frame;
     }
     }
 
 
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
@@ -59,7 +62,7 @@ internal class TransformSelectedArea_UpdateableChange : UpdateableChange
         images = new();
         images = new();
         foreach (var guid in membersToTransform)
         foreach (var guid in membersToTransform)
         {
         {
-            ChunkyImage image = DrawingChangeHelper.GetTargetImageOrThrow(target, guid, drawOnMask);
+            ChunkyImage image = DrawingChangeHelper.GetTargetImageOrThrow(target, guid, drawOnMask, frame);
             var extracted = ExtractArea(image, originalPath, roundedTightBounds);
             var extracted = ExtractArea(image, originalPath, roundedTightBounds);
             if (extracted.IsT0)
             if (extracted.IsT0)
                 continue;
                 continue;
@@ -130,7 +133,7 @@ internal class TransformSelectedArea_UpdateableChange : UpdateableChange
         List<IChangeInfo> infos = new();
         List<IChangeInfo> infos = new();
         foreach (var (guid, (image, pos)) in images!)
         foreach (var (guid, (image, pos)) in images!)
         {
         {
-            ChunkyImage memberImage = DrawingChangeHelper.GetTargetImageOrThrow(target, guid, drawOnMask);
+            ChunkyImage memberImage = DrawingChangeHelper.GetTargetImageOrThrow(target, guid, drawOnMask, frame);
             var area = DrawImage(target, guid, image, pos, memberImage);
             var area = DrawImage(target, guid, image, pos, memberImage);
             savedChunks[guid] = new(memberImage, memberImage.FindAffectedArea().Chunks);
             savedChunks[guid] = new(memberImage, memberImage.FindAffectedArea().Chunks);
             memberImage.CommitChanges();
             memberImage.CommitChanges();
@@ -149,7 +152,7 @@ internal class TransformSelectedArea_UpdateableChange : UpdateableChange
         List<IChangeInfo> infos = new();
         List<IChangeInfo> infos = new();
         foreach (var (guid, (image, pos)) in images!)
         foreach (var (guid, (image, pos)) in images!)
         {
         {
-            ChunkyImage targetImage = DrawingChangeHelper.GetTargetImageOrThrow(target, guid, drawOnMask);
+            ChunkyImage targetImage = DrawingChangeHelper.GetTargetImageOrThrow(target, guid, drawOnMask, frame);
             infos.Add(DrawingChangeHelper.CreateAreaChangeInfo(guid, DrawImage(target, guid, image, pos, targetImage), drawOnMask).AsT1);
             infos.Add(DrawingChangeHelper.CreateAreaChangeInfo(guid, DrawImage(target, guid, image, pos, targetImage), drawOnMask).AsT1);
         }
         }
         infos.Add(SelectionChangeHelper.DoSelectionTransform(target, originalPath!, originalTightBounds, corners));
         infos.Add(SelectionChangeHelper.DoSelectionTransform(target, originalPath!, originalTightBounds, corners));
@@ -162,7 +165,7 @@ internal class TransformSelectedArea_UpdateableChange : UpdateableChange
         foreach (var (guid, storage) in savedChunks!)
         foreach (var (guid, storage) in savedChunks!)
         {
         {
             var storageCopy = storage;
             var storageCopy = storage;
-            var chunks = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, guid, drawOnMask, ref storageCopy);
+            var chunks = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, guid, drawOnMask, frame, ref storageCopy);
             infos.Add(DrawingChangeHelper.CreateAreaChangeInfo(guid, chunks, drawOnMask).AsT1);
             infos.Add(DrawingChangeHelper.CreateAreaChangeInfo(guid, chunks, drawOnMask).AsT1);
         }
         }
 
 

+ 9 - 6
src/PixiEditor.ChangeableDocument/Changes/Root/CenterContent_Change.cs

@@ -9,10 +9,12 @@ internal class CenterContent_Change : Change
     private VecI _oldOffset;
     private VecI _oldOffset;
     private List<Guid> affectedLayers;
     private List<Guid> affectedLayers;
     private Dictionary<Guid, CommittedChunkStorage>? originalLayerChunks;
     private Dictionary<Guid, CommittedChunkStorage>? originalLayerChunks;
+    private int frame;
 
 
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
-    public CenterContent_Change(List<Guid> layers)
+    public CenterContent_Change(List<Guid> layers, int frame)
     {
     {
+        this.frame = frame;
         affectedLayers = layers;
         affectedLayers = layers;
     }
     }
     
     
@@ -42,7 +44,7 @@ internal class CenterContent_Change : Change
         foreach (var layerGuid in affectedLayers)
         foreach (var layerGuid in affectedLayers)
         {
         {
             Layer layer = document.FindMemberOrThrow<Layer>(layerGuid);
             Layer layer = document.FindMemberOrThrow<Layer>(layerGuid);
-            RectI? tightBounds = layer.GetTightBounds();
+            RectI? tightBounds = layer.GetTightBounds(frame);
             if (tightBounds.HasValue)
             if (tightBounds.HasValue)
             {
             {
                 currentBounds = currentBounds.HasValue ? currentBounds.Value.Union(tightBounds.Value) : tightBounds;
                 currentBounds = currentBounds.HasValue ? currentBounds.Value.Union(tightBounds.Value) : tightBounds;
@@ -68,13 +70,14 @@ internal class CenterContent_Change : Change
         foreach (var layerGuid in affectedLayers)
         foreach (var layerGuid in affectedLayers)
         {
         {
             RasterLayer layer = target.FindMemberOrThrow<RasterLayer>(layerGuid);
             RasterLayer layer = target.FindMemberOrThrow<RasterLayer>(layerGuid);
-            var chunks = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, false, shift);
+            var chunks = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, false, shift, frame);
             changes.Add(new LayerImageArea_ChangeInfo(layerGuid, chunks));
             changes.Add(new LayerImageArea_ChangeInfo(layerGuid, chunks));
 
 
             // TODO: Adding support for non-raster layer should be easy, add
             // TODO: Adding support for non-raster layer should be easy, add
             
             
-            originalLayerChunks[layerGuid] = new CommittedChunkStorage(layer.LayerImage, layer.LayerImage.FindAffectedArea().Chunks);
-            layer.LayerImage.CommitChanges();
+            var image = layer.GetLayerImageAtFrame(frame);
+            originalLayerChunks[layerGuid] = new CommittedChunkStorage(image, image.FindAffectedArea().Chunks);
+            image.CommitChanges();
         }
         }
 
 
         ignoreInUndo = shift.TaxicabLength == 0;
         ignoreInUndo = shift.TaxicabLength == 0;
@@ -86,7 +89,7 @@ internal class CenterContent_Change : Change
         List<IChangeInfo> changes = new List<IChangeInfo>();
         List<IChangeInfo> changes = new List<IChangeInfo>();
         foreach (var layerGuid in affectedLayers)
         foreach (var layerGuid in affectedLayers)
         {
         {
-            var image = target.FindMemberOrThrow<RasterLayer>(layerGuid).LayerImage;
+            var image = target.FindMemberOrThrow<RasterLayer>(layerGuid).GetLayerImageAtFrame(frame);
             CommittedChunkStorage? originalChunks = originalLayerChunks?[layerGuid];
             CommittedChunkStorage? originalChunks = originalLayerChunks?[layerGuid];
             var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(image, ref originalChunks);
             var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(image, ref originalChunks);
             changes.Add(new LayerImageArea_ChangeInfo(layerGuid, affected));
             changes.Add(new LayerImageArea_ChangeInfo(layerGuid, affected));

+ 5 - 3
src/PixiEditor.ChangeableDocument/Changes/Root/ClipCanvas_Change.cs

@@ -7,7 +7,9 @@ namespace PixiEditor.ChangeableDocument.Changes.Root;
 internal class ClipCanvas_Change : ResizeBasedChangeBase
 internal class ClipCanvas_Change : ResizeBasedChangeBase
 {
 {
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
-    public ClipCanvas_Change() { }
+    public ClipCanvas_Change(int frame) : base(frame)
+    {
+    }
 
 
     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)
     {
     {
@@ -16,7 +18,7 @@ internal class ClipCanvas_Change : ResizeBasedChangeBase
         {
         {
             if (member is Layer layer)
             if (member is Layer layer)
             {
             {
-                var layerBounds = layer.GetTightBounds();
+                var layerBounds = layer.GetTightBounds(frame);
                 if (layerBounds.HasValue)
                 if (layerBounds.HasValue)
                 {
                 {
                     bounds ??= layerBounds.Value;
                     bounds ??= layerBounds.Value;
@@ -41,7 +43,7 @@ internal class ClipCanvas_Change : ResizeBasedChangeBase
         {
         {
             if (member is RasterLayer layer)
             if (member is RasterLayer layer)
             {
             {
-                Resize(layer.LayerImage, layer.GuidValue, newBounds.Size, -newBounds.Pos, deletedChunks);
+                Resize(layer.GetLayerImageAtFrame(frame), layer.GuidValue, newBounds.Size, -newBounds.Pos, deletedChunks);
             }
             }
             
             
             if (member.Mask is null)
             if (member.Mask is null)

+ 3 - 2
src/PixiEditor.ChangeableDocument/Changes/Root/Crop_Change.cs

@@ -9,11 +9,12 @@ internal class Crop_Change : ResizeBasedChangeBase
     private RectI rect;
     private RectI rect;
     
     
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
-    public Crop_Change(RectI rect)
+    public Crop_Change(RectI rect, int frame) : base(frame)
     {
     {
         this.rect = rect;
         this.rect = rect;
     }
     }
 
 
+
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
     {
     {
         return base.InitializeAndValidate(target) && rect is { Width: > 0, Height: > 0 };
         return base.InitializeAndValidate(target) && rect is { Width: > 0, Height: > 0 };
@@ -35,7 +36,7 @@ internal class Crop_Change : ResizeBasedChangeBase
         {
         {
             if (member is RasterLayer layer)
             if (member is RasterLayer layer)
             {
             {
-                Resize(layer.LayerImage, layer.GuidValue, rect.Size, rect.Pos * -1, deletedChunks);
+                Resize(layer.GetLayerImageAtFrame(frame), layer.GuidValue, rect.Size, rect.Pos * -1, deletedChunks);
             }
             }
             if (member.Mask is null)
             if (member.Mask is null)
                 return;
                 return;

+ 7 - 4
src/PixiEditor.ChangeableDocument/Changes/Root/FlipImage_Change.cs

@@ -13,12 +13,14 @@ internal sealed class FlipImage_Change : Change
 {
 {
     private readonly FlipType flipType;
     private readonly FlipType flipType;
     private List<Guid> membersToFlip;
     private List<Guid> membersToFlip;
+    private int frame;
 
 
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
-    public FlipImage_Change(FlipType flipType, List<Guid>? membersToFlip = null)
+    public FlipImage_Change(FlipType flipType, int frame, List<Guid>? membersToFlip = null)
     {
     {
         this.flipType = flipType;
         this.flipType = flipType;
         membersToFlip ??= new List<Guid>();
         membersToFlip ??= new List<Guid>();
+        this.frame = frame;
         this.membersToFlip = membersToFlip;
         this.membersToFlip = membersToFlip;
     }
     }
     
     
@@ -102,10 +104,11 @@ internal sealed class FlipImage_Change : Change
             {
             {
                 if (member is RasterLayer layer)
                 if (member is RasterLayer layer)
                 {
                 {
-                    FlipImage(layer.LayerImage);
+                    var image = layer.GetLayerImageAtFrame(frame);
+                    FlipImage(image);
                     changes.Add(
                     changes.Add(
-                        new LayerImageArea_ChangeInfo(member.GuidValue, layer.LayerImage.FindAffectedArea()));
-                    layer.LayerImage.CommitChanges();
+                        new LayerImageArea_ChangeInfo(member.GuidValue, image.FindAffectedArea()));
+                    image.CommitChanges();
                 }
                 }
                 // TODO: Add support for non-raster layers
                 // TODO: Add support for non-raster layers
 
 

+ 10 - 3
src/PixiEditor.ChangeableDocument/Changes/Root/ResizeBasedChangeBase.cs

@@ -11,6 +11,12 @@ internal abstract class ResizeBasedChangeBase : Change
     protected double _originalVerAxisX;
     protected double _originalVerAxisX;
     protected Dictionary<Guid, CommittedChunkStorage> deletedChunks = new();
     protected Dictionary<Guid, CommittedChunkStorage> deletedChunks = new();
     protected Dictionary<Guid, CommittedChunkStorage> deletedMaskChunks = new();
     protected Dictionary<Guid, CommittedChunkStorage> deletedMaskChunks = new();
+    protected int frame;
+    
+    public ResizeBasedChangeBase(int frame)
+    {
+        this.frame = frame;
+    }
     
     
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
     {
     {
@@ -40,9 +46,10 @@ internal abstract class ResizeBasedChangeBase : Change
         {
         {
             if (member is RasterLayer layer)
             if (member is RasterLayer layer)
             {
             {
-                layer.LayerImage.EnqueueResize(_originalSize);
-                deletedChunks[layer.GuidValue].ApplyChunksToImage(layer.LayerImage);
-                layer.LayerImage.CommitChanges();
+                var layerImage = layer.GetLayerImageAtFrame(frame);
+                layerImage.EnqueueResize(_originalSize);
+                deletedChunks[layer.GuidValue].ApplyChunksToImage(layerImage);
+                layerImage.CommitChanges();
             }
             }
 
 
             // TODO: Add support for different Layer types?
             // TODO: Add support for different Layer types?

+ 2 - 2
src/PixiEditor.ChangeableDocument/Changes/Root/ResizeCanvas_Change.cs

@@ -11,7 +11,7 @@ internal class ResizeCanvas_Change : ResizeBasedChangeBase
     private readonly ResizeAnchor anchor;
     private readonly ResizeAnchor anchor;
 
 
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
-    public ResizeCanvas_Change(VecI size, ResizeAnchor anchor)
+    public ResizeCanvas_Change(VecI size, ResizeAnchor anchor, int frame) : base(frame)
     {
     {
         newSize = size;
         newSize = size;
         this.anchor = anchor;
         this.anchor = anchor;
@@ -47,7 +47,7 @@ internal class ResizeCanvas_Change : ResizeBasedChangeBase
         {
         {
             if (member is RasterLayer layer)
             if (member is RasterLayer layer)
             {
             {
-                Resize(layer.LayerImage, layer.GuidValue, newSize, offset, deletedChunks);
+                Resize(layer.GetLayerImageAtFrame(frame), layer.GuidValue, newSize, offset, deletedChunks);
             }
             }
 
 
             // TODO: Check if adding support for different Layer types is necessary
             // TODO: Check if adding support for different Layer types is necessary

+ 13 - 9
src/PixiEditor.ChangeableDocument/Changes/Root/ResizeImage_Change.cs

@@ -15,15 +15,17 @@ internal class ResizeImage_Change : Change
     private VecI originalSize;
     private VecI originalSize;
     private double originalHorAxisY;
     private double originalHorAxisY;
     private double originalVerAxisX;
     private double originalVerAxisX;
+    private int frame;
     
     
     private Dictionary<Guid, CommittedChunkStorage> savedChunks = new();
     private Dictionary<Guid, CommittedChunkStorage> savedChunks = new();
     private Dictionary<Guid, CommittedChunkStorage> savedMaskChunks = new();
     private Dictionary<Guid, CommittedChunkStorage> savedMaskChunks = new();
 
 
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
-    public ResizeImage_Change(VecI size, ResamplingMethod method)
+    public ResizeImage_Change(VecI size, ResamplingMethod method, int frame)
     {
     {
         this.newSize = size;
         this.newSize = size;
         this.method = method;
         this.method = method;
+        this.frame = frame;
     }
     }
     
     
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
@@ -91,10 +93,11 @@ internal class ResizeImage_Change : Change
         {
         {
             if (member is RasterLayer layer)
             if (member is RasterLayer layer)
             {
             {
-                ScaleChunkyImage(layer.LayerImage);
-                var affected = layer.LayerImage.FindAffectedArea();
-                savedChunks[layer.GuidValue] = new CommittedChunkStorage(layer.LayerImage, affected.Chunks);
-                layer.LayerImage.CommitChanges();
+                var layerImage = layer.GetLayerImageAtFrame(frame);
+                ScaleChunkyImage(layerImage);
+                var affected = layerImage.FindAffectedArea();
+                savedChunks[layer.GuidValue] = new CommittedChunkStorage(layerImage, affected.Chunks);
+                layerImage.CommitChanges();
             }
             }
 
 
             // Add support for different Layer types
             // Add support for different Layer types
@@ -119,10 +122,11 @@ internal class ResizeImage_Change : Change
         {
         {
             if (member is RasterLayer layer)
             if (member is RasterLayer layer)
             {
             {
-                layer.LayerImage.EnqueueResize(originalSize);
-                layer.LayerImage.EnqueueClear();
-                savedChunks[layer.GuidValue].ApplyChunksToImage(layer.LayerImage);
-                layer.LayerImage.CommitChanges();
+                var layerImage = layer.GetLayerImageAtFrame(frame);
+                layerImage.EnqueueResize(originalSize);
+                layerImage.EnqueueClear();
+                savedChunks[layer.GuidValue].ApplyChunksToImage(layerImage);
+                layerImage.CommitChanges();
             }
             }
             
             
             if (member.Mask is not null)
             if (member.Mask is not null)

+ 11 - 8
src/PixiEditor.ChangeableDocument/Changes/Root/RotateImage_Change.cs

@@ -19,13 +19,15 @@ internal sealed class RotateImage_Change : Change
     private double originalVerAxisX;
     private double originalVerAxisX;
     private Dictionary<Guid, CommittedChunkStorage> deletedChunks = new();
     private Dictionary<Guid, CommittedChunkStorage> deletedChunks = new();
     private Dictionary<Guid, CommittedChunkStorage> deletedMaskChunks = new();
     private Dictionary<Guid, CommittedChunkStorage> deletedMaskChunks = new();
-
+    int frame;
+    
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
-    public RotateImage_Change(RotationAngle rotation, List<Guid>? membersToRotate)
+    public RotateImage_Change(RotationAngle rotation, List<Guid>? membersToRotate, int frame)
     {
     {
         this.rotation = rotation;
         this.rotation = rotation;
         membersToRotate ??= new List<Guid>();
         membersToRotate ??= new List<Guid>();
         this.membersToRotate = membersToRotate;
         this.membersToRotate = membersToRotate;
+        this.frame = frame;
     }
     }
     
     
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
@@ -142,7 +144,7 @@ internal sealed class RotateImage_Change : Change
             {
             {
                 if (member is RasterLayer layer)
                 if (member is RasterLayer layer)
                 {
                 {
-                    Resize(layer.LayerImage, layer.GuidValue, deletedChunks, changes);
+                    Resize(layer.GetLayerImageAtFrame(frame), layer.GuidValue, deletedChunks, changes);
                 }
                 }
 
 
                 // TODO: Add support for different Layer types
                 // TODO: Add support for different Layer types
@@ -175,7 +177,7 @@ internal sealed class RotateImage_Change : Change
         {
         {
             if (member is RasterLayer layer)
             if (member is RasterLayer layer)
             {
             {
-                Resize(layer.LayerImage, layer.GuidValue, deletedChunks, null);
+                Resize(layer.GetLayerImageAtFrame(frame), layer.GuidValue, deletedChunks, null);
             }
             }
 
 
             if (member.Mask is null)
             if (member.Mask is null)
@@ -216,10 +218,11 @@ internal sealed class RotateImage_Change : Change
             if(membersToRotate.Count > 0 && !membersToRotate.Contains(member.GuidValue)) return;
             if(membersToRotate.Count > 0 && !membersToRotate.Contains(member.GuidValue)) return;
             if (member is RasterLayer layer)
             if (member is RasterLayer layer)
             {
             {
-                layer.LayerImage.EnqueueResize(originalSize);
-                deletedChunks[layer.GuidValue].ApplyChunksToImage(layer.LayerImage);
-                revertChanges.Add(new LayerImageArea_ChangeInfo(layer.GuidValue, layer.LayerImage.FindAffectedArea()));
-                layer.LayerImage.CommitChanges();
+                var layerImage = layer.GetLayerImageAtFrame(frame);
+                layerImage.EnqueueResize(originalSize);
+                deletedChunks[layer.GuidValue].ApplyChunksToImage(layerImage);
+                revertChanges.Add(new LayerImageArea_ChangeInfo(layer.GuidValue, layerImage.FindAffectedArea()));
+                layerImage.CommitChanges();
             }
             }
 
 
             if (member.Mask is null)
             if (member.Mask is null)

+ 2 - 2
src/PixiEditor.ChangeableDocument/Changes/Selection/MagicWand/MagicWandHelper.cs

@@ -108,14 +108,14 @@ internal class MagicWandHelper
     }
     }
 
 
     public static VectorPath DoMagicWandFloodFill(VecI startingPos, HashSet<Guid> membersToFloodFill,
     public static VectorPath DoMagicWandFloodFill(VecI startingPos, HashSet<Guid> membersToFloodFill,
-        IReadOnlyDocument document)
+        IReadOnlyDocument document, int frame)
     {
     {
         if (startingPos.X < 0 || startingPos.Y < 0 || startingPos.X >= document.Size.X || startingPos.Y >= document.Size.Y)
         if (startingPos.X < 0 || startingPos.Y < 0 || startingPos.X >= document.Size.X || startingPos.Y >= document.Size.Y)
             return new VectorPath();
             return new VectorPath();
 
 
         int chunkSize = ChunkResolution.Full.PixelSize();
         int chunkSize = ChunkResolution.Full.PixelSize();
 
 
-        FloodFillChunkCache cache = FloodFillHelper.CreateCache(membersToFloodFill, document);
+        FloodFillChunkCache cache = FloodFillHelper.CreateCache(membersToFloodFill, document, frame);
 
 
         VecI initChunkPos = OperationHelper.GetChunkPos(startingPos, chunkSize);
         VecI initChunkPos = OperationHelper.GetChunkPos(startingPos, chunkSize);
         VecI imageSizeInChunks = (VecI)(document.Size / (double)chunkSize).Ceiling();
         VecI imageSizeInChunks = (VecI)(document.Size / (double)chunkSize).Ceiling();

+ 4 - 2
src/PixiEditor.ChangeableDocument/Changes/Selection/MagicWand/MagicWand_Change.cs

@@ -13,14 +13,16 @@ internal class MagicWand_Change : Change
     private VecI point;
     private VecI point;
     private readonly List<Guid> memberGuids;
     private readonly List<Guid> memberGuids;
     private readonly SelectionMode mode;
     private readonly SelectionMode mode;
+    private int frame;
 
 
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
-    public MagicWand_Change(List<Guid> memberGuids, VecI point, SelectionMode mode)
+    public MagicWand_Change(List<Guid> memberGuids, VecI point, SelectionMode mode, int frame)
     {
     {
         path.MoveTo(point);
         path.MoveTo(point);
         this.mode = mode;
         this.mode = mode;
         this.memberGuids = memberGuids;
         this.memberGuids = memberGuids;
         this.point = point;
         this.point = point;
+        this.frame = frame;
     }
     }
 
 
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
@@ -39,7 +41,7 @@ internal class MagicWand_Change : Change
                 membersToReference.Add(member.GuidValue);
                 membersToReference.Add(member.GuidValue);
         });
         });
 
 
-        path = MagicWandHelper.DoMagicWandFloodFill(point, membersToReference, target);
+        path = MagicWandHelper.DoMagicWandFloodFill(point, membersToReference, target, frame);
 
 
         ignoreInUndo = false;
         ignoreInUndo = false;
         return CommonApply(target);
         return CommonApply(target);

+ 15 - 9
src/PixiEditor.ChangeableDocument/Changes/Structure/ApplyMask_Change.cs

@@ -10,13 +10,15 @@ internal sealed class ApplyMask_Change : Change
     private Guid structureMemberGuid;
     private Guid structureMemberGuid;
 
 
     private CommittedChunkStorage? savedChunks;
     private CommittedChunkStorage? savedChunks;
+    private int frame;
 
 
     [GenerateMakeChangeAction]
     [GenerateMakeChangeAction]
-    public ApplyMask_Change(Guid structureMemberGuid)
+    public ApplyMask_Change(Guid structureMemberGuid, int frame)
     {
     {
         this.structureMemberGuid = structureMemberGuid;
         this.structureMemberGuid = structureMemberGuid;
+        this.frame = frame;
     }
     }
-        
+
     public override bool InitializeAndValidate(Document target)
     public override bool InitializeAndValidate(Document target)
     {
     {
         var member = target.FindMember(structureMemberGuid);
         var member = target.FindMember(structureMemberGuid);
@@ -25,21 +27,25 @@ internal sealed class ApplyMask_Change : Change
         return isValid;
         return isValid;
     }
     }
 
 
-    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 layer = target.FindMemberOrThrow<RasterLayer>(structureMemberGuid)!;
         var layer = target.FindMemberOrThrow<RasterLayer>(structureMemberGuid)!;
-        layer!.LayerImage.EnqueueApplyMask(layer.Mask!);
+        var layerImage = layer.GetLayerImageAtFrame(frame);
+        layerImage.EnqueueApplyMask(layer.Mask!);
         ignoreInUndo = false;
         ignoreInUndo = false;
-        var layerInfo = new LayerImageArea_ChangeInfo(structureMemberGuid, layer.LayerImage.FindAffectedArea());
-        savedChunks = new CommittedChunkStorage(layer.LayerImage, layerInfo.Area.Chunks);
-        
-        layer.LayerImage.CommitChanges();
+        var layerInfo = new LayerImageArea_ChangeInfo(structureMemberGuid, layerImage.FindAffectedArea());
+        savedChunks = new CommittedChunkStorage(layerImage, layerInfo.Area.Chunks);
+
+        layerImage.CommitChanges();
         return layerInfo;
         return layerInfo;
     }
     }
 
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
     {
-        var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, structureMemberGuid, false, ref savedChunks);
+        var affected =
+            DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(target, structureMemberGuid, false, frame,
+                ref savedChunks);
         return new LayerImageArea_ChangeInfo(structureMemberGuid, affected);
         return new LayerImageArea_ChangeInfo(structureMemberGuid, affected);
     }
     }
 }
 }