Browse Source

Added bunch of matrix nodes and tile node

Krzysztof Krysiński 5 months ago
parent
commit
3c87660627

+ 1 - 1
src/Drawie

@@ -1 +1 @@
-Subproject commit 2bd4d8535c152c9507c96e1d550b854c80f3b6fd
+Subproject commit 319522cc5845845e9d639d2508b5bc986b100219

+ 3 - 6
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/FilterNodes/ApplyFilterNode.cs

@@ -25,12 +25,12 @@ public class ApplyFilterNode : RenderNode, IRenderInput
 
     protected override void OnPaint(RenderContext context, DrawingSurface surface)
     {
-        if (Background.Value == null || Filter.Value == null || _paint == null)
+        if (_paint == null)
             return;
 
         _paint.SetFilters(Filter.Value);
         int layer = surface.Canvas.SaveLayer(_paint);
-        Background.Value.Paint(context, surface);
+        Background.Value?.Paint(context, surface);
 
         surface.Canvas.RestoreToCount(layer);
     }
@@ -43,11 +43,8 @@ public class ApplyFilterNode : RenderNode, IRenderInput
     public override bool RenderPreview(DrawingSurface renderOn, RenderContext context,
         string elementToRenderName)
     {
-        if (Background.Value == null)
-            return false;
-
         int layer = renderOn.Canvas.SaveLayer(_paint);
-        Background.Value.Paint(context, renderOn);
+        Background.Value?.Paint(context, renderOn);
         renderOn.Canvas.RestoreToCount(layer);
 
         return true;

+ 61 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Matrix/Matrix3X3BaseNode.cs

@@ -0,0 +1,61 @@
+using Drawie.Backend.Core.Numerics;
+using Drawie.Backend.Core.Surfaces;
+using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Numerics;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
+using PixiEditor.ChangeableDocument.Rendering;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Matrix;
+
+public abstract class Matrix3X3BaseNode : RenderNode, IRenderInput
+{
+    public RenderInputProperty Background { get; }
+    public InputProperty<Matrix3X3> Input { get; }
+    public OutputProperty<Matrix3X3> Matrix { get; }
+
+    private Paint? paint;
+
+    public Matrix3X3BaseNode()
+    {
+        Background = CreateRenderInput("Background", "IMAGE");
+        Input = CreateInput("Input", "INPUT_MATRIX", Matrix3X3.Identity);
+        Matrix = CreateOutput("Matrix", "OUTPUT_MATRIX", Matrix3X3.Identity);
+        Output.FirstInChain = null;
+        AllowHighDpiRendering = true;
+    }
+
+    protected override void OnExecute(RenderContext context)
+    {
+        Matrix.Value = CalculateMatrix(Input.Value);
+        if (Background.Value == null)
+            return;
+
+        paint ??= new();
+        base.OnExecute(context);
+    }
+
+    protected override void OnPaint(RenderContext context, DrawingSurface surface)
+    {
+        if (paint == null)
+            return;
+
+        int layer = surface.Canvas.Save();
+
+        surface.Canvas.SetMatrix(surface.Canvas.TotalMatrix.Concat(Matrix.Value));
+        Background.Value?.Paint(context, surface);
+
+        surface.Canvas.RestoreToCount(layer);
+    }
+
+    protected abstract Matrix3X3 CalculateMatrix(Matrix3X3 input);
+
+    public override RectD? GetPreviewBounds(int frame, string elementToRenderName = "")
+    {
+        return null;
+    }
+
+    public override bool RenderPreview(DrawingSurface renderOn, RenderContext context, string elementToRenderName)
+    {
+        return false;
+    }
+}

+ 6 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Matrix/MatrixNode.cs

@@ -0,0 +1,6 @@
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Matrix;
+
+public class MatrixNode
+{
+
+}

+ 43 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Matrix/RotateNode.cs

@@ -0,0 +1,43 @@
+using Drawie.Backend.Core.Numerics;
+using Drawie.Numerics;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Matrix;
+
+[NodeInfo("Rotate")]
+public class RotateNode : Matrix3X3BaseNode
+{
+    public InputProperty<RotationType> RotationType { get; }
+    public InputProperty<double> Angle { get; }
+    public InputProperty<VecD> Center { get; }
+
+    public RotateNode()
+    {
+        RotationType = CreateInput("RotationType", "ROTATION_TYPE", Nodes.Matrix.RotationType.Degrees);
+        Angle = CreateInput("Angle", "ANGLE", 0.0);
+        Center = CreateInput("Center", "CENTER", new VecD(0, 0));
+    }
+
+    protected override Matrix3X3 CalculateMatrix(Matrix3X3 input)
+    {
+        VecD scaledCenter = new VecD(Center.Value.X, Center.Value.Y);
+        Matrix3X3 rotated = RotationType.Value switch
+        {
+            Nodes.Matrix.RotationType.Degrees => Matrix3X3.CreateRotationDegrees((float)Angle.Value, (float)scaledCenter.X, (float)scaledCenter.Y),
+            Nodes.Matrix.RotationType.Radians => Matrix3X3.CreateRotation((float)Angle.Value, (float)scaledCenter.X, (float)scaledCenter.Y),
+            _ => throw new ArgumentOutOfRangeException()
+        };
+
+        return input.PostConcat(rotated);
+    }
+
+    public override Node CreateCopy()
+    {
+        return new RotateNode();
+    }
+}
+
+public enum RotationType
+{
+    Degrees,
+    Radians
+}

+ 28 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Matrix/ScaleNode.cs

@@ -0,0 +1,28 @@
+using Drawie.Backend.Core.Numerics;
+using Drawie.Numerics;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Matrix;
+
+[NodeInfo("Scale")]
+public class ScaleNode : Matrix3X3BaseNode
+{
+    public InputProperty<VecD> Scale { get; }
+    public InputProperty<VecD> Center { get; }
+
+    public ScaleNode()
+    {
+        Scale = CreateInput("Scale", "SCALE", new VecD(1, 1));
+        Center = CreateInput("Center", "CENTER", new VecD(0, 0));
+    }
+
+    protected override Matrix3X3 CalculateMatrix(Matrix3X3 input)
+    {
+        Matrix3X3 scaled = Matrix3X3.CreateScale((float)Scale.Value.X, (float)Scale.Value.Y, (float)Center.Value.X, (float)Center.Value.Y);
+        return input.PostConcat(scaled);
+    }
+
+    public override Node CreateCopy()
+    {
+        return new ScaleNode();
+    }
+}

+ 26 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Matrix/SkewNode.cs

@@ -0,0 +1,26 @@
+using Drawie.Backend.Core.Numerics;
+using Drawie.Numerics;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Matrix;
+
+[NodeInfo("Skew")]
+public class SkewNode : Matrix3X3BaseNode
+{
+    public InputProperty<VecD> Skew { get; }
+
+    public SkewNode()
+    {
+        Skew = CreateInput("Skew", "SKEW", VecD.Zero);
+    }
+
+    protected override Matrix3X3 CalculateMatrix(Matrix3X3 input)
+    {
+        Matrix3X3 matrix = Matrix3X3.CreateSkew((float)Skew.Value.X, (float)Skew.Value.Y);
+        return input.PostConcat(matrix);
+    }
+
+    public override Node CreateCopy()
+    {
+        return new SkewNode();
+    }
+}

+ 6 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Matrix/TransformNode.cs

@@ -0,0 +1,6 @@
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Matrix;
+
+public class TransformNode
+{
+
+}

+ 26 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Matrix/TranslateNode.cs

@@ -0,0 +1,26 @@
+using Drawie.Backend.Core.Numerics;
+using Drawie.Numerics;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Matrix;
+
+[NodeInfo("Translate")]
+public class TranslateNode : Matrix3X3BaseNode
+{
+    public InputProperty<VecD> Translation { get; }
+
+    public TranslateNode()
+    {
+        Translation = CreateInput("Translation", "TRANSLATION", VecD.Zero);
+    }
+
+    protected override Matrix3X3 CalculateMatrix(Matrix3X3 input)
+    {
+        Matrix3X3 matrix = Matrix3X3.CreateTranslation((float)(Translation.Value.X), (float)(Translation.Value.Y));
+        return input.PostConcat(matrix);
+    }
+
+    public override Node CreateCopy()
+    {
+        return new TranslateNode();
+    }
+}

+ 83 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/TileNode.cs

@@ -0,0 +1,83 @@
+using Drawie.Backend.Core;
+using Drawie.Backend.Core.Numerics;
+using Drawie.Backend.Core.Shaders;
+using Drawie.Backend.Core.Surfaces;
+using Drawie.Backend.Core.Surfaces.ImageData;
+using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Numerics;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
+using PixiEditor.ChangeableDocument.Helpers;
+using PixiEditor.ChangeableDocument.Rendering;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+
+[NodeInfo("Tile")]
+public class TileNode : RenderNode
+{
+    public InputProperty<Texture> Image { get; }
+    public InputProperty<ShaderTileMode> TileModeX { get; }
+    public InputProperty<ShaderTileMode> TileModeY { get; }
+    public InputProperty<Matrix3X3> Matrix { get; }
+
+    private Image lastImage;
+    private Shader tileShader;
+    private Paint paint;
+
+    public TileNode()
+    {
+        Image = CreateInput<Texture>("Image", "IMAGE", null);
+        TileModeX = CreateInput<ShaderTileMode>("TileModeX", "TILE_MODE_X", ShaderTileMode.Repeat);
+        TileModeY = CreateInput<ShaderTileMode>("TileModeY", "TILE_MODE_Y", ShaderTileMode.Repeat);
+        Matrix = CreateInput<Matrix3X3>("Matrix", "MATRIX", Matrix3X3.Identity);
+
+        Output.FirstInChain = null;
+    }
+
+    protected override bool ExecuteOnlyOnCacheChange => true;
+    protected override CacheTriggerFlags CacheTrigger => CacheTriggerFlags.Inputs;
+
+    protected override void OnExecute(RenderContext context)
+    {
+        base.OnExecute(context);
+
+        lastImage?.Dispose();
+        tileShader?.Dispose();
+        if (paint != null)
+        {
+            paint.Shader = null;
+        }
+
+        if (Image.Value == null)
+            return;
+
+        lastImage = Image.Value.DrawingSurface.Snapshot();
+        tileShader = Shader.CreateImage(lastImage, TileModeX.Value, TileModeY.Value, Matrix.Value);
+
+        paint ??= new();
+        paint.Shader = tileShader;
+    }
+
+    protected override void OnPaint(RenderContext context, DrawingSurface surface)
+    {
+        if (paint == null)
+            return;
+
+        surface.Canvas.DrawRect(0, 0, context.DocumentSize.X, context.DocumentSize.Y, paint);
+    }
+
+    public override Node CreateCopy()
+    {
+        return new TileNode();
+    }
+
+    public override RectD? GetPreviewBounds(int frame, string elementToRenderName = "")
+    {
+        return null;
+    }
+
+    public override bool RenderPreview(DrawingSurface renderOn, RenderContext context, string elementToRenderName)
+    {
+        return false;
+    }
+
+}

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

@@ -0,0 +1,7 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Matrix;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.Matrix;
+
+[NodeViewModel("ROTATE_NODE", "MATRIX", "")]
+internal class RotateNodeViewModel : NodeViewModel<RotateNode>;

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

@@ -0,0 +1,7 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Matrix;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.Matrix;
+
+[NodeViewModel("SCALE_NODE", "MATRIX", "")]
+internal class ScaleNodeViewModel : NodeViewModel<ScaleNode>;

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

@@ -0,0 +1,7 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Matrix;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.Matrix;
+
+[NodeViewModel("SKEW_NODE", "MATRIX", "")]
+internal class SkewNodeViewModel : NodeViewModel<SkewNode>;

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

@@ -0,0 +1,7 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Matrix;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes.Matrix;
+
+[NodeViewModel("TRANSLATE_NODE", "MATRIX", "")]
+internal class TranslateNodeViewModel : NodeViewModel<TranslateNode>;

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

@@ -0,0 +1,7 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.ViewModels.Nodes;
+
+namespace PixiEditor.ViewModels.Document.Nodes;
+
+[NodeViewModel("TILE_NODE", "IMAGE", "")]
+internal class TileNodeViewModel : NodeViewModel<TileNode>;