Explorar o código

Added editing of already placed vectors

flabbet hai 1 ano
pai
achega
50b276dac4
Modificáronse 19 ficheiros con 240 adicións e 19 borrados
  1. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Document.cs
  2. 8 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/VectorLayerNode.cs
  3. 1 1
      src/PixiEditor/Models/DocumentModels/ChangeExecutionController.cs
  4. 35 2
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/LineExecutor.cs
  5. 6 0
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/RasterLineToolExecutor.cs
  6. 29 4
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/ShapeToolExecutor.cs
  7. 12 0
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/VectorEllipseToolExecutor.cs
  8. 13 0
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/VectorLineToolExecutor.cs
  9. 18 1
      src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/VectorRectangleToolExecutor.cs
  10. 5 2
      src/PixiEditor/Models/Handlers/IVectorLayerHandler.cs
  11. 8 0
      src/PixiEditor/Models/Handlers/Toolbars/ILineToolbar.cs
  12. 1 1
      src/PixiEditor/Models/Serialization/Factories/PointsDataSerializationFactory.cs
  13. 2 1
      src/PixiEditor/ViewModels/Document/Nodes/StructureMemberViewModel.cs
  14. 7 0
      src/PixiEditor/ViewModels/Document/Nodes/VectorLayerNodeViewModel.cs
  15. 26 0
      src/PixiEditor/ViewModels/Tools/ToolSettings/Toolbars/LineToolbar.cs
  16. 1 1
      src/PixiEditor/ViewModels/Tools/Tools/RasterLineToolViewModel.cs
  17. 20 0
      src/PixiEditor/ViewModels/Tools/Tools/VectorEllipseToolViewModel.cs
  18. 27 4
      src/PixiEditor/ViewModels/Tools/Tools/VectorLineToolViewModel.cs
  19. 20 0
      src/PixiEditor/ViewModels/Tools/Tools/VectorRectangleToolViewModel.cs

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Document.cs

@@ -263,7 +263,7 @@ internal class Document : IChangeable, IReadOnlyDocument
     /// <returns>True if the node could be found, otherwise false.</returns>
     public bool TryFindNode<T>(Guid id, out T node) where T : Node
     {
-        node = (T?)NodeGraph.Nodes.FirstOrDefault(x => x.Id == id) ?? default;
+        node = (T?)NodeGraph.Nodes.FirstOrDefault(x => x.Id == id && x is T) ?? default;
         return node != null;
     }
 

+ 8 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/VectorLayerNode.cs

@@ -96,8 +96,15 @@ public class VectorLayerNode : LayerNode, ITransformableObject, IReadOnlyVectorN
         VecI translation = new VecI(
             (int)Math.Max(ShapeData.TransformedAABB.TopLeft.X, 0),
             (int)Math.Max(ShapeData.TransformedAABB.TopLeft.Y, 0));
+        
+        VecI size = tightBoundsSize + translation;
+        
+        if (size.X == 0 || size.Y == 0)
+        {
+            return false;
+        }
 
-        using Texture toRasterizeOn = new(tightBoundsSize + translation);
+        using Texture toRasterizeOn = new(size);
 
         int save = toRasterizeOn.DrawingSurface.Canvas.Save();
 

+ 1 - 1
src/PixiEditor/Models/DocumentModels/ChangeExecutionController.cs

@@ -76,7 +76,7 @@ internal class ChangeExecutionController
     private bool TryStartExecutorInternal(UpdateableChangeExecutor executor)
     {
         executor.Initialize(document, internals, services, this, EndExecutor);
-
+        
         if (executor.StartMode == ExecutorStartMode.OnMouseLeftButtonDown)
         {
             _queuedExecutor = executor;

+ 35 - 2
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/LineExecutor.cs

@@ -1,9 +1,13 @@
 using PixiEditor.ChangeableDocument.Actions;
 using PixiEditor.ChangeableDocument.Actions.Generated;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces.Shapes;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.Surfaces.PaintImpl;
 using PixiEditor.Extensions.CommonApi.Palettes;
+using PixiEditor.Helpers.Extensions;
 using PixiEditor.Models.Handlers;
+using PixiEditor.Models.Handlers.Toolbars;
 using PixiEditor.Models.Handlers.Tools;
 using PixiEditor.Models.Tools;
 using PixiEditor.Numerics;
@@ -15,7 +19,7 @@ internal abstract class LineExecutor<T> : UpdateableChangeExecutor where T : ILi
     public override ExecutorType Type => ExecutorType.ToolLinked;
 
     protected VecI startPos;
-    protected Color StrokeColor => colorsVM!.PrimaryColor;
+    protected Color StrokeColor => toolbar!.StrokeColor.ToColor();
     protected int StrokeWidth => toolViewModel!.ToolSize;
     protected Guid memberGuid;
     protected bool drawOnMask;
@@ -25,12 +29,14 @@ internal abstract class LineExecutor<T> : UpdateableChangeExecutor where T : ILi
     private bool transforming = false;
     private T? toolViewModel;
     private IColorsHandler? colorsVM;
+    private ILineToolbar? toolbar;
 
     public override ExecutionState Start()
     {
         colorsVM = GetHandler<IColorsHandler>();
         toolViewModel = GetHandler<T>();
         IStructureMemberHandler? member = document?.SelectedStructureMember;
+        toolbar = (ILineToolbar?)toolViewModel?.Toolbar;
         if (colorsVM is null || toolViewModel is null || member is null)
             return ExecutionState.Error;
 
@@ -40,12 +46,38 @@ internal abstract class LineExecutor<T> : UpdateableChangeExecutor where T : ILi
         if (!drawOnMask && member is not ILayerHandler)
             return ExecutionState.Error;
 
-        startPos = controller!.LastPixelPosition;
         memberGuid = member.Id;
 
+        if (controller.LeftMousePressed || member is not IVectorLayerHandler)
+        {
+            startPos = controller!.LastPixelPosition;
+            OnColorChanged(colorsVM.PrimaryColor, true);
+        }
+        else
+        {
+            transforming = true;
+            var node = (VectorLayerNode)internals.Tracker.Document.FindMember(member.Id);
+            IReadOnlyLineData data = node.ShapeData as IReadOnlyLineData;
+            
+            if(data is null)
+            {
+                document.TransformHandler.HideTransform();
+                return ExecutionState.Error;
+            }
+
+            toolbar.StrokeColor = data.StrokeColor.ToColor();
+            
+            if (!InitShapeData(node.ShapeData as IReadOnlyLineData))
+            {
+                document.TransformHandler.HideTransform();
+                return ExecutionState.Error;
+            }
+        }
+
         return ExecutionState.Success;
     }
 
+    protected abstract bool InitShapeData(IReadOnlyLineData? data);
     protected abstract IAction DrawLine(VecI pos);
     protected abstract IAction TransformOverlayMoved(VecD start, VecD end);
     protected abstract IAction SettingsChange();
@@ -94,6 +126,7 @@ internal abstract class LineExecutor<T> : UpdateableChangeExecutor where T : ILi
         if (!primary)
             return;
 
+        toolbar!.StrokeColor = color.ToColor();
         var colorChangedAction = SettingsChange();
         internals!.ActionAccumulator.AddActions(colorChangedAction);
     }

+ 6 - 0
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/RasterLineToolExecutor.cs

@@ -1,5 +1,6 @@
 using PixiEditor.ChangeableDocument.Actions;
 using PixiEditor.ChangeableDocument.Actions.Generated;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces.Shapes;
 using PixiEditor.DrawingApi.Core.Surfaces.PaintImpl;
 using PixiEditor.Models.Handlers.Tools;
 using PixiEditor.Numerics;
@@ -8,6 +9,11 @@ namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 #nullable enable
 internal class RasterLineToolExecutor : LineExecutor<ILineToolHandler>
 {
+    protected override bool InitShapeData(IReadOnlyLineData? data)
+    {
+        return false;
+    }
+
     protected override IAction DrawLine(VecI pos)
     {
         return new DrawRasterLine_Action(memberGuid, startPos, pos, StrokeWidth,

+ 29 - 4
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/ShapeToolExecutor.cs

@@ -1,6 +1,8 @@
 using ChunkyImageLib.DataHolders;
 using PixiEditor.Helpers.Extensions;
 using PixiEditor.ChangeableDocument.Actions;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.Models.Handlers;
 using PixiEditor.Models.Handlers.Toolbars;
@@ -38,24 +40,47 @@ internal abstract class ShapeToolExecutor<T> : UpdateableChangeExecutor where T
         IStructureMemberHandler? member = document?.SelectedStructureMember;
         if (colorsVM is null || toolbar is null || member is null)
             return ExecutionState.Error;
-        drawOnMask = member is ILayerHandler layer ? layer.ShouldDrawOnMask : true;
+        drawOnMask = member is not ILayerHandler layer || layer.ShouldDrawOnMask;
         if (drawOnMask && !member.HasMaskBindable)
             return ExecutionState.Error;
         if (!drawOnMask && member is not ILayerHandler)
             return ExecutionState.Error;
 
-        startPos = controller!.LastPixelPosition;
         memberGuid = member.Id;
         
-        OnColorChanged(colorsVM.PrimaryColor, true);
+        if (controller.LeftMousePressed || member is not IVectorLayerHandler)
+        {
+            startPos = controller!.LastPixelPosition;
+            OnColorChanged(colorsVM.PrimaryColor, true);
+            DrawShape(startPos, 0, true);
+        }
+        else
+        {
+            transforming = true;
+            if (member is IVectorLayerHandler)
+            {
+                var node = (VectorLayerNode)internals.Tracker.Document.FindMember(member.Id);
+                if (!InitShapeData(node.ShapeData))
+                {
+                    document.TransformHandler.HideTransform();
+                    return ExecutionState.Error;
+                }
+                
+                toolbar.StrokeColor = node.ShapeData.StrokeColor.ToColor();
+                toolbar.FillColor = node.ShapeData.FillColor.ToColor();
+                toolbar.ToolSize = node.ShapeData.StrokeWidth;
+                toolbar.Fill = node.ShapeData.FillColor != Colors.Transparent;
+            }
+        }
+        
         
-        DrawShape(startPos, 0, true);
         return ExecutionState.Success;
     }
 
     protected abstract void DrawShape(VecI currentPos, double rotationRad, bool firstDraw);
     protected abstract IAction SettingsChangedAction();
     protected abstract IAction TransformMovedAction(ShapeData data, ShapeCorners corners);
+    protected virtual bool InitShapeData(ShapeVectorData data) { return true; }
     protected abstract IAction EndDrawAction();
     protected virtual DocumentTransformMode TransformMode => DocumentTransformMode.Scale_Rotate_NoShear_NoPerspective;
 

+ 12 - 0
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/VectorEllipseToolExecutor.cs

@@ -20,6 +20,18 @@ internal class VectorEllipseToolExecutor : ShapeToolExecutor<IVectorEllipseToolH
     
     private Matrix3X3 lastMatrix = Matrix3X3.Identity;
 
+    protected override bool InitShapeData(ShapeVectorData data)
+    {
+        if (data is not EllipseVectorData ellipseData)
+            return false;
+        
+        firstCenter = ellipseData.Center;
+        firstRadius = ellipseData.Radius;
+        lastMatrix = ellipseData.TransformationMatrix;
+        
+        return true;
+    }
+
     protected override void DrawShape(VecI curPos, double rotationRad, bool firstDraw)
     {
         RectI rect;

+ 13 - 0
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/VectorLineToolExecutor.cs

@@ -1,6 +1,7 @@
 using ChunkyImageLib.DataHolders;
 using PixiEditor.ChangeableDocument.Actions;
 using PixiEditor.ChangeableDocument.Actions.Generated;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces.Shapes;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 using PixiEditor.Models.Handlers.Tools;
 using PixiEditor.Numerics;
@@ -11,6 +12,18 @@ internal class VectorLineToolExecutor : LineExecutor<IVectorLineToolHandler>
 {
     private VecD startPoint;
     private VecD endPoint;
+
+    protected override bool InitShapeData(IReadOnlyLineData? data)
+    {
+        if (data is null)
+            return false;
+
+        startPoint = data.Start;
+        endPoint = data.End;
+
+        return true;
+    }
+
     protected override IAction DrawLine(VecI pos)
     {
         LineVectorData data = new LineVectorData(startPos, pos)

+ 18 - 1
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/VectorRectangleToolExecutor.cs

@@ -20,6 +20,18 @@ internal class VectorRectangleToolExecutor : ShapeToolExecutor<IVectorRectangleT
 
     private Matrix3X3 lastMatrix = Matrix3X3.Identity;
 
+    protected override bool InitShapeData(ShapeVectorData data)
+    {
+        if (data is not RectangleVectorData rectData)
+            return false;
+        
+        firstCenter = rectData.Center;
+        firstSize = rectData.Size;
+        lastMatrix = rectData.TransformationMatrix;
+        
+        return true;
+    }
+
     protected override void DrawShape(VecI curPos, double rotationRad, bool firstDraw)
     {
         RectI rect;
@@ -55,7 +67,12 @@ internal class VectorRectangleToolExecutor : ShapeToolExecutor<IVectorRectangleT
 
     protected override IAction TransformMovedAction(ShapeData data, ShapeCorners corners)
     {
-        RectI rect = (RectI)RectD.FromCenterAndSize(data.Center, data.Size);
+        if (firstCenter == default || firstSize == default)
+        {
+            firstCenter = data.Center;
+            firstSize = data.Size;
+        }
+
         RectD firstRect = RectD.FromCenterAndSize(firstCenter, firstSize);
         Matrix3X3 matrix = OperationHelper.CreateMatrixFromPoints(corners, firstSize);
         matrix = matrix.Concat(Matrix3X3.CreateTranslation(-(float)firstRect.TopLeft.X, -(float)firstRect.TopLeft.Y));

+ 5 - 2
src/PixiEditor/Models/Handlers/IVectorLayerHandler.cs

@@ -1,6 +1,9 @@
-namespace PixiEditor.Models.Handlers;
+using PixiEditor.ChangeableDocument.Changeables.Animations;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
+
+namespace PixiEditor.Models.Handlers;
 
 internal interface IVectorLayerHandler : ILayerHandler
 {
-    
+    public IReadOnlyShapeVectorData? GetShapeData(KeyFrameTime frameTime);
 }

+ 8 - 0
src/PixiEditor/Models/Handlers/Toolbars/ILineToolbar.cs

@@ -0,0 +1,8 @@
+using Avalonia.Media;
+
+namespace PixiEditor.Models.Handlers.Toolbars;
+
+internal interface ILineToolbar : IBasicToolbar
+{
+    public Color StrokeColor { get; set; }
+}

+ 1 - 1
src/PixiEditor/Models/Serialization/Factories/PointsDataSerializationFactory.cs

@@ -5,7 +5,7 @@ using PixiEditor.Numerics;
 
 namespace PixiEditor.Models.Serialization.Factories;
 
-public class PointsDataSerializationFactory : VectorShapeSerializationFactory<PointsVectorData> 
+internal class PointsDataSerializationFactory : VectorShapeSerializationFactory<PointsVectorData> 
 {
     public override string DeserializationId { get; } = "PixiEditor.PointsData";
     protected override void AddSpecificData(ByteBuilder builder, PointsVectorData original)

+ 2 - 1
src/PixiEditor/ViewModels/Document/Nodes/StructureMemberViewModel.cs

@@ -1,5 +1,6 @@
 using ChunkyImageLib.DataHolders;
 using PixiEditor.ChangeableDocument.Actions.Generated;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.Helpers;
@@ -44,7 +45,7 @@ internal abstract class StructureMemberViewModel<T> : NodeViewModel<T>, IStructu
     
     public ShapeCorners TransformationCorners => Internals.Tracker.Document.FindMember(Id)
         ?.GetTransformationCorners(Document.AnimationDataViewModel.ActiveFrameBindable) ?? new ShapeCorners();
-
+    
     public void SetMaskIsVisible(bool maskIsVisible)
     {
         this.maskIsVisible = maskIsVisible;

+ 7 - 0
src/PixiEditor/ViewModels/Document/Nodes/VectorLayerNodeViewModel.cs

@@ -1,4 +1,6 @@
 using PixiEditor.ChangeableDocument.Actions.Generated;
+using PixiEditor.ChangeableDocument.Changeables.Animations;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.Models.Handlers;
 using PixiEditor.ViewModels.Nodes;
@@ -36,4 +38,9 @@ internal class VectorLayerNodeViewModel : StructureMemberViewModel<VectorLayerNo
             OnPropertyChanged(nameof(ShouldDrawOnMask));
         }
     }
+
+    public IReadOnlyShapeVectorData? GetShapeData(KeyFrameTime frameTime)
+    {
+        return ((IReadOnlyVectorNode)Internals.Tracker.Document.FindMember(Id))?.ShapeData;
+    }
 }

+ 26 - 0
src/PixiEditor/ViewModels/Tools/ToolSettings/Toolbars/LineToolbar.cs

@@ -0,0 +1,26 @@
+using Avalonia.Media;
+using PixiEditor.Models.Handlers.Toolbars;
+using PixiEditor.ViewModels.Tools.ToolSettings.Settings;
+
+namespace PixiEditor.ViewModels.Tools.ToolSettings.Toolbars;
+
+internal class LineToolbar : BasicToolbar, ILineToolbar
+{
+    
+    public Color StrokeColor
+    {
+        get
+        {
+            return GetSetting<ColorSettingViewModel>(nameof(StrokeColor)).Value;
+        }
+        set
+        {
+            GetSetting<ColorSettingViewModel>(nameof(StrokeColor)).Value = value;
+        }
+    }
+
+    public LineToolbar()
+    {
+        AddSetting(new ColorSettingViewModel(nameof(StrokeColor), "STROKE_COLOR_LABEL"));
+    }
+}

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

@@ -20,7 +20,7 @@ internal class RasterLineToolViewModel : ShapeTool, ILineToolHandler
     public RasterLineToolViewModel()
     {
         ActionDisplay = defaultActionDisplay;
-        Toolbar = ToolbarFactory.Create<RasterLineToolViewModel, BasicToolbar>(this);
+        Toolbar = ToolbarFactory.Create<RasterLineToolViewModel, LineToolbar>(this);
     }
 
     public override string ToolNameLocalizationKey => "LINE_TOOL";

+ 20 - 0
src/PixiEditor/ViewModels/Tools/Tools/VectorEllipseToolViewModel.cs

@@ -1,7 +1,9 @@
 using Avalonia.Input;
+using ChunkyImageLib.DataHolders;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Commands.Attributes.Commands;
+using PixiEditor.Models.DocumentModels;
 using PixiEditor.Models.Handlers;
 using PixiEditor.Models.Handlers.Tools;
 using PixiEditor.Numerics;
@@ -35,4 +37,22 @@ internal class VectorEllipseToolViewModel : ShapeTool, IVectorEllipseToolHandler
     {
         ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseVectorEllipseTool();
     }
+
+    public override void OnSelected()
+    {
+        var layer = ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.SelectedStructureMember;
+        if (layer is IVectorLayerHandler vectorLayer)
+        {
+            ShapeCorners corners = vectorLayer.TransformationCorners;
+            ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument.TransformViewModel.ShowTransform(
+                DocumentTransformMode.Scale_Rotate_Shear_NoPerspective, false, corners, false);
+        }
+        
+        ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseVectorEllipseTool();
+    }
+
+    public override void OnDeselecting()
+    {
+        ViewModelMain.Current.DocumentManagerSubViewModel.ActiveDocument?.Operations.TryStopToolLinkedExecutor();
+    }
 }

+ 27 - 4
src/PixiEditor/ViewModels/Tools/Tools/VectorLineToolViewModel.cs

@@ -1,9 +1,13 @@
 using Avalonia.Input;
+using ChunkyImageLib.DataHolders;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces.Shapes;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 using PixiEditor.Views.Overlays.BrushShapeOverlay;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Commands.Attributes.Commands;
+using PixiEditor.Models.DocumentModels;
 using PixiEditor.Models.Handlers;
 using PixiEditor.Models.Handlers.Tools;
 using PixiEditor.Numerics;
@@ -20,7 +24,7 @@ internal class VectorLineToolViewModel : ShapeTool, IVectorLineToolHandler
     public VectorLineToolViewModel()
     {
         ActionDisplay = defaultActionDisplay;
-        Toolbar = ToolbarFactory.Create<VectorLineToolViewModel, BasicToolbar>(this);
+        Toolbar = ToolbarFactory.Create<VectorLineToolViewModel, LineToolbar>(this);
     }
 
     public override string ToolNameLocalizationKey => "LINE_TOOL";
@@ -28,10 +32,9 @@ internal class VectorLineToolViewModel : ShapeTool, IVectorLineToolHandler
 
     public override string Icon => PixiPerfectIcons.Line;
     public override Type[]? SupportedLayerTypes { get; } = [];
-    public string? DefaultNewLayerName { get; } = new LocalizedString("NEW_LINE_LAYER_NAME"); 
+    public string? DefaultNewLayerName { get; } = new LocalizedString("NEW_LINE_LAYER_NAME");
 
-    [Settings.Inherited]
-    public int ToolSize => GetValue<int>();
+    [Settings.Inherited] public int ToolSize => GetValue<int>();
 
     public bool Snap { get; private set; }
 
@@ -55,4 +58,24 @@ internal class VectorLineToolViewModel : ShapeTool, IVectorLineToolHandler
     {
         ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseVectorLineTool();
     }
+
+    public override void OnSelected()
+    {
+        var document = ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument;
+        var layer = document.SelectedStructureMember;
+        if (layer is IVectorLayerHandler vectorLayer)
+        {
+            IReadOnlyLineData? lineVectorData = vectorLayer.GetShapeData(document.AnimationDataViewModel.ActiveFrameTime) as IReadOnlyLineData;
+            if (lineVectorData is null) return;
+            
+            document.LineToolOverlayViewModel.Show(lineVectorData.Start, lineVectorData.End);
+        }
+
+        document.Tools.UseVectorLineTool();
+    }
+    
+    public override void OnDeselecting()
+    {
+        ViewModelMain.Current.DocumentManagerSubViewModel.ActiveDocument?.Operations.TryStopToolLinkedExecutor();
+    }
 }

+ 20 - 0
src/PixiEditor/ViewModels/Tools/Tools/VectorRectangleToolViewModel.cs

@@ -1,7 +1,9 @@
 using Avalonia.Input;
+using ChunkyImageLib.DataHolders;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Commands.Attributes.Commands;
+using PixiEditor.Models.DocumentModels;
 using PixiEditor.Models.Handlers;
 using PixiEditor.Models.Handlers.Tools;
 using PixiEditor.Numerics;
@@ -47,4 +49,22 @@ internal class VectorRectangleToolViewModel : ShapeTool, IVectorRectangleToolHan
     {
         ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseVectorRectangleTool();
     }
+
+    public override void OnSelected()
+    {
+        var layer = ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.SelectedStructureMember;
+        if (layer is IVectorLayerHandler vectorLayer)
+        {
+            ShapeCorners corners = vectorLayer.TransformationCorners;
+            ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument.TransformViewModel.ShowTransform(
+                DocumentTransformMode.Scale_Rotate_Shear_NoPerspective, false, corners, false);
+        }
+        
+        ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseVectorRectangleTool();
+    }
+
+    public override void OnDeselecting()
+    {
+        ViewModelMain.Current.DocumentManagerSubViewModel.ActiveDocument?.Operations.TryStopToolLinkedExecutor();
+    }
 }