Browse Source

Support transform when reusing stamps

Krzysztof Krysiński 3 days ago
parent
commit
08dcc3a20c

+ 7 - 3
src/PixiEditor.ChangeableDocument/Changeables/Brushes/BrushEngine.cs

@@ -31,6 +31,7 @@ public class BrushEngine : IDisposable
     private int lastAppliedHistoryIndex = -1;
     private int lastAppliedHistoryIndex = -1;
     private VecI lastCachedTexturePaintableSize = VecI.Zero;
     private VecI lastCachedTexturePaintableSize = VecI.Zero;
     private TexturePaintable? lastCachedTexturePaintable = null;
     private TexturePaintable? lastCachedTexturePaintable = null;
+    private Matrix3X3 lastCachedTransform = Matrix3X3.Identity;
     private readonly List<RecordedPoint> pointsHistory = new();
     private readonly List<RecordedPoint> pointsHistory = new();
 
 
     private bool drawnOnce = false;
     private bool drawnOnce = false;
@@ -217,6 +218,7 @@ public class BrushEngine : IDisposable
             lastPos = point;
             lastPos = point;
             drawnOnce = true;
             drawnOnce = true;
             target?.SetBlendMode(imageBlendMode);
             target?.SetBlendMode(imageBlendMode);
+            brushNode.ResetContentTexture();
         }
         }
 
 
         float strokeWidth = brushData.StrokeWidth;
         float strokeWidth = brushData.StrokeWidth;
@@ -333,10 +335,11 @@ public class BrushEngine : IDisposable
         bool snapToPixels = brushNode.SnapToPixels.Value;
         bool snapToPixels = brushNode.SnapToPixels.Value;
         bool canReuseStamps = brushNode.CanReuseStamps.Value;
         bool canReuseStamps = brushNode.CanReuseStamps.Value;
         Blender? stampBlender = brushNode.UseCustomStampBlender.Value ? brushNode.LastStampBlender : null;
         Blender? stampBlender = brushNode.UseCustomStampBlender.Value ? brushNode.LastStampBlender : null;
+        Matrix3X3 transform = brushNode.Transform.Value;
         //Blender? imageBlender = brushNode.UseCustomImageBlender.Value ? brushNode.LastImageBlender : null;
         //Blender? imageBlender = brushNode.UseCustomImageBlender.Value ? brushNode.LastImageBlender : null;
 
 
         if (PaintBrush(target, autoPosition, vectorShape, rect, fitToStrokeSize, pressure, content, contentTexture,
         if (PaintBrush(target, autoPosition, vectorShape, rect, fitToStrokeSize, pressure, content, contentTexture,
-                stampBlender, brushNode.StampBlendMode.Value, antiAliasing, fill, stroke, snapToPixels, canReuseStamps))
+                stampBlender, brushNode.StampBlendMode.Value, antiAliasing, fill, stroke, snapToPixels, canReuseStamps, transform))
         {
         {
             lastPos = point;
             lastPos = point;
         }
         }
@@ -345,7 +348,7 @@ public class BrushEngine : IDisposable
     public bool PaintBrush(ChunkyImage target, bool autoPosition, ShapeVectorData vectorShape,
     public bool PaintBrush(ChunkyImage target, bool autoPosition, ShapeVectorData vectorShape,
         RectD rect, bool fitToStrokeSize, float pressure, Painter? content,
         RectD rect, bool fitToStrokeSize, float pressure, Painter? content,
         Texture? contentTexture, Blender? blender, DrawingApiBlendMode blendMode, bool antiAliasing, Paintable fill, Paintable stroke,
         Texture? contentTexture, Blender? blender, DrawingApiBlendMode blendMode, bool antiAliasing, Paintable fill, Paintable stroke,
-        bool snapToPixels, bool canReuseStamps)
+        bool snapToPixels, bool canReuseStamps, Matrix3X3 transform)
     {
     {
         var path = vectorShape.ToPath(true);
         var path = vectorShape.ToPath(true);
         if (path == null)
         if (path == null)
@@ -411,11 +414,12 @@ public class BrushEngine : IDisposable
                 TexturePaintable brushPaintable;
                 TexturePaintable brushPaintable;
                 if (canReuseStamps)
                 if (canReuseStamps)
                 {
                 {
-                    if (lastCachedTexturePaintableSize != contentTexture.Size || lastCachedTexturePaintable == null)
+                    if (lastCachedTexturePaintableSize != contentTexture.Size || lastCachedTexturePaintable == null || lastCachedTransform != transform)
                     {
                     {
                         lastCachedTexturePaintable?.Dispose();
                         lastCachedTexturePaintable?.Dispose();
                         lastCachedTexturePaintable = new TexturePaintable(new Texture(contentTexture), false);
                         lastCachedTexturePaintable = new TexturePaintable(new Texture(contentTexture), false);
                         lastCachedTexturePaintableSize = contentTexture.Size;
                         lastCachedTexturePaintableSize = contentTexture.Size;
+                        lastCachedTransform = transform;
                     }
                     }
 
 
                     brushPaintable = lastCachedTexturePaintable;
                     brushPaintable = lastCachedTexturePaintable;

+ 22 - 7
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Brushes/BrushOutputNode.cs

@@ -89,8 +89,12 @@ public class BrushOutputNode : Node
     public const string UseCustomStampBlenderProperty = "UseCustomStampBlender";
     public const string UseCustomStampBlenderProperty = "UseCustomStampBlender";
     public const string CustomStampBlenderCodeProperty = "CustomStampBlender";
     public const string CustomStampBlenderCodeProperty = "CustomStampBlender";
     public const string StampBlendModeProperty = "StampBlendMode";
     public const string StampBlendModeProperty = "StampBlendMode";
+    public const string ContentProperty = "Content";
+    public const string ContentTransformProperty = "Transform";
 
 
     private VectorPath? previewVectorPath;
     private VectorPath? previewVectorPath;
+    private bool drawnContentTextureOnce = false;
+    private Matrix3X3 lastTranform = Matrix3X3.Identity;
 
 
     public BrushOutputNode()
     public BrushOutputNode()
     {
     {
@@ -98,8 +102,8 @@ public class BrushOutputNode : Node
         VectorShape = CreateInput<ShapeVectorData>("VectorShape", "SHAPE", null);
         VectorShape = CreateInput<ShapeVectorData>("VectorShape", "SHAPE", null);
         Stroke = CreateInput<Paintable>("Stroke", "STROKE", null);
         Stroke = CreateInput<Paintable>("Stroke", "STROKE", null);
         Fill = CreateInput<Paintable>("Fill", "FILL", null);
         Fill = CreateInput<Paintable>("Fill", "FILL", null);
-        Content = CreateRenderInput("Content", "CONTENT");
-        Transform = CreateInput<Matrix3X3>("Transform", "TRANSFORM", Matrix3X3.Identity);
+        Content = CreateRenderInput(ContentProperty, "CONTENT");
+        Transform = CreateInput<Matrix3X3>(ContentTransformProperty, "CONTENT_TRANSFORM", Matrix3X3.Identity);
         ImageBlendMode = CreateInput<Drawie.Backend.Core.Surfaces.BlendMode>("BlendMode", "BLEND_MODE",
         ImageBlendMode = CreateInput<Drawie.Backend.Core.Surfaces.BlendMode>("BlendMode", "BLEND_MODE",
             Drawie.Backend.Core.Surfaces.BlendMode.SrcOver);
             Drawie.Backend.Core.Surfaces.BlendMode.SrcOver);
         StampBlendMode = CreateInput<Drawie.Backend.Core.Surfaces.BlendMode>(StampBlendModeProperty, "STAMP_BLEND_MODE",
         StampBlendMode = CreateInput<Drawie.Backend.Core.Surfaces.BlendMode>(StampBlendModeProperty, "STAMP_BLEND_MODE",
@@ -146,11 +150,17 @@ public class BrushOutputNode : Node
         {
         {
             if (context.RenderOutputSize.LongestAxis > 0)
             if (context.RenderOutputSize.LongestAxis > 0)
             {
             {
-                ContentTexture = cache.RequestTexture(0, context.RenderOutputSize, context.ProcessingColorSpace);
-                ContentTexture.DrawingSurface.Canvas.Save();
-                ContentTexture.DrawingSurface.Canvas.SetMatrix(Transform.Value);
-                Content.Value.Paint(context, ContentTexture.DrawingSurface.Canvas);
-                ContentTexture.DrawingSurface.Canvas.Restore();
+                if (!CanReuseStamps.Value || ContentTexture == null || ContentTexture.Size != context.RenderOutputSize ||
+                    !drawnContentTextureOnce || Transform.Value != lastTranform)
+                {
+                    ContentTexture = cache.RequestTexture(0, context.RenderOutputSize, context.ProcessingColorSpace);
+                    ContentTexture.DrawingSurface.Canvas.Save();
+                    ContentTexture.DrawingSurface.Canvas.SetMatrix(Transform.Value);
+                    Content.Value.Paint(context, ContentTexture.DrawingSurface.Canvas);
+                    ContentTexture.DrawingSurface.Canvas.Restore();
+                    drawnContentTextureOnce = true;
+                    lastTranform = Transform.Value;
+                }
             }
             }
         }
         }
 
 
@@ -179,6 +189,11 @@ public class BrushOutputNode : Node
         additionalData["PersistentId"] = PersistentId;
         additionalData["PersistentId"] = PersistentId;
     }
     }
 
 
+    public void ResetContentTexture()
+    {
+        drawnContentTextureOnce = false;
+    }
+
     internal override void DeserializeAdditionalData(IReadOnlyDocument target, IReadOnlyDictionary<string, object> data,
     internal override void DeserializeAdditionalData(IReadOnlyDocument target, IReadOnlyDictionary<string, object> data,
         List<IChangeInfo> infos)
         List<IChangeInfo> infos)
     {
     {

+ 2 - 1
src/PixiEditor/Data/Localization/Languages/en.json

@@ -1290,5 +1290,6 @@
   "VIEWPORT_INFO_NODE": "Viewport Info",
   "VIEWPORT_INFO_NODE": "Viewport Info",
   "EQUALS_NODE": "Equals",
   "EQUALS_NODE": "Equals",
   "IS_LEFT_BUTTON_PRESSED": "Is Left Button Pressed",
   "IS_LEFT_BUTTON_PRESSED": "Is Left Button Pressed",
-  "IS_RIGHT_BUTTON_PRESSED": "Is Right Button Pressed"
+  "IS_RIGHT_BUTTON_PRESSED": "Is Right Button Pressed",
+  "CONTENT_TRANSFORM": "Content Transform"
 }
 }

+ 8 - 0
src/PixiEditor/ViewModels/Document/Nodes/Brushes/BrushOutputNodeViewModel.cs

@@ -15,6 +15,8 @@ internal class BrushOutputNodeViewModel : NodeViewModel<BrushOutputNode>
         InputPropertyMap[BrushOutputNode.BrushNameProperty].SocketEnabled = false;
         InputPropertyMap[BrushOutputNode.BrushNameProperty].SocketEnabled = false;
         InputPropertyMap[BrushOutputNode.FitToStrokeSizeProperty].SocketEnabled = false;
         InputPropertyMap[BrushOutputNode.FitToStrokeSizeProperty].SocketEnabled = false;
         InputPropertyMap[BrushOutputNode.UseCustomStampBlenderProperty].ValueChanged += OnValueChanged;
         InputPropertyMap[BrushOutputNode.UseCustomStampBlenderProperty].ValueChanged += OnValueChanged;
+        InputPropertyMap[BrushOutputNode.ContentProperty].ConnectedOutputChanged += OnContentConnectionChanged;
+        InputPropertyMap[BrushOutputNode.ContentTransformProperty].IsVisible = InputPropertyMap[BrushOutputNode.ContentProperty].ConnectedOutput != null;
         if(InputPropertyMap[BrushOutputNode.CustomStampBlenderCodeProperty] is StringPropertyViewModel codeProperty)
         if(InputPropertyMap[BrushOutputNode.CustomStampBlenderCodeProperty] is StringPropertyViewModel codeProperty)
         {
         {
             codeProperty.IsVisible = (bool)InputPropertyMap[BrushOutputNode.UseCustomStampBlenderProperty].Value;
             codeProperty.IsVisible = (bool)InputPropertyMap[BrushOutputNode.UseCustomStampBlenderProperty].Value;
@@ -27,4 +29,10 @@ internal class BrushOutputNodeViewModel : NodeViewModel<BrushOutputNode>
         InputPropertyMap[BrushOutputNode.CustomStampBlenderCodeProperty].IsVisible = (bool)args.NewValue;
         InputPropertyMap[BrushOutputNode.CustomStampBlenderCodeProperty].IsVisible = (bool)args.NewValue;
         InputPropertyMap[BrushOutputNode.StampBlendModeProperty].IsVisible = !(bool)args.NewValue;
         InputPropertyMap[BrushOutputNode.StampBlendModeProperty].IsVisible = !(bool)args.NewValue;
     }
     }
+
+    private void OnContentConnectionChanged(object? sender, EventArgs eventArgs)
+    {
+        var connection = InputPropertyMap[BrushOutputNode.ContentProperty].ConnectedOutput;
+        InputPropertyMap[BrushOutputNode.ContentTransformProperty].IsVisible = connection != null;
+    }
 }
 }