Browse Source

Vector ellipse wip

flabbet 11 months ago
parent
commit
6247451684
19 changed files with 204 additions and 44 deletions
  1. 6 0
      src/PixiEditor.ChangeableDocument/ChangeInfos/Vectors/VectorShape_ChangeInfo.cs
  2. 10 4
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/VectorLayerNode.cs
  3. 2 2
      src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawRasterLine_UpdateableChange.cs
  4. 2 2
      src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawRasterRectangle_UpdateableChange.cs
  5. 63 0
      src/PixiEditor.ChangeableDocument/Changes/Vectors/SetShapeGeometry_UpdateableChange.cs
  6. 4 4
      src/PixiEditor/Data/Configs/ToolSetsConfig.json
  7. 2 2
      src/PixiEditor/Helpers/ServiceCollectionHelpers.cs
  8. 1 1
      src/PixiEditor/Models/DocumentModels/Public/DocumentToolsModule.cs
  9. 9 9
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/RasterLineToolExecutor.cs
  10. 5 5
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/RasterRectangleToolExecutor.cs
  11. 50 5
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/VectorEllipseToolExecutor.cs
  12. 1 1
      src/PixiEditor/Models/Handlers/Tools/IRasterLineToolHandler.cs
  13. 1 1
      src/PixiEditor/Models/Handlers/Tools/IRasterRectangleToolHandler.cs
  14. 1 1
      src/PixiEditor/Models/Handlers/Tools/IVectorEllipseToolHandler.cs
  15. 40 0
      src/PixiEditor/Models/Rendering/AffectedAreasGatherer.cs
  16. 1 1
      src/PixiEditor/Models/Rendering/MemberPreviewUpdater.cs
  17. 3 3
      src/PixiEditor/ViewModels/Tools/Tools/RasterLineToolViewModel.cs
  18. 2 2
      src/PixiEditor/ViewModels/Tools/Tools/RasterRectangleToolViewModel.cs
  19. 1 1
      src/PixiEditor/ViewModels/Tools/Tools/VectorEllipseToolViewModel.cs

+ 6 - 0
src/PixiEditor.ChangeableDocument/ChangeInfos/Vectors/VectorShape_ChangeInfo.cs

@@ -0,0 +1,6 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
+using PixiEditor.Numerics;
+
+namespace PixiEditor.ChangeableDocument.ChangeInfos.Vectors;
+
+    public record VectorShape_ChangeInfo(Guid LayerId) : IChangeInfo;

+ 10 - 4
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/VectorLayerNode.cs

@@ -18,7 +18,7 @@ public class VectorLayerNode : LayerNode, ITransformableObject
         set => ShapeData.TransformationMatrix = value;
     }
     
-    public ShapeVectorData ShapeData { get; } = new EllipseVectorData(new VecI(32), new VecI(32));
+    public ShapeVectorData? ShapeData { get; set; }
 
     protected override bool AffectedByChunkResolution => true;
 
@@ -26,6 +26,12 @@ public class VectorLayerNode : LayerNode, ITransformableObject
     
     protected override Texture? OnExecute(RenderingContext context)
     {
+        if (ShapeData == null)
+        {
+            Output.Value = null;
+            return null;
+        }
+        
         Texture texture = RequestTexture(0, context.DocumentSize);
 
         ShapeData.Rasterize(texture.DrawingSurface, context.ChunkResolution);
@@ -37,18 +43,18 @@ public class VectorLayerNode : LayerNode, ITransformableObject
 
     protected override bool CacheChanged(RenderingContext context)
     {
-        return base.CacheChanged(context) || ShapeData.GetCacheHash() != lastCacheHash;
+        return base.CacheChanged(context) || (ShapeData?.GetCacheHash() ?? -1) != lastCacheHash;
     }
 
     protected override void UpdateCache(RenderingContext context)
     {
         base.UpdateCache(context);
-        lastCacheHash = ShapeData.GetCacheHash();
+        lastCacheHash = ShapeData?.GetCacheHash() ?? -1;
     }
 
     public override RectD? GetTightBounds(KeyFrameTime frameTime)
     {
-        return ShapeData.TransformedAABB;
+        return ShapeData?.TransformedAABB ?? null;
     }
 
     public override ShapeCorners GetTransformationCorners(KeyFrameTime frameTime)

+ 2 - 2
src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawLine_UpdateableChange.cs → src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawRasterLine_UpdateableChange.cs

@@ -5,7 +5,7 @@ using PixiEditor.Numerics;
 
 namespace PixiEditor.ChangeableDocument.Changes.Drawing;
 
-internal class DrawLine_UpdateableChange : UpdateableChange
+internal class DrawRasterLine_UpdateableChange : UpdateableChange
 {
     private readonly Guid memberGuid;
     private VecI from;
@@ -18,7 +18,7 @@ internal class DrawLine_UpdateableChange : UpdateableChange
     private int frame;
 
     [GenerateUpdateableChangeActions]
-    public DrawLine_UpdateableChange
+    public DrawRasterLine_UpdateableChange
         (Guid memberGuid, VecI from, VecI to, int strokeWidth, Color color, StrokeCap caps, bool drawOnMask, int frame)
     {
         this.memberGuid = memberGuid;

+ 2 - 2
src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawRectangle_UpdateableChange.cs → src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawRasterRectangle_UpdateableChange.cs

@@ -2,7 +2,7 @@
 
 namespace PixiEditor.ChangeableDocument.Changes.Drawing;
 
-internal class DrawRectangle_UpdateableChange : UpdateableChange
+internal class DrawRasterRectangle_UpdateableChange : UpdateableChange
 {
     private readonly Guid memberGuid;
     private ShapeData rect;
@@ -11,7 +11,7 @@ internal class DrawRectangle_UpdateableChange : UpdateableChange
     private int frame;
     
     [GenerateUpdateableChangeActions]
-    public DrawRectangle_UpdateableChange(Guid memberGuid, ShapeData rectangle, bool drawOnMask, int frame)
+    public DrawRasterRectangle_UpdateableChange(Guid memberGuid, ShapeData rectangle, bool drawOnMask, int frame)
     {
         this.memberGuid = memberGuid;
         this.rect = rectangle;

+ 63 - 0
src/PixiEditor.ChangeableDocument/Changes/Vectors/SetShapeGeometry_UpdateableChange.cs

@@ -0,0 +1,63 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
+using PixiEditor.ChangeableDocument.ChangeInfos.Vectors;
+
+namespace PixiEditor.ChangeableDocument.Changes.Vectors;
+
+internal class SetShapeGeometry_UpdateableChange : UpdateableChange
+{
+    public Guid TargetId { get; set; }
+    public ShapeVectorData Data { get; set; }
+
+    private ShapeVectorData? originalData;
+
+    [GenerateUpdateableChangeActions]
+    public SetShapeGeometry_UpdateableChange(Guid targetId, ShapeVectorData data)
+    {
+        TargetId = targetId;
+        Data = data;
+    }
+
+    public override bool InitializeAndValidate(Document target)
+    {
+        if (target.TryFindNode<VectorLayerNode>(TargetId, out var node))
+        {
+            originalData = (ShapeVectorData?)node.ShapeData?.Clone();
+            return true;
+        }
+
+        return false;
+    }
+
+    [UpdateChangeMethod]
+    public void Update(ShapeVectorData data)
+    {
+        Data = data;
+    }
+
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
+    {
+        var node = target.FindNode<VectorLayerNode>(TargetId);
+        node.ShapeData = Data;
+
+        return new VectorShape_ChangeInfo(node.Id);
+    }
+
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply,
+        out bool ignoreInUndo)
+    {
+        ignoreInUndo = false;
+        var node = target.FindNode<VectorLayerNode>(TargetId);
+        node.ShapeData = Data;
+
+        return new VectorShape_ChangeInfo(node.Id);
+    }
+
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
+    {
+        var node = target.FindNode<VectorLayerNode>(TargetId);
+        node.ShapeData = originalData;
+
+        return new VectorShape_ChangeInfo(node.Id);
+    }
+}

+ 4 - 4
src/PixiEditor/Data/Configs/ToolSetsConfig.json

@@ -10,9 +10,9 @@
       "MagicWand",
       "Lasso",
       "FloodFill",
-      "Line",
+      "RasterLine",
       "RasterEllipse",
-      "Rectangle",
+      "RasterRectangle",
       "Eraser",
       "ColorPicker",
       "Brightness",
@@ -25,9 +25,9 @@
       "MoveViewport",
       "RotateViewport",
       "Move",
-      "Line",
+      "RasterLine",
       "VectorEllipse",
-      "Rectangle"
+      "RasterRectangle"
     ]
   }
 ]

+ 2 - 2
src/PixiEditor/Helpers/ServiceCollectionHelpers.cs

@@ -89,9 +89,9 @@ internal static class ServiceCollectionHelpers
             .AddTool<IMagicWandToolHandler, MagicWandToolViewModel>()
             .AddTool<ILassoToolHandler, LassoToolViewModel>()
             .AddTool<IFloodFillToolHandler, FloodFillToolViewModel>()
-            .AddTool<ILineToolHandler, LineToolViewModel>()
+            .AddTool<IRasterLineToolHandler, RasterLineToolViewModel>()
             .AddTool<IRasterEllipseToolHandler, RasterEllipseToolViewModel>()
-            .AddTool<IRectangleToolHandler, RectangleToolViewModel>()
+            .AddTool<IRasterRectangleToolHandler, RasterRectangleToolViewModel>()
             .AddTool<IEraserToolHandler, EraserToolViewModel>()
             .AddTool<IColorPickerHandler, ColorPickerToolViewModel>()
             .AddTool<IBrightnessToolHandler, BrightnessToolViewModel>()

+ 1 - 1
src/PixiEditor/Models/DocumentModels/Public/DocumentToolsModule.cs

@@ -48,7 +48,7 @@ internal class DocumentToolsModule
     public void UseLineTool()
     {
         bool force = Internals.ChangeController.GetCurrentExecutorType() == ExecutorType.ToolLinked;
-        Internals.ChangeController.TryStartExecutor<LineToolExecutor>(force);
+        Internals.ChangeController.TryStartExecutor<RasterLineToolExecutor>(force);
     }
 
     public void UseSelectTool() => Internals.ChangeController.TryStartExecutor<SelectToolExecutor>();

+ 9 - 9
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/LineToolExecutor.cs → src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/RasterLineToolExecutor.cs

@@ -10,7 +10,7 @@ using PixiEditor.Numerics;
 
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 #nullable enable
-internal class LineToolExecutor : UpdateableChangeExecutor
+internal class RasterLineToolExecutor : UpdateableChangeExecutor
 {
     public override ExecutorType Type => ExecutorType.ToolLinked;
 
@@ -23,13 +23,13 @@ internal class LineToolExecutor : UpdateableChangeExecutor
     private VecI curPos;
     private bool started = false;
     private bool transforming = false;
-    private ILineToolHandler? toolViewModel;
+    private IRasterLineToolHandler? toolViewModel;
     private IColorsHandler? colorsVM;
 
     public override ExecutionState Start()
     {
         colorsVM = GetHandler<IColorsHandler>();
-        toolViewModel = GetHandler<ILineToolHandler>();
+        toolViewModel = GetHandler<IRasterLineToolHandler>();
         IStructureMemberHandler? member = document?.SelectedStructureMember;
         if (colorsVM is null || toolViewModel is null || member is null)
             return ExecutionState.Error;
@@ -56,7 +56,7 @@ internal class LineToolExecutor : UpdateableChangeExecutor
         if (toolViewModel!.Snap)
             pos = ShapeToolExecutor<IShapeToolHandler>.Get45IncrementedPosition(startPos, pos);
         curPos = pos;
-        internals!.ActionAccumulator.AddActions(new DrawLine_Action(memberGuid, startPos, pos, StrokeWidth, strokeColor, StrokeCap.Butt, drawOnMask, document!.AnimationHandler.ActiveFrameBindable));
+        internals!.ActionAccumulator.AddActions(new DrawRasterLine_Action(memberGuid, startPos, pos, StrokeWidth, strokeColor, StrokeCap.Butt, drawOnMask, document!.AnimationHandler.ActiveFrameBindable));
     }
 
     public override void OnLeftMouseButtonUp()
@@ -75,7 +75,7 @@ internal class LineToolExecutor : UpdateableChangeExecutor
     {
         if (!transforming)
             return;
-        internals!.ActionAccumulator.AddActions(new DrawLine_Action(memberGuid, (VecI)start, (VecI)end, StrokeWidth, strokeColor, StrokeCap.Butt, drawOnMask, document!.AnimationHandler.ActiveFrameBindable));
+        internals!.ActionAccumulator.AddActions(new DrawRasterLine_Action(memberGuid, (VecI)start, (VecI)end, StrokeWidth, strokeColor, StrokeCap.Butt, drawOnMask, document!.AnimationHandler.ActiveFrameBindable));
         
         startPos = (VecI)start;
         curPos = (VecI)end;
@@ -87,7 +87,7 @@ internal class LineToolExecutor : UpdateableChangeExecutor
             return;
         
         strokeColor = color;
-        internals!.ActionAccumulator.AddActions(new DrawLine_Action(memberGuid, startPos, curPos, StrokeWidth, strokeColor, StrokeCap.Butt, drawOnMask, document!.AnimationHandler.ActiveFrameBindable));
+        internals!.ActionAccumulator.AddActions(new DrawRasterLine_Action(memberGuid, startPos, curPos, StrokeWidth, strokeColor, StrokeCap.Butt, drawOnMask, document!.AnimationHandler.ActiveFrameBindable));
     }
 
     public override void OnSelectedObjectNudged(VecI distance)
@@ -99,7 +99,7 @@ internal class LineToolExecutor : UpdateableChangeExecutor
 
     public override void OnSettingsChanged(string name, object value)
     {
-        internals!.ActionAccumulator.AddActions(new DrawLine_Action(memberGuid, startPos, curPos, StrokeWidth, strokeColor, StrokeCap.Butt, drawOnMask, document!.AnimationHandler.ActiveFrameBindable));
+        internals!.ActionAccumulator.AddActions(new DrawRasterLine_Action(memberGuid, startPos, curPos, StrokeWidth, strokeColor, StrokeCap.Butt, drawOnMask, document!.AnimationHandler.ActiveFrameBindable));
     }
 
     public override void OnMidChangeUndo()
@@ -122,7 +122,7 @@ internal class LineToolExecutor : UpdateableChangeExecutor
             return;
 
         document!.LineToolOverlayHandler.Hide();
-        internals!.ActionAccumulator.AddFinishedActions(new EndDrawLine_Action());
+        internals!.ActionAccumulator.AddFinishedActions(new EndDrawRasterLine_Action());
         onEnded!(this);
 
         colorsVM.AddSwatch(new PaletteColor(strokeColor.R, strokeColor.G, strokeColor.B));
@@ -133,6 +133,6 @@ internal class LineToolExecutor : UpdateableChangeExecutor
         if (transforming)
             document!.LineToolOverlayHandler.Hide();
 
-        internals!.ActionAccumulator.AddFinishedActions(new EndDrawLine_Action());
+        internals!.ActionAccumulator.AddFinishedActions(new EndDrawRasterLine_Action());
     }
 }

+ 5 - 5
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/RasterRectangleToolExecutor.cs

@@ -8,7 +8,7 @@ using PixiEditor.Numerics;
 
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 #nullable enable
-internal class RasterRectangleToolExecutor : ShapeToolExecutor<IRectangleToolHandler>
+internal class RasterRectangleToolExecutor : ShapeToolExecutor<IRasterRectangleToolHandler>
 {
     private ShapeData lastData;
     public override ExecutorType Type => ExecutorType.ToolLinked;
@@ -26,14 +26,14 @@ internal class RasterRectangleToolExecutor : ShapeToolExecutor<IRectangleToolHan
         
         lastData = new ShapeData(rect.Center, rect.Size, rotationRad, StrokeWidth, StrokeColor, FillColor);
 
-        internals!.ActionAccumulator.AddActions(new DrawRectangle_Action(memberGuid, lastData, drawOnMask, document!.AnimationHandler.ActiveFrameBindable));
+        internals!.ActionAccumulator.AddActions(new DrawRasterRectangle_Action(memberGuid, lastData, drawOnMask, document!.AnimationHandler.ActiveFrameBindable));
     }
 
     protected override void DrawShape(VecI currentPos, double rotationRad, bool first) => DrawRectangle(currentPos, rotationRad, first);
     protected override IAction SettingsChangedAction()
     {
         lastData = new ShapeData(lastData.Center, lastData.Size, lastRadians, StrokeWidth, StrokeColor, FillColor);
-        return new DrawRectangle_Action(memberGuid, lastData, drawOnMask, document!.AnimationHandler.ActiveFrameBindable);   
+        return new DrawRasterRectangle_Action(memberGuid, lastData, drawOnMask, document!.AnimationHandler.ActiveFrameBindable);   
     }
 
     protected override IAction TransformMovedAction(ShapeData data, ShapeCorners corners)
@@ -42,8 +42,8 @@ internal class RasterRectangleToolExecutor : ShapeToolExecutor<IRectangleToolHan
         
         lastRadians = corners.RectRotation;
         
-        return new DrawRectangle_Action(memberGuid, data, drawOnMask, document!.AnimationHandler.ActiveFrameBindable);
+        return new DrawRasterRectangle_Action(memberGuid, data, drawOnMask, document!.AnimationHandler.ActiveFrameBindable);
     }
 
-    protected override IAction EndDrawAction() => new EndDrawRectangle_Action();
+    protected override IAction EndDrawAction() => new EndDrawRasterRectangle_Action();
 }

+ 50 - 5
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/VectorEllipseToolExecutor.cs

@@ -1,29 +1,74 @@
 using ChunkyImageLib.DataHolders;
 using PixiEditor.ChangeableDocument.Actions;
+using PixiEditor.ChangeableDocument.Actions.Generated;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 using PixiEditor.Models.Handlers.Tools;
+using PixiEditor.Models.Tools;
 using PixiEditor.Numerics;
 
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 
 internal class VectorEllipseToolExecutor : ShapeToolExecutor<IVectorEllipseToolHandler>
 {
-    protected override void DrawShape(VecI currentPos, double rotationRad, bool firstDraw)
+    public override ExecutorType Type => ExecutorType.ToolLinked;
+    protected override DocumentTransformMode TransformMode => DocumentTransformMode.Scale_Rotate_Shear_Perspective;
+
+    protected override void DrawShape(VecI curPos, double rotationRad, bool firstDraw)
     {
-        throw new NotImplementedException();
+        RectI rect;
+        if (firstDraw)
+            rect = new RectI(curPos, VecI.Zero);
+        else if (toolViewModel!.DrawCircle)
+            rect = GetSquaredCoordinates(startPos, curPos);
+        else
+            rect = RectI.FromTwoPixels(startPos, curPos);
+        
+        EllipseVectorData data = new EllipseVectorData(rect.Center, rect.Size / 2f) 
+        {
+            RotationRadians = rotationRad, 
+            StrokeColor = StrokeColor, 
+            FillColor = FillColor, 
+            StrokeWidth = StrokeWidth
+        };
+        
+        lastRect = rect;
+        lastRadians = rotationRad;
+        
+        internals!.ActionAccumulator.AddActions(new SetShapeGeometry_Action(memberGuid, data));
     }
 
     protected override IAction SettingsChangedAction()
     {
-        throw new NotImplementedException();
+        return new SetShapeGeometry_Action(memberGuid, new EllipseVectorData(lastRect.Center, lastRect.Size / 2f) 
+        {
+            RotationRadians = lastRadians, 
+            StrokeColor = StrokeColor, 
+            FillColor = FillColor, 
+            StrokeWidth = StrokeWidth
+        });
     }
 
     protected override IAction TransformMovedAction(ShapeData data, ShapeCorners corners)
     {
-        throw new NotImplementedException();
+        RectI rect = (RectI)RectD.FromCenterAndSize(data.Center, data.Size);
+        double radians = corners.RectRotation;
+        
+        EllipseVectorData ellipseData = new EllipseVectorData(rect.Center, rect.Size / 2f) 
+        {
+            RotationRadians = radians, 
+            StrokeColor = StrokeColor, 
+            FillColor = FillColor, 
+            StrokeWidth = StrokeWidth
+        };
+        
+        lastRect = rect;
+        lastRadians = radians;
+        
+        return new SetShapeGeometry_Action(memberGuid, ellipseData);
     }
 
     protected override IAction EndDrawAction()
     {
-        throw new NotImplementedException();
+        return new EndSetShapeGeometry_Action();
     }
 }

+ 1 - 1
src/PixiEditor/Models/Handlers/Tools/ILineToolHandler.cs → src/PixiEditor/Models/Handlers/Tools/IRasterLineToolHandler.cs

@@ -1,6 +1,6 @@
 namespace PixiEditor.Models.Handlers.Tools;
 
-internal interface ILineToolHandler : IToolHandler
+internal interface IRasterLineToolHandler : IToolHandler
 {
     public int ToolSize { get; }
     public bool Snap { get; }

+ 1 - 1
src/PixiEditor/Models/Handlers/Tools/IRectangleToolHandler.cs → src/PixiEditor/Models/Handlers/Tools/IRasterRectangleToolHandler.cs

@@ -1,6 +1,6 @@
 namespace PixiEditor.Models.Handlers.Tools;
 
-internal interface IRectangleToolHandler : IShapeToolHandler
+internal interface IRasterRectangleToolHandler : IShapeToolHandler
 {
     public bool DrawSquare { get; }
 }

+ 1 - 1
src/PixiEditor/Models/Handlers/Tools/IVectorEllipseToolHandler.cs

@@ -2,5 +2,5 @@
 
 internal interface IVectorEllipseToolHandler : IShapeToolHandler
 {
-    
+    public bool DrawCircle { get; }
 }

+ 40 - 0
src/PixiEditor/Models/Rendering/AffectedAreasGatherer.cs

@@ -1,6 +1,7 @@
 using System.Collections.Generic;
 using ChunkyImageLib;
 using ChunkyImageLib.DataHolders;
+using ChunkyImageLib.Operations;
 using PixiEditor.ChangeableDocument;
 using PixiEditor.ChangeableDocument.Actions.Generated;
 using PixiEditor.ChangeableDocument.Changeables.Animations;
@@ -15,6 +16,7 @@ using PixiEditor.ChangeableDocument.ChangeInfos.Objects;
 using PixiEditor.ChangeableDocument.ChangeInfos.Properties;
 using PixiEditor.ChangeableDocument.ChangeInfos.Root;
 using PixiEditor.ChangeableDocument.ChangeInfos.Structure;
+using PixiEditor.ChangeableDocument.ChangeInfos.Vectors;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Models.DocumentPassthroughActions;
 using PixiEditor.Numerics;
@@ -161,6 +163,10 @@ internal class AffectedAreasGatherer
                 case OnionFrames_ChangeInfo:
                     AddWholeCanvasToMainImage();
                     break;
+                case VectorShape_ChangeInfo info:
+                    AddAllToMainImage(info.LayerId, ActiveFrame, false);
+                    AddAllToImagePreviews(info.LayerId, ActiveFrame, false);
+                    break;
             }
         }
     }
@@ -186,6 +192,20 @@ internal class AffectedAreasGatherer
             /*foreach (var child in folder.Children)
                 AddAllToImagePreviews(child.Id, frame);*/
         }
+        else if (member is IReadOnlyLayerNode genericLayerNode)
+        {
+            var tightBounds = genericLayerNode.GetTightBounds(frame);
+            if (tightBounds is not null)
+            {
+                var affectedArea = new AffectedArea(
+                    OperationHelper.FindChunksTouchingRectangle((RectI)tightBounds.Value, ChunkyImage.FullChunkSize));
+                AddToImagePreviews(memberGuid, affectedArea, ignoreSelf);
+            }
+            else
+            {
+                AddWholeCanvasToImagePreviews(memberGuid, ignoreSelf);
+            }
+        }
     }
 
     private void AddAllToMainImage(Guid memberGuid, KeyFrameTime frame, bool useMask = true)
@@ -205,6 +225,26 @@ internal class AffectedAreasGatherer
                 chunks.IntersectWith(layer.EmbeddedMask.FindAllChunks());
             AddToMainImage(new AffectedArea(chunks));
         }
+        else if (member is IReadOnlyLayerNode genericLayer)
+        {
+            var tightBounds = genericLayer.GetTightBounds(frame);
+            if (tightBounds is not null)
+            {
+                var affectedArea = new AffectedArea(
+                    OperationHelper.FindChunksTouchingRectangle((RectI)tightBounds.Value, ChunkyImage.FullChunkSize));
+                AddToMainImage(affectedArea);
+            }
+            else
+            {
+                AddWholeCanvasToMainImage();
+            }
+        }
+        else if (member is IReadOnlyFolderNode folder)
+        {
+            AddWholeCanvasToMainImage();
+            /*foreach (var child in folder.Children)
+                AddAllToMainImage(child.Id, frame);*/
+        }
         else
         {
             AddWholeCanvasToMainImage();

+ 1 - 1
src/PixiEditor/Models/Rendering/MemberPreviewUpdater.cs

@@ -315,7 +315,7 @@ internal class MemberPreviewUpdater
             return FindImageTightBoundsFast(raster.GetLayerImageAtFrame(frame));
         }
 
-        return (RectI)layer.GetTightBounds(frame);
+        return (RectI?)layer.GetTightBounds(frame);
     }
 
     /// <summary>

+ 3 - 3
src/PixiEditor/ViewModels/Tools/Tools/LineToolViewModel.cs → src/PixiEditor/ViewModels/Tools/Tools/RasterLineToolViewModel.cs

@@ -11,14 +11,14 @@ using PixiEditor.ViewModels.Tools.ToolSettings.Toolbars;
 namespace PixiEditor.ViewModels.Tools.Tools;
 
 [Command.Tool(Key = Key.L)]
-internal class LineToolViewModel : ShapeTool, ILineToolHandler
+internal class RasterLineToolViewModel : ShapeTool, IRasterLineToolHandler
 {
     private string defaultActionDisplay = "LINE_TOOL_ACTION_DISPLAY_DEFAULT";
 
-    public LineToolViewModel()
+    public RasterLineToolViewModel()
     {
         ActionDisplay = defaultActionDisplay;
-        Toolbar = ToolbarFactory.Create<LineToolViewModel, BasicToolbar>(this);
+        Toolbar = ToolbarFactory.Create<RasterLineToolViewModel, BasicToolbar>(this);
     }
 
     public override string ToolNameLocalizationKey => "LINE_TOOL";

+ 2 - 2
src/PixiEditor/ViewModels/Tools/Tools/RectangleToolViewModel.cs → src/PixiEditor/ViewModels/Tools/Tools/RasterRectangleToolViewModel.cs

@@ -9,10 +9,10 @@ using PixiEditor.UI.Common.Fonts;
 namespace PixiEditor.ViewModels.Tools.Tools;
 
 [Command.Tool(Key = Key.R)]
-internal class RectangleToolViewModel : ShapeTool, IRectangleToolHandler
+internal class RasterRectangleToolViewModel : ShapeTool, IRasterRectangleToolHandler
 {
     private string defaultActionDisplay = "RECTANGLE_TOOL_ACTION_DISPLAY_DEFAULT";
-    public RectangleToolViewModel()
+    public RasterRectangleToolViewModel()
     {
         ActionDisplay = defaultActionDisplay;
     }

+ 1 - 1
src/PixiEditor/ViewModels/Tools/Tools/VectorEllipseToolViewModel.cs

@@ -22,6 +22,6 @@ internal class VectorEllipseToolViewModel : ShapeTool, IVectorEllipseToolHandler
 
     public override void UseTool(VecD pos)
     {
-        ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseRasterEllipseTool();
+        ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseVectorEllipseTool();
     }
 }