Browse Source

Basic setup

flabbet 9 months ago
parent
commit
1d6677ad46

+ 8 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/Shapes/IReadOnlyPathData.cs

@@ -0,0 +1,8 @@
+using Drawie.Backend.Core.Surfaces.Vector;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces.Shapes;
+
+public interface IReadOnlyPathData : IReadOnlyShapeVectorData
+{
+    public VectorPath Path { get; }
+}

+ 0 - 37
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/EllipseVectorData.cs

@@ -61,43 +61,6 @@ public class EllipseVectorData : ShapeVectorData, IReadOnlyEllipseData
         {
         {
             drawingSurface.Canvas.RestoreToCount(saved);
             drawingSurface.Canvas.RestoreToCount(saved);
         }
         }
-
-        // Do not remove below, it might be used (directly or as a reference) for pixelated rendering
-        /*var imageSize = (VecI)(Radius * 2);
-
-        using ChunkyImage img = new ChunkyImage((VecI)GeometryAABB.Size);
-
-        RectD rotated = new ShapeCorners(RectD.FromTwoPoints(VecD.Zero, imageSize)).AABBBounds;
-
-        VecI shift = new VecI((int)Math.Floor(-rotated.Left), (int)Math.Floor(-rotated.Top));
-        RectI drawRect = new(shift, imageSize);
-
-        img.EnqueueDrawEllipse(drawRect, StrokeColor, FillColor, StrokeWidth);
-        img.CommitChanges();
-
-        VecI topLeft = new VecI((int)Math.Round(Center.X - Radius.X), (int)Math.Round(Center.Y - Radius.Y)) - shift;
-        topLeft = (VecI)(topLeft * resolution.Multiplier());
-
-        RectI region = new(VecI.Zero, (VecI)GeometryAABB.Size);
-
-        int num = 0;
-        if (applyTransform)
-        {
-            num = drawingSurface.Canvas.Save();
-            Matrix3X3 final = TransformationMatrix with
-            {
-                TransX = TransformationMatrix.TransX * (float)resolution.Multiplier(),
-                TransY = TransformationMatrix.TransY * (float)resolution.Multiplier()
-            };
-            drawingSurface.Canvas.SetMatrix(final);
-        }
-
-        img.DrawMostUpToDateRegionOn(region, resolution, drawingSurface, topLeft, paint);
-
-        if (applyTransform)
-        {
-            drawingSurface.Canvas.RestoreToCount(num);
-        }*/
     }
     }
     
     
     public override bool IsValid()
     public override bool IsValid()

+ 0 - 49
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/LineVectorData.cs

@@ -67,55 +67,6 @@ public class LineVectorData(VecD startPos, VecD pos) : ShapeVectorData, IReadOnl
         {
         {
             drawingSurface.Canvas.RestoreToCount(num);
             drawingSurface.Canvas.RestoreToCount(num);
         }
         }
-
-        /*
-        RectD adjustedAABB = GeometryAABB.RoundOutwards();
-        adjustedAABB = adjustedAABB with { Size = adjustedAABB.Size + new VecD(1, 1) };
-        var imageSize = (VecI)adjustedAABB.Size;
-
-        using ChunkyImage img = new ChunkyImage(imageSize);
-
-        if (StrokeWidth == 1)
-        {
-            VecD adjustment = new VecD(0.5, 0.5);
-
-            img.EnqueueDrawBresenhamLine(
-                (VecI)(Start - adjustedAABB.TopLeft - adjustment),
-                (VecI)(End - adjustedAABB.TopLeft - adjustment), StrokeColor, BlendMode.SrcOver);
-        }
-        else
-        {
-            img.EnqueueDrawSkiaLine(
-                (VecI)Start.Round() - (VecI)adjustedAABB.TopLeft,
-                (VecI)End.Round() - (VecI)adjustedAABB.TopLeft, StrokeCap.Butt, StrokeWidth, StrokeColor, BlendMode.SrcOver);
-        }
-
-        img.CommitChanges();
-
-        VecI topLeft = (VecI)(adjustedAABB.TopLeft * resolution.Multiplier());
-
-        RectI region = new(VecI.Zero, imageSize);
-
-        int num = 0;
-
-        if (applyTransform)
-        {
-            num = drawingSurface.Canvas.Save();
-            Matrix3X3 final = TransformationMatrix with
-            {
-                TransX = TransformationMatrix.TransX * (float)resolution.Multiplier(),
-                TransY = TransformationMatrix.TransY * (float)resolution.Multiplier()
-            };
-            drawingSurface.Canvas.SetMatrix(final);
-        }
-
-        img.DrawMostUpToDateRegionOn(region, resolution, drawingSurface, topLeft, paint);
-
-        if (applyTransform)
-        {
-            drawingSurface.Canvas.RestoreToCount(num);
-        }
-    */
     }
     }
 
 
     public override bool IsValid()
     public override bool IsValid()

+ 83 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/PathVectorData.cs

@@ -0,0 +1,83 @@
+using Drawie.Backend.Core.ColorsImpl;
+using Drawie.Backend.Core.Surfaces;
+using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Backend.Core.Surfaces.Vector;
+using Drawie.Numerics;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces.Shapes;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
+
+public class PathVectorData : ShapeVectorData, IReadOnlyPathData
+{
+    public VectorPath Path { get; }
+    public override RectD GeometryAABB => Path.Bounds.Inflate(StrokeWidth);
+
+    public override ShapeCorners TransformationCorners =>
+        new ShapeCorners(GeometryAABB).WithMatrix(TransformationMatrix);
+
+    public PathVectorData(VectorPath path)
+    {
+        Path = path;
+    }
+
+    public override void RasterizeGeometry(DrawingSurface drawingSurface)
+    {
+        Rasterize(drawingSurface, false);
+    }
+
+    public override void RasterizeTransformed(DrawingSurface drawingSurface)
+    {
+        Rasterize(drawingSurface, true);
+    }
+
+    private void Rasterize(DrawingSurface drawingSurface, bool applyTransform)
+    {
+        int num = 0;
+        if (applyTransform)
+        {
+            num = drawingSurface.Canvas.Save();
+            ApplyTransformTo(drawingSurface);
+        }
+
+        using Paint paint = new Paint() { IsAntiAliased = true };
+
+        if (FillColor.A > 0)
+        {
+            paint.Color = FillColor;
+            paint.Style = PaintStyle.Fill;
+
+            drawingSurface.Canvas.DrawPath(Path, paint);
+        }
+
+        paint.Color = StrokeColor;
+        paint.Style = PaintStyle.Stroke;
+        paint.StrokeWidth = StrokeWidth;
+
+        drawingSurface.Canvas.DrawPath(Path, paint);
+
+        if (applyTransform)
+        {
+            drawingSurface.Canvas.RestoreToCount(num);
+        }
+    }
+
+    public override bool IsValid()
+    {
+        return Path is { IsEmpty: false };
+    }
+
+    public override int GetCacheHash()
+    {
+        return Path.GetHashCode();
+    }
+
+    public override int CalculateHash()
+    {
+        return Path.GetHashCode();
+    }
+
+    public override object Clone()
+    {
+        return new PathVectorData(new VectorPath(Path));
+    }
+}

+ 0 - 31
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/RectangleVectorData.cs

@@ -59,37 +59,6 @@ public class RectangleVectorData : ShapeVectorData, IReadOnlyRectangleData
         {
         {
             drawingSurface.Canvas.RestoreToCount(saved);
             drawingSurface.Canvas.RestoreToCount(saved);
         }
         }
-        /*var imageSize = (VecI)Size; 
-
-        using ChunkyImage img = new ChunkyImage(imageSize);
-
-        RectI drawRect = (RectI)RectD.FromTwoPoints(VecD.Zero, Size).RoundOutwards();
-
-        ShapeData data = new ShapeData(drawRect.Center, drawRect.Size, 0, StrokeWidth, StrokeColor, FillColor);
-        img.EnqueueDrawRectangle(data);
-        img.CommitChanges();
-        
-        VecI topLeft = (VecI)((Center - Size / 2) * resolution.Multiplier());
-        RectI region = new(VecI.Zero, (VecI)GeometryAABB.Size);
-
-        int num = 0;
-        if (applyTransform)
-        {
-            num = drawingSurface.Canvas.Save();
-            Matrix3X3 final = TransformationMatrix with
-            {
-                TransX = TransformationMatrix.TransX * (float)resolution.Multiplier(),
-                TransY = TransformationMatrix.TransY * (float)resolution.Multiplier()
-            };
-            drawingSurface.Canvas.SetMatrix(final);
-        }
-
-        img.DrawMostUpToDateRegionOn(region, resolution, drawingSurface, topLeft, paint);
-        
-        if (applyTransform)
-        {
-            drawingSurface.Canvas.RestoreToCount(num);
-        }*/
     }
     }
 
 
     public override bool IsValid()
     public override bool IsValid()

+ 2 - 1
src/PixiEditor/Data/Configs/ToolSetsConfig.json

@@ -101,7 +101,8 @@
       "Move",
       "Move",
       "VectorLine",
       "VectorLine",
       "VectorEllipse",
       "VectorEllipse",
-      "VectorRectangle"
+      "VectorRectangle",
+      "VectorPath"
     ]
     ]
   }
   }
 ]
 ]

+ 1 - 0
src/PixiEditor/Helpers/ServiceCollectionHelpers.cs

@@ -98,6 +98,7 @@ internal static class ServiceCollectionHelpers
             .AddTool<IVectorEllipseToolHandler, VectorEllipseToolViewModel>()
             .AddTool<IVectorEllipseToolHandler, VectorEllipseToolViewModel>()
             .AddTool<IVectorRectangleToolHandler, VectorRectangleToolViewModel>()
             .AddTool<IVectorRectangleToolHandler, VectorRectangleToolViewModel>()
             .AddTool<IVectorLineToolHandler, VectorLineToolViewModel>()
             .AddTool<IVectorLineToolHandler, VectorLineToolViewModel>()
+            .AddTool<IVectorPathToolHandler, VectorPathToolViewModel>()
             .AddTool<ZoomToolViewModel>()
             .AddTool<ZoomToolViewModel>()
             // File types
             // File types
             .AddSingleton<IoFileType, PixiFileType>()
             .AddSingleton<IoFileType, PixiFileType>()

+ 2 - 0
src/PixiEditor/Models/DocumentModels/Public/DocumentToolsModule.cs

@@ -74,4 +74,6 @@ internal class DocumentToolsModule
     public void UseLassoTool() => Internals.ChangeController.TryStartExecutor<LassoToolExecutor>();
     public void UseLassoTool() => Internals.ChangeController.TryStartExecutor<LassoToolExecutor>();
 
 
     public void UseMagicWandTool() => Internals.ChangeController.TryStartExecutor<MagicWandToolExecutor>();
     public void UseMagicWandTool() => Internals.ChangeController.TryStartExecutor<MagicWandToolExecutor>();
+
+    public void UseVectorPathTool() => Internals.ChangeController.TryStartExecutor<VectorPathToolExecutor>();
 }
 }

+ 9 - 14
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/ComplexShapeToolExecutor.cs

@@ -9,6 +9,7 @@ using PixiEditor.Models.Handlers.Toolbars;
 using PixiEditor.Models.Handlers.Tools;
 using PixiEditor.Models.Handlers.Tools;
 using PixiEditor.Models.Tools;
 using PixiEditor.Models.Tools;
 using Drawie.Numerics;
 using Drawie.Numerics;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 
 
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 
 
@@ -67,25 +68,19 @@ internal abstract class ComplexShapeToolExecutor<T> : SimpleShapeToolExecutor wh
             return ExecutionState.Success;
             return ExecutionState.Success;
         }
         }
 
 
-        if (member is IVectorLayerHandler)
+        if (member is IVectorLayerHandler vectorLayerHandler)
         {
         {
-            var node = (VectorLayerNode)internals.Tracker.Document.FindMember(member.Id);
-
-            if (node == null)
-            {
-                return ExecutionState.Error;
-            }
-
-            if (node.ShapeData == null || !InitShapeData(node.ShapeData))
+            var shapeData = vectorLayerHandler.GetShapeData(document.AnimationHandler.ActiveFrameTime);
+            if (shapeData == null || !InitShapeData(shapeData))
             {
             {
                 ActiveMode = ShapeToolMode.Preview;
                 ActiveMode = ShapeToolMode.Preview;
                 return ExecutionState.Success;
                 return ExecutionState.Success;
             }
             }
 
 
-            toolbar.StrokeColor = node.ShapeData.StrokeColor.ToColor();
-            toolbar.FillColor = node.ShapeData.FillColor.ToColor();
-            toolbar.ToolSize = node.ShapeData.StrokeWidth;
-            toolbar.Fill = node.ShapeData.FillColor != Colors.Transparent;
+            toolbar.StrokeColor = shapeData.StrokeColor.ToColor();
+            toolbar.FillColor = shapeData.FillColor.ToColor();
+            toolbar.ToolSize = shapeData.StrokeWidth;
+            toolbar.Fill = shapeData.FillColor != Colors.Transparent;
             ActiveMode = ShapeToolMode.Transform;
             ActiveMode = ShapeToolMode.Transform;
         }
         }
         else
         else
@@ -99,7 +94,7 @@ internal abstract class ComplexShapeToolExecutor<T> : SimpleShapeToolExecutor wh
     protected abstract void DrawShape(VecI currentPos, double rotationRad, bool firstDraw);
     protected abstract void DrawShape(VecI currentPos, double rotationRad, bool firstDraw);
     protected abstract IAction SettingsChangedAction();
     protected abstract IAction SettingsChangedAction();
     protected abstract IAction TransformMovedAction(ShapeData data, ShapeCorners corners);
     protected abstract IAction TransformMovedAction(ShapeData data, ShapeCorners corners);
-    protected virtual bool InitShapeData(ShapeVectorData data) { return true; }
+    protected virtual bool InitShapeData(IReadOnlyShapeVectorData data) { return true; }
     protected abstract IAction EndDrawAction();
     protected abstract IAction EndDrawAction();
     protected virtual DocumentTransformMode TransformMode => DocumentTransformMode.Scale_Rotate_NoShear_NoPerspective;
     protected virtual DocumentTransformMode TransformMode => DocumentTransformMode.Scale_Rotate_NoShear_NoPerspective;
 
 

+ 2 - 1
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/VectorEllipseToolExecutor.cs

@@ -7,6 +7,7 @@ using Drawie.Backend.Core.Numerics;
 using PixiEditor.Models.Handlers.Tools;
 using PixiEditor.Models.Handlers.Tools;
 using PixiEditor.Models.Tools;
 using PixiEditor.Models.Tools;
 using Drawie.Numerics;
 using Drawie.Numerics;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 
 
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 
 
@@ -20,7 +21,7 @@ internal class VectorEllipseToolExecutor : ComplexShapeToolExecutor<IVectorEllip
     
     
     private Matrix3X3 lastMatrix = Matrix3X3.Identity;
     private Matrix3X3 lastMatrix = Matrix3X3.Identity;
 
 
-    protected override bool InitShapeData(ShapeVectorData data)
+    protected override bool InitShapeData(IReadOnlyShapeVectorData data)
     {
     {
         if (data is not EllipseVectorData ellipseData)
         if (data is not EllipseVectorData ellipseData)
             return false;
             return false;

+ 98 - 0
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/VectorPathToolExecutor.cs

@@ -0,0 +1,98 @@
+using Avalonia.Media;
+using Drawie.Backend.Core.Surfaces.Vector;
+using Drawie.Numerics;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
+using PixiEditor.Models.Handlers;
+using PixiEditor.Models.Handlers.Tools;
+using PixiEditor.ChangeableDocument.Actions.Generated;
+using PixiEditor.Helpers.Extensions;
+using PixiEditor.Models.Controllers.InputDevice;
+using PixiEditor.Models.Handlers.Toolbars;
+using PixiEditor.Models.Tools;
+using Color = Drawie.Backend.Core.ColorsImpl.Color;
+using Colors = Drawie.Backend.Core.ColorsImpl.Colors;
+
+namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
+
+internal class VectorPathToolExecutor : UpdateableChangeExecutor
+{
+    private IStructureMemberHandler member;
+    private VectorPath startingPath;
+    private IVectorPathToolHandler vectorPathToolHandler;
+    private IBasicShapeToolbar toolbar;
+
+    public override ExecutionState Start()
+    {
+        vectorPathToolHandler = GetHandler<IVectorPathToolHandler>();
+
+        member = document.SelectedStructureMember;
+
+        if (member is null)
+        {
+            return ExecutionState.Error;
+        }
+
+        toolbar = (IBasicShapeToolbar)vectorPathToolHandler.Toolbar;
+
+        if (member is IVectorLayerHandler vectorLayerHandler)
+        {
+            var shapeData = vectorLayerHandler.GetShapeData(document.AnimationHandler.ActiveFrameTime);
+            if (shapeData is PathVectorData pathData)
+            {
+                startingPath = pathData.Path;
+            }
+            else if (shapeData is null)
+            {
+                startingPath = new VectorPath();
+            }
+            else
+            {
+                return ExecutionState.Error;
+            }
+
+            startingPath.MoveTo((VecF)controller.LastPrecisePosition);
+            internals.ActionAccumulator.AddActions(new SetShapeGeometry_Action(member.Id,
+                new PathVectorData(new VectorPath(startingPath))));
+        }
+
+        return ExecutionState.Success;
+    }
+
+    public override void OnLeftMouseButtonDown(MouseOnCanvasEventArgs args)
+    {
+        startingPath.LineTo((VecF)args.PositionOnCanvas);
+        PathVectorData vectorData = new PathVectorData(new VectorPath(startingPath))
+        {
+            StrokeWidth = toolbar.ToolSize,
+            StrokeColor = toolbar.StrokeColor.ToColor(),
+            FillColor = toolbar.Fill ? toolbar.FillColor.ToColor() : Colors.Transparent,
+        };
+
+        internals.ActionAccumulator.AddActions(new SetShapeGeometry_Action(member.Id, vectorData));
+    }
+
+    public override void OnColorChanged(Color color, bool primary)
+    {
+        if (primary && toolbar.SyncWithPrimaryColor)
+        {
+            toolbar.StrokeColor = color.ToColor();
+            toolbar.FillColor = color.ToColor();
+        }
+    }
+
+    public override void OnSettingsChanged(string name, object value)
+    {
+        internals.ActionAccumulator.AddActions(new SetShapeGeometry_Action(member.Id,
+            new PathVectorData(new VectorPath(startingPath))
+            {
+                StrokeWidth = toolbar.ToolSize,
+                StrokeColor = toolbar.StrokeColor.ToColor(),
+                FillColor = toolbar.Fill ? toolbar.FillColor.ToColor() : Colors.Transparent,
+            }));
+    }
+
+    public override void ForceStop()
+    {
+        internals.ActionAccumulator.AddActions(new EndSetShapeGeometry_Action());
+    }
+}

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

@@ -7,6 +7,7 @@ using Drawie.Backend.Core.Numerics;
 using PixiEditor.Models.Handlers.Tools;
 using PixiEditor.Models.Handlers.Tools;
 using PixiEditor.Models.Tools;
 using PixiEditor.Models.Tools;
 using Drawie.Numerics;
 using Drawie.Numerics;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 
 
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 
 
@@ -20,7 +21,7 @@ internal class VectorRectangleToolExecutor : ComplexShapeToolExecutor<IVectorRec
 
 
     private Matrix3X3 lastMatrix = Matrix3X3.Identity;
     private Matrix3X3 lastMatrix = Matrix3X3.Identity;
 
 
-    protected override bool InitShapeData(ShapeVectorData data)
+    protected override bool InitShapeData(IReadOnlyShapeVectorData data)
     {
     {
         if (data is not RectangleVectorData rectData)
         if (data is not RectangleVectorData rectData)
             return false;
             return false;

+ 6 - 0
src/PixiEditor/Models/Handlers/Tools/IVectorPathToolHandler.cs

@@ -0,0 +1,6 @@
+namespace PixiEditor.Models.Handlers.Tools;
+
+internal interface IVectorPathToolHandler : IToolHandler
+{
+    
+}

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

@@ -0,0 +1,20 @@
+using Drawie.Numerics;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.Extensions.Common.Localization;
+using PixiEditor.Models.Handlers;
+using PixiEditor.Models.Handlers.Tools;
+
+namespace PixiEditor.ViewModels.Tools.Tools;
+
+internal class VectorPathToolViewModel : ShapeTool, IVectorPathToolHandler
+{
+    public override string ToolNameLocalizationKey => "PATH_TOOL";
+    public override Type[]? SupportedLayerTypes { get; } = [typeof(IVectorLayerHandler)];
+    public override Type LayerTypeToCreateOnEmptyUse { get; } = typeof(VectorLayerNode);
+    public override LocalizedString Tooltip => new LocalizedString("PATH_TOOL_TOOLTIP", Shortcut);
+
+    public override void UseTool(VecD pos)
+    {
+        ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseVectorPathTool();
+    }
+}

+ 1 - 1
src/PixiEditor/Views/Main/Tools/ToolPickerButton.axaml

@@ -17,7 +17,7 @@
     <Button Command="{xaml:Command PixiEditor.Tools.SelectTool, UseProvided=true}"
     <Button Command="{xaml:Command PixiEditor.Tools.SelectTool, UseProvided=true}"
             CommandParameter="{Binding}"
             CommandParameter="{Binding}"
             Width="44" Height="34"
             Width="44" Height="34"
-            ui:Translator.TooltipKey="{Binding DisplayName}"
+            ui:Translator.TooltipLocalizedString="{Binding Tooltip}"
             Background="{DynamicResource ThemeBackgroundBrush1}">
             Background="{DynamicResource ThemeBackgroundBrush1}">
         <Button.Template>
         <Button.Template>
             <ControlTemplate>
             <ControlTemplate>