Răsfoiți Sursa

AutoPosition and optimizations

Krzysztof Krysiński 20 ore în urmă
părinte
comite
a4001e74e4

+ 8 - 4
src/PixiEditor.ChangeableDocument/Changeables/Brushes/BrushEngine.cs

@@ -110,8 +110,11 @@ internal class BrushEngine
         }
 
 
-        path.Offset(vectorShape.TransformedAABB.Pos - vectorShape.GeometryAABB.Pos);
-        path.Offset(rect.Center - path.Bounds.Center);
+        if (brushNode.AutoPosition.Value)
+        {
+            path.Offset(vectorShape.TransformedAABB.Pos - vectorShape.GeometryAABB.Pos);
+            path.Offset(rect.Center - path.Bounds.Center);
+        }
 
         if (brushNode.FitToStrokeSize.Value)
         {
@@ -122,8 +125,9 @@ internal class BrushEngine
             }
 
             VecD uniformScale = new VecD(Math.Min(scale.X, scale.Y));
-            path.Transform(Matrix3X3.CreateScale((float)uniformScale.X, (float)uniformScale.Y, (float)rect.Center.X,
-                (float)rect.Center.Y));
+            VecD center = brushNode.AutoPosition.Value ? rect.Center : vectorShape.TransformedAABB.Center;
+            path.Transform(Matrix3X3.CreateScale((float)uniformScale.X, (float)uniformScale.Y, (float)center.X,
+                (float)center.Y));
         }
 
         var pressure = brushNode.Pressure.Value;

+ 16 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Context/FuncContext.cs

@@ -92,13 +92,28 @@ public class FuncContext
         if (!HasContext && first is Int1 firstInt && second is Int1 secondInt)
         {
             Int2 constantInt = new Int2("");
-            constantInt.ConstantValue = new VecI(firstInt.ConstantValue, secondInt.ConstantValue);
+            constantInt.ConstantValue = new VecI(GetIntConstant(firstInt), GetIntConstant(secondInt));
             return constantInt;
         }
 
         return Builder.ConstructInt2(first, second);
     }
 
+    private static int GetIntConstant(Int1 int1)
+    {
+        object constant = int1.GetConstant();
+        return constant switch
+        {
+            int i => i,
+            double d => (int)d,
+            float f => (int)f,
+            long l => (int)l,
+            byte b => b,
+            short s => s,
+            _ => 0
+        };
+    }
+
     public Half4 NewHalf4(Expression r, Expression g, Expression b, Expression a)
     {
         if (!HasContext && r is Float1 firstFloat && g is Float1 secondFloat && b is Float1 thirdFloat &&

+ 3 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/NodeGraph.cs

@@ -151,7 +151,9 @@ public class NodeGraph : IReadOnlyNodeGraph, IDisposable
     public int GetCacheHash()
     {
         HashCode hash = new();
-        foreach (var node in Nodes)
+        var queue = CalculateExecutionQueueInternal(OutputNode);
+
+        foreach (var node in queue)
         {
             hash.Add(node.GetCacheHash());
         }

+ 4 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Brushes/BrushOutputNode.cs

@@ -7,9 +7,10 @@ using PixiEditor.ChangeableDocument.Rendering;
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Brushes;
 
-[NodeInfo("BrushOutput")]
+[NodeInfo(NodeId)]
 public class BrushOutputNode : Node
 {
+    public const string NodeId = "BrushOutput";
     public InputProperty<ShapeVectorData> VectorShape { get; }
     public InputProperty<Paintable> Stroke { get; }
     public InputProperty<Paintable> Fill { get; }
@@ -17,6 +18,7 @@ public class BrushOutputNode : Node
     public InputProperty<Matrix3X3> Transform { get; }
     public InputProperty<float> Pressure { get; }
     public InputProperty<bool> FitToStrokeSize { get; }
+    public InputProperty<bool> AutoPosition { get; }
     public InputProperty<bool> AllowSampleStacking { get; }
 
     internal Texture ContentTexture;
@@ -35,6 +37,7 @@ public class BrushOutputNode : Node
 
         Pressure = CreateInput<float>("Pressure", "PRESSURE", 1f);
         FitToStrokeSize = CreateInput<bool>("FitToStrokeSize", "FIT_TO_STROKE_SIZE", true);
+        AutoPosition = CreateInput<bool>("AutoPosition", "AUTO_POSITION", true);
         AllowSampleStacking = CreateInput<bool>("AllowSampleStacking", "ALLOW_SAMPLE_STACKING", false);
     }
 

+ 13 - 3
src/PixiEditor.ChangeableDocument/Changes/NodeGraph/ConversionTable.cs

@@ -67,18 +67,22 @@ public static class ConversionTable
                 ]
             },
             {
-                typeof(Vec3D),[
+                typeof(Vec3D), [
                     (typeof(double), new TypeConverter<Vec3D, double>(v => v.X)),
                     (typeof(int), new TypeConverter<Vec3D, int>(v => (int)v.X)),
                     (typeof(VecD), new TypeConverter<Vec3D, VecD>(v => new VecD(v.X, v.Y))),
                     (typeof(VecI), new TypeConverter<Vec3D, VecI>(v => new VecI((int)v.X, (int)v.Y))),
-                    (typeof(Color), new TypeConverter<Vec3D, Color>(v => new Color((byte)Math.Clamp(v.X, 0, 255), (byte)Math.Clamp(v.Y, 0, 255), (byte)Math.Clamp(v.Z, 0, 255)))),
+                    (typeof(Color),
+                        new TypeConverter<Vec3D, Color>(v => new Color((byte)Math.Clamp(v.X, 0, 255),
+                            (byte)Math.Clamp(v.Y, 0, 255), (byte)Math.Clamp(v.Z, 0, 255)))),
                 ]
             },
             {
                 typeof(Texture), [
                     (typeof(Paintable), new TypeConverter<Texture, Paintable>(img => new TexturePaintable(img))),
-                    (typeof(Painter), new TypeConverter<Texture, Painter>(img => new Painter((c, s) => s.Canvas.DrawSurface(img.DrawingSurface, 0, 0)))),
+                    (typeof(Painter),
+                        new TypeConverter<Texture, Painter>(img =>
+                            new Painter((c, s) => s.Canvas.DrawSurface(img.DrawingSurface, 0, 0)))),
                 ]
             }
         };
@@ -125,6 +129,12 @@ public static class ConversionTable
 
         try
         {
+            if (!arg.GetType().IsValueType && targetType.IsValueType)
+            {
+                result = null;
+                return false;
+            }
+
             result = System.Convert.ChangeType(arg, targetType);
             return true;
         }

+ 6 - 0
src/PixiEditor/Models/Controllers/BrushLibrary.cs

@@ -73,4 +73,10 @@ internal class BrushLibrary
         LoadBuiltIn();
         LoadBrushesFromPath(pathToBrushes);
     }
+
+    public void Add(Brush brush)
+    {
+        if (!brushes.Contains(brush))
+            brushes.Add(brush);
+    }
 }

+ 16 - 0
src/PixiEditor/Models/DocumentModels/DocumentUpdater.cs

@@ -24,12 +24,16 @@ using PixiEditor.Models.Handlers;
 using PixiEditor.Models.Layers;
 using Drawie.Numerics;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Context;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Brushes;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Workspace;
+using PixiEditor.Models.BrushEngine;
 using PixiEditor.Models.Dialogs;
 using PixiEditor.Models.DocumentModels.UpdateableChangeExecutors.Features;
+using PixiEditor.ViewModels;
 using PixiEditor.ViewModels.Document;
 using PixiEditor.ViewModels.Document.Nodes;
 using PixiEditor.ViewModels.Nodes;
+using PixiEditor.ViewModels.SubViewModels;
 
 namespace PixiEditor.Models.DocumentModels;
 #nullable enable
@@ -179,6 +183,7 @@ internal class DocumentUpdater
                 break;
             case CreateNode_ChangeInfo info:
                 ProcessCreateNode(info);
+                ProcessCreateBrushNodeIfNeeded(info);
                 break;
             case DeleteNode_ChangeInfo info:
                 ProcessDeleteNode(info);
@@ -931,4 +936,15 @@ internal class DocumentUpdater
 
         property.InternalSetComputedValue(finalValue);
     }
+
+    private void ProcessCreateBrushNodeIfNeeded(CreateNode_ChangeInfo info)
+    {
+        if(info.InternalName != "PixiEditor." + BrushOutputNode.NodeId) return;
+
+        if (ViewModelMain.Current.ToolsSubViewModel is ToolsViewModel toolsHandler)
+        {
+            if(ViewModelMain.Current.DocumentManagerSubViewModel.Documents.All(x => x.Id != doc.Id)) return;
+            toolsHandler.BrushLibrary.Add(new Brush(!string.IsNullOrWhiteSpace(doc.FullFilePath) ? Path.GetFileName(doc.FullFilePath) : "Unnamed", doc));
+        }
+    }
 }

+ 3 - 3
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/PenToolExecutor.cs

@@ -94,7 +94,7 @@ internal class PenToolExecutor : UpdateableChangeExecutor
             internals!.ActionAccumulator.AddActions(action);
         }
 
-        handler.FinalBrushShape = vectorShapeInput.Value?.ToPath(true);
+        handler.FinalBrushShape = vectorShapeInput?.Value?.ToPath(true);
 
         return ExecutionState.Success;
     }
@@ -158,7 +158,7 @@ internal class PenToolExecutor : UpdateableChangeExecutor
                 });
         }
 
-        handler.FinalBrushShape = vectorShapeInput?.Value.ToPath(true);
+        handler.FinalBrushShape = vectorShapeInput?.Value?.ToPath(true);
     }
 
     public override void OnPixelPositionChange(VecI pos, MouseOnCanvasEventArgs args)
@@ -180,7 +180,7 @@ internal class PenToolExecutor : UpdateableChangeExecutor
     public override void OnConvertedKeyDown(Key key)
     {
         base.OnConvertedKeyDown(key);
-        handler.FinalBrushShape = vectorShapeInput.Value?.ToPath(true);
+        handler.FinalBrushShape = vectorShapeInput?.Value?.ToPath(true);
     }
 
     public override void OnLeftMouseButtonUp(VecD argsPositionOnCanvas)

+ 1 - 0
src/PixiEditor/Models/Handlers/IDocument.cs

@@ -25,6 +25,7 @@ namespace PixiEditor.Models.Handlers;
 internal interface IDocument : IHandler, Extensions.CommonApi.Documents.IDocument
 {
     public Guid Id { get; }
+    public string FullFilePath { get; }
     public ObservableRangeCollection<PaletteColor> Palette { get; set; }
     public VecI SizeBindable { get; }
     public IStructureMemberHandler? SelectedStructureMember { get; }