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;
         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;
     protected override bool AffectedByChunkResolution => true;
 
 
@@ -26,6 +26,12 @@ public class VectorLayerNode : LayerNode, ITransformableObject
     
     
     protected override Texture? OnExecute(RenderingContext context)
     protected override Texture? OnExecute(RenderingContext context)
     {
     {
+        if (ShapeData == null)
+        {
+            Output.Value = null;
+            return null;
+        }
+        
         Texture texture = RequestTexture(0, context.DocumentSize);
         Texture texture = RequestTexture(0, context.DocumentSize);
 
 
         ShapeData.Rasterize(texture.DrawingSurface, context.ChunkResolution);
         ShapeData.Rasterize(texture.DrawingSurface, context.ChunkResolution);
@@ -37,18 +43,18 @@ public class VectorLayerNode : LayerNode, ITransformableObject
 
 
     protected override bool CacheChanged(RenderingContext context)
     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)
     protected override void UpdateCache(RenderingContext context)
     {
     {
         base.UpdateCache(context);
         base.UpdateCache(context);
-        lastCacheHash = ShapeData.GetCacheHash();
+        lastCacheHash = ShapeData?.GetCacheHash() ?? -1;
     }
     }
 
 
     public override RectD? GetTightBounds(KeyFrameTime frameTime)
     public override RectD? GetTightBounds(KeyFrameTime frameTime)
     {
     {
-        return ShapeData.TransformedAABB;
+        return ShapeData?.TransformedAABB ?? null;
     }
     }
 
 
     public override ShapeCorners GetTransformationCorners(KeyFrameTime frameTime)
     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;
 namespace PixiEditor.ChangeableDocument.Changes.Drawing;
 
 
-internal class DrawLine_UpdateableChange : UpdateableChange
+internal class DrawRasterLine_UpdateableChange : UpdateableChange
 {
 {
     private readonly Guid memberGuid;
     private readonly Guid memberGuid;
     private VecI from;
     private VecI from;
@@ -18,7 +18,7 @@ internal class DrawLine_UpdateableChange : UpdateableChange
     private int frame;
     private int frame;
 
 
     [GenerateUpdateableChangeActions]
     [GenerateUpdateableChangeActions]
-    public DrawLine_UpdateableChange
+    public DrawRasterLine_UpdateableChange
         (Guid memberGuid, VecI from, VecI to, int strokeWidth, Color color, StrokeCap caps, bool drawOnMask, int frame)
         (Guid memberGuid, VecI from, VecI to, int strokeWidth, Color color, StrokeCap caps, bool drawOnMask, int frame)
     {
     {
         this.memberGuid = memberGuid;
         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;
 namespace PixiEditor.ChangeableDocument.Changes.Drawing;
 
 
-internal class DrawRectangle_UpdateableChange : UpdateableChange
+internal class DrawRasterRectangle_UpdateableChange : UpdateableChange
 {
 {
     private readonly Guid memberGuid;
     private readonly Guid memberGuid;
     private ShapeData rect;
     private ShapeData rect;
@@ -11,7 +11,7 @@ internal class DrawRectangle_UpdateableChange : UpdateableChange
     private int frame;
     private int frame;
     
     
     [GenerateUpdateableChangeActions]
     [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.memberGuid = memberGuid;
         this.rect = rectangle;
         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",
       "MagicWand",
       "Lasso",
       "Lasso",
       "FloodFill",
       "FloodFill",
-      "Line",
+      "RasterLine",
       "RasterEllipse",
       "RasterEllipse",
-      "Rectangle",
+      "RasterRectangle",
       "Eraser",
       "Eraser",
       "ColorPicker",
       "ColorPicker",
       "Brightness",
       "Brightness",
@@ -25,9 +25,9 @@
       "MoveViewport",
       "MoveViewport",
       "RotateViewport",
       "RotateViewport",
       "Move",
       "Move",
-      "Line",
+      "RasterLine",
       "VectorEllipse",
       "VectorEllipse",
-      "Rectangle"
+      "RasterRectangle"
     ]
     ]
   }
   }
 ]
 ]

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

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

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

@@ -48,7 +48,7 @@ internal class DocumentToolsModule
     public void UseLineTool()
     public void UseLineTool()
     {
     {
         bool force = Internals.ChangeController.GetCurrentExecutorType() == ExecutorType.ToolLinked;
         bool force = Internals.ChangeController.GetCurrentExecutorType() == ExecutorType.ToolLinked;
-        Internals.ChangeController.TryStartExecutor<LineToolExecutor>(force);
+        Internals.ChangeController.TryStartExecutor<RasterLineToolExecutor>(force);
     }
     }
 
 
     public void UseSelectTool() => Internals.ChangeController.TryStartExecutor<SelectToolExecutor>();
     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;
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 #nullable enable
 #nullable enable
-internal class LineToolExecutor : UpdateableChangeExecutor
+internal class RasterLineToolExecutor : UpdateableChangeExecutor
 {
 {
     public override ExecutorType Type => ExecutorType.ToolLinked;
     public override ExecutorType Type => ExecutorType.ToolLinked;
 
 
@@ -23,13 +23,13 @@ internal class LineToolExecutor : UpdateableChangeExecutor
     private VecI curPos;
     private VecI curPos;
     private bool started = false;
     private bool started = false;
     private bool transforming = false;
     private bool transforming = false;
-    private ILineToolHandler? toolViewModel;
+    private IRasterLineToolHandler? toolViewModel;
     private IColorsHandler? colorsVM;
     private IColorsHandler? colorsVM;
 
 
     public override ExecutionState Start()
     public override ExecutionState Start()
     {
     {
         colorsVM = GetHandler<IColorsHandler>();
         colorsVM = GetHandler<IColorsHandler>();
-        toolViewModel = GetHandler<ILineToolHandler>();
+        toolViewModel = GetHandler<IRasterLineToolHandler>();
         IStructureMemberHandler? member = document?.SelectedStructureMember;
         IStructureMemberHandler? member = document?.SelectedStructureMember;
         if (colorsVM is null || toolViewModel is null || member is null)
         if (colorsVM is null || toolViewModel is null || member is null)
             return ExecutionState.Error;
             return ExecutionState.Error;
@@ -56,7 +56,7 @@ internal class LineToolExecutor : UpdateableChangeExecutor
         if (toolViewModel!.Snap)
         if (toolViewModel!.Snap)
             pos = ShapeToolExecutor<IShapeToolHandler>.Get45IncrementedPosition(startPos, pos);
             pos = ShapeToolExecutor<IShapeToolHandler>.Get45IncrementedPosition(startPos, pos);
         curPos = 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()
     public override void OnLeftMouseButtonUp()
@@ -75,7 +75,7 @@ internal class LineToolExecutor : UpdateableChangeExecutor
     {
     {
         if (!transforming)
         if (!transforming)
             return;
             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;
         startPos = (VecI)start;
         curPos = (VecI)end;
         curPos = (VecI)end;
@@ -87,7 +87,7 @@ internal class LineToolExecutor : UpdateableChangeExecutor
             return;
             return;
         
         
         strokeColor = color;
         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)
     public override void OnSelectedObjectNudged(VecI distance)
@@ -99,7 +99,7 @@ internal class LineToolExecutor : UpdateableChangeExecutor
 
 
     public override void OnSettingsChanged(string name, object value)
     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()
     public override void OnMidChangeUndo()
@@ -122,7 +122,7 @@ internal class LineToolExecutor : UpdateableChangeExecutor
             return;
             return;
 
 
         document!.LineToolOverlayHandler.Hide();
         document!.LineToolOverlayHandler.Hide();
-        internals!.ActionAccumulator.AddFinishedActions(new EndDrawLine_Action());
+        internals!.ActionAccumulator.AddFinishedActions(new EndDrawRasterLine_Action());
         onEnded!(this);
         onEnded!(this);
 
 
         colorsVM.AddSwatch(new PaletteColor(strokeColor.R, strokeColor.G, strokeColor.B));
         colorsVM.AddSwatch(new PaletteColor(strokeColor.R, strokeColor.G, strokeColor.B));
@@ -133,6 +133,6 @@ internal class LineToolExecutor : UpdateableChangeExecutor
         if (transforming)
         if (transforming)
             document!.LineToolOverlayHandler.Hide();
             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;
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 #nullable enable
 #nullable enable
-internal class RasterRectangleToolExecutor : ShapeToolExecutor<IRectangleToolHandler>
+internal class RasterRectangleToolExecutor : ShapeToolExecutor<IRasterRectangleToolHandler>
 {
 {
     private ShapeData lastData;
     private ShapeData lastData;
     public override ExecutorType Type => ExecutorType.ToolLinked;
     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);
         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 void DrawShape(VecI currentPos, double rotationRad, bool first) => DrawRectangle(currentPos, rotationRad, first);
     protected override IAction SettingsChangedAction()
     protected override IAction SettingsChangedAction()
     {
     {
         lastData = new ShapeData(lastData.Center, lastData.Size, lastRadians, StrokeWidth, StrokeColor, FillColor);
         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)
     protected override IAction TransformMovedAction(ShapeData data, ShapeCorners corners)
@@ -42,8 +42,8 @@ internal class RasterRectangleToolExecutor : ShapeToolExecutor<IRectangleToolHan
         
         
         lastRadians = corners.RectRotation;
         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 ChunkyImageLib.DataHolders;
 using PixiEditor.ChangeableDocument.Actions;
 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.Handlers.Tools;
+using PixiEditor.Models.Tools;
 using PixiEditor.Numerics;
 using PixiEditor.Numerics;
 
 
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 
 
 internal class VectorEllipseToolExecutor : ShapeToolExecutor<IVectorEllipseToolHandler>
 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()
     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)
     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()
     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;
 namespace PixiEditor.Models.Handlers.Tools;
 
 
-internal interface ILineToolHandler : IToolHandler
+internal interface IRasterLineToolHandler : IToolHandler
 {
 {
     public int ToolSize { get; }
     public int ToolSize { get; }
     public bool Snap { 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;
 namespace PixiEditor.Models.Handlers.Tools;
 
 
-internal interface IRectangleToolHandler : IShapeToolHandler
+internal interface IRasterRectangleToolHandler : IShapeToolHandler
 {
 {
     public bool DrawSquare { get; }
     public bool DrawSquare { get; }
 }
 }

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

@@ -2,5 +2,5 @@
 
 
 internal interface IVectorEllipseToolHandler : IShapeToolHandler
 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 System.Collections.Generic;
 using ChunkyImageLib;
 using ChunkyImageLib;
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.DataHolders;
+using ChunkyImageLib.Operations;
 using PixiEditor.ChangeableDocument;
 using PixiEditor.ChangeableDocument;
 using PixiEditor.ChangeableDocument.Actions.Generated;
 using PixiEditor.ChangeableDocument.Actions.Generated;
 using PixiEditor.ChangeableDocument.Changeables.Animations;
 using PixiEditor.ChangeableDocument.Changeables.Animations;
@@ -15,6 +16,7 @@ using PixiEditor.ChangeableDocument.ChangeInfos.Objects;
 using PixiEditor.ChangeableDocument.ChangeInfos.Properties;
 using PixiEditor.ChangeableDocument.ChangeInfos.Properties;
 using PixiEditor.ChangeableDocument.ChangeInfos.Root;
 using PixiEditor.ChangeableDocument.ChangeInfos.Root;
 using PixiEditor.ChangeableDocument.ChangeInfos.Structure;
 using PixiEditor.ChangeableDocument.ChangeInfos.Structure;
+using PixiEditor.ChangeableDocument.ChangeInfos.Vectors;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Models.DocumentPassthroughActions;
 using PixiEditor.Models.DocumentPassthroughActions;
 using PixiEditor.Numerics;
 using PixiEditor.Numerics;
@@ -161,6 +163,10 @@ internal class AffectedAreasGatherer
                 case OnionFrames_ChangeInfo:
                 case OnionFrames_ChangeInfo:
                     AddWholeCanvasToMainImage();
                     AddWholeCanvasToMainImage();
                     break;
                     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)
             /*foreach (var child in folder.Children)
                 AddAllToImagePreviews(child.Id, frame);*/
                 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)
     private void AddAllToMainImage(Guid memberGuid, KeyFrameTime frame, bool useMask = true)
@@ -205,6 +225,26 @@ internal class AffectedAreasGatherer
                 chunks.IntersectWith(layer.EmbeddedMask.FindAllChunks());
                 chunks.IntersectWith(layer.EmbeddedMask.FindAllChunks());
             AddToMainImage(new AffectedArea(chunks));
             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
         else
         {
         {
             AddWholeCanvasToMainImage();
             AddWholeCanvasToMainImage();

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

@@ -315,7 +315,7 @@ internal class MemberPreviewUpdater
             return FindImageTightBoundsFast(raster.GetLayerImageAtFrame(frame));
             return FindImageTightBoundsFast(raster.GetLayerImageAtFrame(frame));
         }
         }
 
 
-        return (RectI)layer.GetTightBounds(frame);
+        return (RectI?)layer.GetTightBounds(frame);
     }
     }
 
 
     /// <summary>
     /// <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;
 namespace PixiEditor.ViewModels.Tools.Tools;
 
 
 [Command.Tool(Key = Key.L)]
 [Command.Tool(Key = Key.L)]
-internal class LineToolViewModel : ShapeTool, ILineToolHandler
+internal class RasterLineToolViewModel : ShapeTool, IRasterLineToolHandler
 {
 {
     private string defaultActionDisplay = "LINE_TOOL_ACTION_DISPLAY_DEFAULT";
     private string defaultActionDisplay = "LINE_TOOL_ACTION_DISPLAY_DEFAULT";
 
 
-    public LineToolViewModel()
+    public RasterLineToolViewModel()
     {
     {
         ActionDisplay = defaultActionDisplay;
         ActionDisplay = defaultActionDisplay;
-        Toolbar = ToolbarFactory.Create<LineToolViewModel, BasicToolbar>(this);
+        Toolbar = ToolbarFactory.Create<RasterLineToolViewModel, BasicToolbar>(this);
     }
     }
 
 
     public override string ToolNameLocalizationKey => "LINE_TOOL";
     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;
 namespace PixiEditor.ViewModels.Tools.Tools;
 
 
 [Command.Tool(Key = Key.R)]
 [Command.Tool(Key = Key.R)]
-internal class RectangleToolViewModel : ShapeTool, IRectangleToolHandler
+internal class RasterRectangleToolViewModel : ShapeTool, IRasterRectangleToolHandler
 {
 {
     private string defaultActionDisplay = "RECTANGLE_TOOL_ACTION_DISPLAY_DEFAULT";
     private string defaultActionDisplay = "RECTANGLE_TOOL_ACTION_DISPLAY_DEFAULT";
-    public RectangleToolViewModel()
+    public RasterRectangleToolViewModel()
     {
     {
         ActionDisplay = defaultActionDisplay;
         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)
     public override void UseTool(VecD pos)
     {
     {
-        ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseRasterEllipseTool();
+        ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseVectorEllipseTool();
     }
     }
 }
 }