Browse Source

Painter wip

flabbet 10 months ago
parent
commit
b455b77f5d
22 changed files with 202 additions and 196 deletions
  1. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/IRenderInput.cs
  2. 4 5
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/ISceneObject.cs
  3. 49 14
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/FolderNode.cs
  4. 5 25
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ImageLayerNode.cs
  5. 5 5
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/LayerNode.cs
  6. 5 9
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/MergeNode.cs
  7. 4 9
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/NoiseNode.cs
  8. 3 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/OutputNode.cs
  9. 9 0
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Painter.cs
  10. 18 13
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/RenderNode.cs
  11. 2 7
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/RasterizeShapeNode.cs
  12. 44 40
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/StructureNode.cs
  13. 2 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/VectorLayerNode.cs
  14. 3 9
      src/PixiEditor.ChangeableDocument/Changeables/Graph/RenderInputProperty.cs
  15. 17 15
      src/PixiEditor.ChangeableDocument/Changeables/Graph/RenderOutputProperty.cs
  16. 7 7
      src/PixiEditor.ChangeableDocument/Changes/NodeGraph/NodeOperations.cs
  17. 9 13
      src/PixiEditor.ChangeableDocument/Changes/Structure/CreateStructureMember_Change.cs
  18. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Structure/DeleteStructureMember_Change.cs
  19. 4 7
      src/PixiEditor.ChangeableDocument/Changes/Structure/DuplicateLayer_Change.cs
  20. 3 5
      src/PixiEditor.ChangeableDocument/Changes/Structure/MoveStructureMember_Change.cs
  21. 5 5
      src/PixiEditor.ChangeableDocument/Changes/Structure/RasterizeMember_Change.cs
  22. 2 2
      src/PixiEditor.ChangeableDocument/Rendering/DocumentRenderer.cs

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/IRenderInput.cs

@@ -6,5 +6,5 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 
 
 public interface IRenderInput
 public interface IRenderInput
 {
 {
-    RenderInputProperty RenderTarget { get; }
+    RenderInputProperty Background { get; }
 }
 }

+ 4 - 5
src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/ISceneObject.cs

@@ -1,15 +1,14 @@
-using PixiEditor.ChangeableDocument.Rendering;
-using PixiEditor.DrawingApi.Core.Surfaces;
+using PixiEditor.ChangeableDocument.Changeables.Animations;
 using PixiEditor.Numerics;
 using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 
 
 public interface ISceneObject
 public interface ISceneObject
 {
 {
-    public VecD ScenePosition { get; }
-    public VecD SceneSize { get; }
+    public VecD GetScenePosition(KeyFrameTime atTime);
+    public VecD GetSceneSize(KeyFrameTime atTime);
     
     
-    public RectD GlobalBounds => new RectD(ScenePosition, SceneSize);
+    public RectD GetGlobalBounds(KeyFrameTime atTime) => new RectD(GetScenePosition(atTime), GetSceneSize(atTime));
     
     
     public void Render(SceneObjectRenderContext context);
     public void Render(SceneObjectRenderContext context);
 }
 }

+ 49 - 14
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/FolderNode.cs

@@ -4,6 +4,7 @@ using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.DrawingApi.Core.Surfaces;
+using PixiEditor.DrawingApi.Core.Surfaces.PaintImpl;
 using PixiEditor.Numerics;
 using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
@@ -11,11 +12,12 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 [NodeInfo("Folder")]
 [NodeInfo("Folder")]
 public class FolderNode : StructureNode, IReadOnlyFolderNode, IClipSource, IPreviewRenderable
 public class FolderNode : StructureNode, IReadOnlyFolderNode, IClipSource, IPreviewRenderable
 {
 {
+    private VecI documentSize;
     public RenderInputProperty Content { get; }
     public RenderInputProperty Content { get; }
 
 
     public FolderNode()
     public FolderNode()
     {
     {
-        Content = CreateRenderInput("Content", "CONTENT", ctx =>
+        Content = CreateRenderInput("Content", "CONTENT" /*, ctx =>
         {
         {
             RectD? bounds = new RectD(VecI.Zero, ctx.DocumentSize);
             RectD? bounds = new RectD(VecI.Zero, ctx.DocumentSize);
 
 
@@ -28,42 +30,75 @@ public class FolderNode : StructureNode, IReadOnlyFolderNode, IClipSource, IPrev
             VecI size = (VecI)bounds.Value.Size;
             VecI size = (VecI)bounds.Value.Size;
             var outputWorkingSurface = RequestTexture(0, size, false);
             var outputWorkingSurface = RequestTexture(0, size, false);
             return outputWorkingSurface.DrawingSurface;
             return outputWorkingSurface.DrawingSurface;
-        });
+        }*/);
     }
     }
 
 
     public override Node CreateCopy() => new FolderNode { MemberName = MemberName };
     public override Node CreateCopy() => new FolderNode { MemberName = MemberName };
 
 
-    public override VecD ScenePosition => Content.Value?.DeviceClipBounds.Size / 2f ?? VecD.Zero;
-    public override VecD SceneSize => Content.Value?.DeviceClipBounds.Size ?? VecD.Zero;
+    public override VecD GetScenePosition(KeyFrameTime time) => documentSize / 2f; //GetTightBounds(time).GetValueOrDefault().Center;
+    public override VecD GetSceneSize(KeyFrameTime time) => documentSize; //GetTightBounds(time).GetValueOrDefault().Size;
+
+    protected override void OnExecute(RenderContext context)
+    {
+        base.OnExecute(context);
+        documentSize = context.DocumentSize;
+    }
 
 
     public override void Render(SceneObjectRenderContext sceneContext)
     public override void Render(SceneObjectRenderContext sceneContext)
     {
     {
-        RectD bounds = RectD.Create(VecI.Zero, sceneContext.DocumentSize);
         if (!IsVisible.Value || Opacity.Value <= 0 || IsEmptyMask())
         if (!IsVisible.Value || Opacity.Value <= 0 || IsEmptyMask())
         {
         {
-            Output.Value = sceneContext.RenderSurface;
+            Output.Value = Background.Value;
             return;
             return;
         }
         }
 
 
         if (Content.Connection == null || (!HasOperations() && BlendMode.Value == Enums.BlendMode.Normal))
         if (Content.Connection == null || (!HasOperations() && BlendMode.Value == Enums.BlendMode.Normal))
         {
         {
+            using Paint paint = new();
+            paint.Color = Colors.White.WithAlpha((byte)Math.Round(Opacity.Value * 255f));
+            int saved = sceneContext.RenderSurface.Canvas.SaveLayer(paint);
+            Content.Value?.Paint(sceneContext, sceneContext.RenderSurface);
+            
+            sceneContext.RenderSurface.Canvas.RestoreToCount(saved);
             return;
             return;
         }
         }
 
 
-        VecI size = (VecI)bounds.Size;
-        var outputWorkingSurface = RequestTexture(0, size, false);
+        RectD bounds = RectD.Create(VecI.Zero, sceneContext.DocumentSize);
 
 
-        if (RenderTarget.Value != null)
+        if (sceneContext.TargetPropertyOutput == Output)
         {
         {
-            blendPaint.BlendMode = RenderContext.GetDrawingBlendMode(BlendMode.Value);
+            if (Background.Value != null)
+            {
+                blendPaint.BlendMode = RenderContext.GetDrawingBlendMode(BlendMode.Value);
+            }
+
+            RenderFolder(sceneContext, bounds, true);
         }
         }
+        else if (sceneContext.TargetPropertyOutput == FilterlessOutput ||
+                 sceneContext.TargetPropertyOutput == RawOutput)
+        {
+            RenderFolder(sceneContext, bounds, false);
+        }
+    }
+
+    private void RenderFolder(SceneObjectRenderContext sceneContext, RectD bounds, bool useFilters)
+    {
+        VecI size = (VecI)bounds.Size;
+        var outputWorkingSurface = RequestTexture(0, size, true);
+        
+        blendPaint.Color = Colors.White.WithAlpha((byte)Math.Round(Opacity.Value * 255f));
+        int saved = outputWorkingSurface.DrawingSurface.Canvas.SaveLayer(blendPaint);
+        
+        Content.Value?.Paint(sceneContext, outputWorkingSurface.DrawingSurface);
+        
+        outputWorkingSurface.DrawingSurface.Canvas.RestoreToCount(saved);
 
 
         ApplyMaskIfPresent(outputWorkingSurface.DrawingSurface, sceneContext);
         ApplyMaskIfPresent(outputWorkingSurface.DrawingSurface, sceneContext);
 
 
-        if (RenderTarget.Value != null)
+        if (Background.Value != null)
         {
         {
             Texture tempSurface = RequestTexture(1, outputWorkingSurface.Size);
             Texture tempSurface = RequestTexture(1, outputWorkingSurface.Size);
-            if (RenderTarget.Connection.Node is IClipSource clipSource)
+            if (Background.Connection.Node is IClipSource clipSource)
             {
             {
                 DrawClipSource(tempSurface.DrawingSurface, clipSource, sceneContext);
                 DrawClipSource(tempSurface.DrawingSurface, clipSource, sceneContext);
             }
             }
@@ -152,7 +187,7 @@ public class FolderNode : StructureNode, IReadOnlyFolderNode, IClipSource, IPrev
         if (Content.Connection != null)
         if (Content.Connection != null)
         {
         {
             var executionQueue = GraphUtils.CalculateExecutionQueue(Content.Connection.Node);
             var executionQueue = GraphUtils.CalculateExecutionQueue(Content.Connection.Node);
-            
+
             while (executionQueue.Count > 0)
             while (executionQueue.Count > 0)
             {
             {
                 IReadOnlyNode node = executionQueue.Dequeue();
                 IReadOnlyNode node = executionQueue.Dequeue();
@@ -181,7 +216,7 @@ public class FolderNode : StructureNode, IReadOnlyFolderNode, IClipSource, IPrev
         {
         {
             return base.RenderPreview(renderOn, resolution, frame, elementToRenderName);
             return base.RenderPreview(renderOn, resolution, frame, elementToRenderName);
         }
         }
-        
+
         if (Content.Connection != null)
         if (Content.Connection != null)
         {
         {
             var executionQueue = GraphUtils.CalculateExecutionQueue(Content.Connection.Node);
             var executionQueue = GraphUtils.CalculateExecutionQueue(Content.Connection.Node);

+ 5 - 25
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ImageLayerNode.cs

@@ -16,10 +16,9 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
 {
 {
     public const string ImageFramesKey = "Frames";
     public const string ImageFramesKey = "Frames";
     public const string ImageLayerKey = "LayerImage";
     public const string ImageLayerKey = "LayerImage";
-    //public RenderOutputProperty RawOutput { get; }
 
 
-    public override VecD ScenePosition => layerImage.CommittedSize / 2f;
-    public override VecD SceneSize => layerImage.CommittedSize;
+    public override VecD GetScenePosition(KeyFrameTime time) => layerImage.CommittedSize / 2f;
+    public override VecD GetSceneSize(KeyFrameTime time) => layerImage.CommittedSize;
 
 
     public bool LockTransparency { get; set; }
     public bool LockTransparency { get; set; }
 
 
@@ -31,8 +30,6 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
 
 
     public ImageLayerNode(VecI size)
     public ImageLayerNode(VecI size)
     {
     {
-        //RawOutput = CreateRenderOutput(nameof(RawOutput), "RAW_LAYER_OUTPUT");
-
         if (keyFrames.Count == 0)
         if (keyFrames.Count == 0)
         {
         {
             keyFrames.Add(new KeyFrameData(Guid.NewGuid(), 0, 0, ImageLayerKey) { Data = new ChunkyImage(size) });
             keyFrames.Add(new KeyFrameData(Guid.NewGuid(), 0, 0, ImageLayerKey) { Data = new ChunkyImage(size) });
@@ -45,24 +42,6 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
     {
     {
         return (RectD?)GetLayerImageAtFrame(frameTime.Frame).FindTightCommittedBounds();
         return (RectD?)GetLayerImageAtFrame(frameTime.Frame).FindTightCommittedBounds();
     }
     }
-
-    protected override void OnExecute(RenderContext context)
-    {
-        base.OnExecute(context);
-        /*var rawOutputTarget = RawOutput.GetFirstRenderTarget(context);
-        if (RawOutput.Connections.Count > 0 && rawOutputTarget != null)
-        {
-            using SceneObjectRenderContext sceneContext = CreateSceneContext(context, rawOutputTarget, RawOutput);
-            
-            int renderSaved = rawOutputTarget.Canvas.Save();
-            rawOutputTarget.Canvas.ClipRect(new RectD(ScenePosition - (SceneSize / 2f), SceneSize));
-            
-            DrawLayerInScene(sceneContext, rawOutputTarget, false);
-            
-            rawOutputTarget.Canvas.RestoreToCount(renderSaved);
-            RawOutput.Value = rawOutputTarget;
-        }*/
-    }
     
     
     protected override VecI GetTargetSize(RenderContext ctx)
     protected override VecI GetTargetSize(RenderContext ctx)
     {
     {
@@ -74,7 +53,7 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
     {
     {
         int scaled = workingSurface.Canvas.Save();
         int scaled = workingSurface.Canvas.Save();
         float multiplier = (float)ctx.ChunkResolution.InvertedMultiplier();
         float multiplier = (float)ctx.ChunkResolution.InvertedMultiplier();
-        workingSurface.Canvas.Translate(ScenePosition);
+        workingSurface.Canvas.Translate(GetScenePosition(ctx.FrameTime));
         base.DrawLayerInScene(ctx, workingSurface, useFilters);
         base.DrawLayerInScene(ctx, workingSurface, useFilters);
 
 
         workingSurface.Canvas.RestoreToCount(scaled);
         workingSurface.Canvas.RestoreToCount(scaled);
@@ -96,7 +75,8 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
     {
     {
         int saved = workingSurface.Canvas.Save();
         int saved = workingSurface.Canvas.Save();
 
 
-        VecD topLeft = SceneSize / 2f;
+        var sceneSize = GetSceneSize(ctx.FrameTime);
+        VecD topLeft = sceneSize / 2f;
         if (renderedSurfaceFrame == null || ctx.FullRerender || ctx.FrameTime.Frame != renderedSurfaceFrame)
         if (renderedSurfaceFrame == null || ctx.FullRerender || ctx.FrameTime.Frame != renderedSurfaceFrame)
         {
         {
             GetLayerImageAtFrame(ctx.FrameTime.Frame).DrawMostUpToDateRegionOn(
             GetLayerImageAtFrame(ctx.FrameTime.Frame).DrawMostUpToDateRegionOn(

+ 5 - 5
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/LayerNode.cs

@@ -22,7 +22,7 @@ public abstract class LayerNode : StructureNode, IReadOnlyLayerNode, IClipSource
     {
     {
         if (!IsVisible.Value || Opacity.Value <= 0 || IsEmptyMask())
         if (!IsVisible.Value || Opacity.Value <= 0 || IsEmptyMask())
         {
         {
-            Output.Value = sceneContext.RenderSurface;
+            Output.Value = Background.Value; 
             return;
             return;
         }
         }
 
 
@@ -39,7 +39,7 @@ public abstract class LayerNode : StructureNode, IReadOnlyLayerNode, IClipSource
     {
     {
         if (!HasOperations())
         if (!HasOperations())
         {
         {
-            if (RenderTarget.Value != null)
+            if (Background.Value != null)
             {
             {
                 blendPaint.BlendMode = RenderContext.GetDrawingBlendMode(BlendMode.Value);
                 blendPaint.BlendMode = RenderContext.GetDrawingBlendMode(BlendMode.Value);
             }
             }
@@ -55,11 +55,11 @@ public abstract class LayerNode : StructureNode, IReadOnlyLayerNode, IClipSource
 
 
         ApplyMaskIfPresent(outputWorkingSurface.DrawingSurface, context);
         ApplyMaskIfPresent(outputWorkingSurface.DrawingSurface, context);
 
 
-        if (RenderTarget.Value != null)
+        if (Background.Value != null)
         {
         {
             Texture tempSurface = TryInitWorkingSurface(size, context.ChunkResolution, 4);
             Texture tempSurface = TryInitWorkingSurface(size, context.ChunkResolution, 4);
             tempSurface.DrawingSurface.Canvas.Clear();
             tempSurface.DrawingSurface.Canvas.Clear();
-            if (RenderTarget.Connection.Node is IClipSource clipSource)
+            if (Background.Connection.Node is IClipSource clipSource)
             {
             {
                 // TODO: This probably should work with StructureMembers not Layers only
                 // TODO: This probably should work with StructureMembers not Layers only
                 DrawClipSource(tempSurface.DrawingSurface, clipSource, context);
                 DrawClipSource(tempSurface.DrawingSurface, clipSource, context);
@@ -80,7 +80,7 @@ public abstract class LayerNode : StructureNode, IReadOnlyLayerNode, IClipSource
         bool useFilters)
         bool useFilters)
     {
     {
         int scaled = workingSurface.Canvas.Save();
         int scaled = workingSurface.Canvas.Save();
-        workingSurface.Canvas.Translate(ScenePosition);
+        workingSurface.Canvas.Translate(GetScenePosition(ctx.FrameTime));
 
 
         DrawLayerOnto(ctx, workingSurface, useFilters);
         DrawLayerOnto(ctx, workingSurface, useFilters);
 
 

+ 5 - 9
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/MergeNode.cs

@@ -26,7 +26,7 @@ public class MergeNode : RenderNode
     public MergeNode() 
     public MergeNode() 
     {
     {
         BlendMode = CreateInput("BlendMode", "BlendMode", Enums.BlendMode.Normal);
         BlendMode = CreateInput("BlendMode", "BlendMode", Enums.BlendMode.Normal);
-        Top = CreateRenderInput("Top", "TOP", context =>
+        /*Top = CreateRenderInput("Top", "TOP", context =>
         {
         {
             var output = Output.GetFirstRenderTarget(context);
             var output = Output.GetFirstRenderTarget(context);
             if(output == null)
             if(output == null)
@@ -48,7 +48,7 @@ public class MergeNode : RenderNode
             
             
             bottomLayer = output.Canvas.SaveLayer(blendPaint);
             bottomLayer = output.Canvas.SaveLayer(blendPaint);
             return output;
             return output;
-        });
+        });*/
     }
     }
 
 
     public override Node CreateCopy()
     public override Node CreateCopy()
@@ -57,23 +57,19 @@ public class MergeNode : RenderNode
     }
     }
 
 
 
 
-    protected override DrawingSurface? ExecuteRender(RenderContext context)
+    protected override void OnPaint(RenderContext context, DrawingSurface target)
     {
     {
         if(Top.Value == null && Bottom.Value == null)
         if(Top.Value == null && Bottom.Value == null)
         {
         {
-            return null;
+            return;
         }
         }
         
         
-        var target = context.RenderSurface;
-        
         if(target == null || target.DeviceClipBounds.Size == VecI.Zero)
         if(target == null || target.DeviceClipBounds.Size == VecI.Zero)
         {
         {
-            return null;
+            return;
         }
         }
 
 
         Merge(target);
         Merge(target);
-
-        return target;
     }
     }
 
 
     private void Merge(DrawingSurface target)
     private void Merge(DrawingSurface target)

+ 4 - 9
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/NoiseNode.cs

@@ -47,7 +47,7 @@ public class NoiseNode : RenderNode
         Seed = CreateInput(nameof(Seed), "SEED", 0d);
         Seed = CreateInput(nameof(Seed), "SEED", 0d);
     }
     }
 
 
-    protected override DrawingSurface? ExecuteRender(RenderContext context)
+    protected override void OnPaint(RenderContext context, DrawingSurface target)
     {
     {
         if (Math.Abs(previousScale - Scale.Value) > 0.000001
         if (Math.Abs(previousScale - Scale.Value) > 0.000001
             || previousSeed != Seed.Value
             || previousSeed != Seed.Value
@@ -58,13 +58,13 @@ public class NoiseNode : RenderNode
         {
         {
             if (Scale.Value < 0.000001)
             if (Scale.Value < 0.000001)
             {
             {
-                return null;
+                return;
             }
             }
 
 
             var shader = SelectShader();
             var shader = SelectShader();
             if (shader == null)
             if (shader == null)
             {
             {
-                return null;
+                return;
             }
             }
 
 
             paint.Shader = shader;
             paint.Shader = shader;
@@ -78,12 +78,7 @@ public class NoiseNode : RenderNode
             previousNoiseType = NoiseType.Value;
             previousNoiseType = NoiseType.Value;
         }
         }
 
 
-
-        var workingSurface = Output.GetFirstRenderTarget(context);
-
-        RenderNoise(workingSurface);
-
-        return workingSurface;
+        RenderNoise(target);
     }
     }
 
 
     private void RenderNoise(DrawingSurface workingSurface)
     private void RenderNoise(DrawingSurface workingSurface)

+ 3 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/OutputNode.cs

@@ -17,7 +17,7 @@ public class OutputNode : Node, IRenderInput, IPreviewRenderable
     private VecI? lastDocumentSize;
     private VecI? lastDocumentSize;
     public OutputNode()
     public OutputNode()
     {
     {
-        Input = new RenderInputProperty(this, InputPropertyName, "BACKGROUND", null, (ctx) => ctx.RenderSurface);
+        Input = new RenderInputProperty(this, InputPropertyName, "BACKGROUND", null);
         AddInputProperty(Input);
         AddInputProperty(Input);
     }
     }
 
 
@@ -29,9 +29,10 @@ public class OutputNode : Node, IRenderInput, IPreviewRenderable
     protected override void OnExecute(RenderContext context)
     protected override void OnExecute(RenderContext context)
     {
     {
         lastDocumentSize = context.DocumentSize;
         lastDocumentSize = context.DocumentSize;
+        Input.Value?.Paint(context, context.RenderSurface);
     }
     }
 
 
-    RenderInputProperty IRenderInput.RenderTarget => Input;
+    RenderInputProperty IRenderInput.Background => Input;
     public RectD? GetPreviewBounds(int frame, string elementToRenderName = "")
     public RectD? GetPreviewBounds(int frame, string elementToRenderName = "")
     {
     {
         if (lastDocumentSize == null)
         if (lastDocumentSize == null)

+ 9 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Painter.cs

@@ -0,0 +1,9 @@
+using PixiEditor.ChangeableDocument.Rendering;
+using PixiEditor.DrawingApi.Core.Surfaces;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+
+public class Painter(Action<RenderContext, DrawingSurface> paint)
+{
+    public Action<RenderContext, DrawingSurface> Paint { get; } = paint;
+}

+ 18 - 13
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/RenderNode.cs

@@ -8,36 +8,41 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 public abstract class RenderNode : Node, IPreviewRenderable 
 public abstract class RenderNode : Node, IPreviewRenderable 
 {
 {
     public RenderOutputProperty Output { get; }
     public RenderOutputProperty Output { get; }
-    
+
     public RenderNode()
     public RenderNode()
     {
     {
-        Output = CreateRenderOutput("Output", "OUTPUT");
+        Painter painter = new Painter(OnPaint);
+        Output = CreateRenderOutput("Output", "OUTPUT", 
+            () => painter, 
+            () => this is IRenderInput renderInput ? renderInput.Background.Value : null);
     }
     }
 
 
     protected override void OnExecute(RenderContext context)
     protected override void OnExecute(RenderContext context)
     {
     {
-        using RenderContext ctx = new RenderContext(
-            Output.GetFirstRenderTarget(context), 
-            context.FrameTime, context.ChunkResolution, context.DocumentSize, context.Opacity);
-        ctx.FullRerender = context.FullRerender;
-        
-        Output.Value = ExecuteRender(ctx);
+        foreach (var prop in OutputProperties)
+        {
+            if (prop is RenderOutputProperty output)
+            {
+                output.ChainToPainterValue();
+            }
+        } 
     }
     }
     
     
-    protected abstract DrawingSurface? ExecuteRender(RenderContext context);
+    protected abstract void OnPaint(RenderContext context, DrawingSurface surface);
     
     
-    protected RenderOutputProperty? CreateRenderOutput(string internalName, string displayName)
+    protected RenderOutputProperty? CreateRenderOutput(string internalName, string displayName, Func<Painter?>? nextInChain, Func<Painter?>? previous = null)
     {
     {
         RenderOutputProperty prop = new RenderOutputProperty(this, internalName, displayName, null);
         RenderOutputProperty prop = new RenderOutputProperty(this, internalName, displayName, null);
+        prop.FirstInChain = previous;
+        prop.NextInChain = nextInChain;
         AddOutputProperty(prop);
         AddOutputProperty(prop);
 
 
         return prop;
         return prop;
     }
     }
 
 
-    protected RenderInputProperty CreateRenderInput(string internalName, string displayName,
-        Func<RenderContext, DrawingSurface> renderTarget)
+    protected RenderInputProperty CreateRenderInput(string internalName, string displayName)
     {
     {
-        RenderInputProperty prop = new RenderInputProperty(this, internalName, displayName, null, renderTarget);
+        RenderInputProperty prop = new RenderInputProperty(this, internalName, displayName, null);
         AddInputProperty(prop);
         AddInputProperty(prop);
 
 
         return prop;
         return prop;

+ 2 - 7
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/RasterizeShapeNode.cs

@@ -14,24 +14,19 @@ public class RasterizeShapeNode : RenderNode
     public InputProperty<ShapeVectorData> Data { get; }
     public InputProperty<ShapeVectorData> Data { get; }
 
 
 
 
-    private Paint rasterizePaint = new Paint();
-
     public RasterizeShapeNode()
     public RasterizeShapeNode()
     {
     {
         Data = CreateInput<ShapeVectorData>("Points", "SHAPE", null);
         Data = CreateInput<ShapeVectorData>("Points", "SHAPE", null);
     }
     }
 
 
-    protected override DrawingSurface? ExecuteRender(RenderContext context)
+    protected override void OnPaint(RenderContext context, DrawingSurface surface)
     {
     {
         var shape = Data.Value;
         var shape = Data.Value;
 
 
         if (shape == null || !shape.IsValid())
         if (shape == null || !shape.IsValid())
-            return null;
-
-        var surface = context.RenderSurface;
+            return;
         
         
         shape.RasterizeTransformed(surface);
         shape.RasterizeTransformed(surface);
-        return surface;
     }
     }
 
 
     public override Node CreateCopy() => new RasterizeShapeNode();
     public override Node CreateCopy() => new RasterizeShapeNode();

+ 44 - 40
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/StructureNode.cs

@@ -15,9 +15,6 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 
 
 public abstract class StructureNode : RenderNode, IReadOnlyStructureNode, IRenderInput
 public abstract class StructureNode : RenderNode, IReadOnlyStructureNode, IRenderInput
 {
 {
-    public abstract VecD ScenePosition { get; }
-    public abstract VecD SceneSize { get; }
-
     public const string DefaultMemberName = "DEFAULT_MEMBER_NAME";
     public const string DefaultMemberName = "DEFAULT_MEMBER_NAME";
     public InputProperty<float> Opacity { get; }
     public InputProperty<float> Opacity { get; }
     public InputProperty<bool> IsVisible { get; }
     public InputProperty<bool> IsVisible { get; }
@@ -27,16 +24,19 @@ public abstract class StructureNode : RenderNode, IReadOnlyStructureNode, IRende
     public InputProperty<bool> MaskIsVisible { get; }
     public InputProperty<bool> MaskIsVisible { get; }
     public InputProperty<Filter> Filters { get; }
     public InputProperty<Filter> Filters { get; }
 
 
-    public RenderInputProperty RenderTarget { get; }
+    public RenderInputProperty Background { get; }
     public RenderOutputProperty FilterlessOutput { get; }
     public RenderOutputProperty FilterlessOutput { get; }
+    public RenderOutputProperty RawOutput { get; }
 
 
     public ChunkyImage? EmbeddedMask { get; set; }
     public ChunkyImage? EmbeddedMask { get; set; }
 
 
     protected Texture renderedMask;
     protected Texture renderedMask;
-    protected static readonly Paint replacePaint = new Paint() 
-        { BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src };
-    protected static readonly Paint clearPaint = new Paint() 
-        { BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src, Color = Colors.Transparent };
+    protected static readonly Paint replacePaint = new Paint() { BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src };
+
+    protected static readonly Paint clearPaint = new Paint()
+    {
+        BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src, Color = Colors.Transparent
+    };
 
 
     public virtual ShapeCorners GetTransformationCorners(KeyFrameTime frameTime)
     public virtual ShapeCorners GetTransformationCorners(KeyFrameTime frameTime)
     {
     {
@@ -51,14 +51,18 @@ public abstract class StructureNode : RenderNode, IReadOnlyStructureNode, IRende
 
 
     private Paint maskPaint = new Paint() { BlendMode = DrawingApi.Core.Surfaces.BlendMode.DstIn };
     private Paint maskPaint = new Paint() { BlendMode = DrawingApi.Core.Surfaces.BlendMode.DstIn };
     protected Paint blendPaint = new Paint() { BlendMode = DrawingApi.Core.Surfaces.BlendMode.SrcOver };
     protected Paint blendPaint = new Paint() { BlendMode = DrawingApi.Core.Surfaces.BlendMode.SrcOver };
-    protected Paint maskPreviewPaint = new Paint() { BlendMode = DrawingApi.Core.Surfaces.BlendMode.SrcOver, 
-        ColorFilter = Nodes.Filters.AlphaGrayscaleFilter };
+
+    protected Paint maskPreviewPaint = new Paint()
+    {
+        BlendMode = DrawingApi.Core.Surfaces.BlendMode.SrcOver, ColorFilter = Nodes.Filters.AlphaGrayscaleFilter
+    };
 
 
     private int maskCacheHash = 0;
     private int maskCacheHash = 0;
 
 
     protected StructureNode()
     protected StructureNode()
     {
     {
-        RenderTarget = CreateRenderInput("Background", "BACKGROUND", (context => Output.GetFirstRenderTarget(context)));
+        Painter filterlessPainter = new Painter(OnFilterlessPaint);
+        Background = CreateRenderInput("Background", "BACKGROUND");
         Opacity = CreateInput<float>("Opacity", "OPACITY", 1);
         Opacity = CreateInput<float>("Opacity", "OPACITY", 1);
         IsVisible = CreateInput<bool>("IsVisible", "IS_VISIBLE", true);
         IsVisible = CreateInput<bool>("IsVisible", "IS_VISIBLE", true);
         BlendMode = CreateInput("BlendMode", "BLEND_MODE", Enums.BlendMode.Normal);
         BlendMode = CreateInput("BlendMode", "BLEND_MODE", Enums.BlendMode.Normal);
@@ -66,51 +70,50 @@ public abstract class StructureNode : RenderNode, IReadOnlyStructureNode, IRende
         MaskIsVisible = CreateInput<bool>("MaskIsVisible", "MASK_IS_VISIBLE", true);
         MaskIsVisible = CreateInput<bool>("MaskIsVisible", "MASK_IS_VISIBLE", true);
         Filters = CreateInput<Filter>(nameof(Filters), "FILTERS", null);
         Filters = CreateInput<Filter>(nameof(Filters), "FILTERS", null);
 
 
-        FilterlessOutput = CreateRenderOutput(nameof(FilterlessOutput), "WITHOUT_FILTERS");
+        FilterlessOutput = CreateRenderOutput(nameof(FilterlessOutput), "WITHOUT_FILTERS",
+            () => filterlessPainter, () => Background.Value);
+
+        RawOutput = CreateRenderOutput(nameof(RawOutput), "RAW_LAYER_OUTPUT", () => filterlessPainter);
 
 
         MemberName = DefaultMemberName;
         MemberName = DefaultMemberName;
     }
     }
 
 
-    protected override DrawingSurface? ExecuteRender(RenderContext context)
+    protected override void OnPaint(RenderContext context, DrawingSurface renderTarget)
     {
     {
-        DrawingSurface renderTarget = null;
-        if (Output.Connections.Count > 0 || RenderTarget.Value != null)
+        if (Output.Connections.Count > 0 || Background.Value != null)
         {
         {
-            renderTarget = RenderTarget.Value ?? context.RenderSurface;
             RenderForOutput(context, renderTarget, Output);
             RenderForOutput(context, renderTarget, Output);
         }
         }
+    }
 
 
-        if (FilterlessOutput.Connections.Count > 0)
-        {
-            RenderForOutput(context, FilterlessOutput.GetFirstRenderTarget(context), FilterlessOutput);
-        }
-
-        return renderTarget;
+    private void OnFilterlessPaint(RenderContext context, DrawingSurface renderTarget)
+    {
+        RenderForOutput(context, renderTarget, FilterlessOutput);
     }
     }
+    
+    public abstract VecD GetScenePosition(KeyFrameTime frameTime);
+    public abstract VecD GetSceneSize(KeyFrameTime frameTime);
 
 
-    private DrawingSurface RenderForOutput(RenderContext context, DrawingSurface renderTarget, RenderOutputProperty output)
+    private void RenderForOutput(RenderContext context, DrawingSurface renderTarget, RenderOutputProperty output)
     {
     {
         var renderObjectContext = CreateSceneContext(context, renderTarget, output);
         var renderObjectContext = CreateSceneContext(context, renderTarget, output);
 
 
-        int renderSaved = 0;
-        if (renderTarget != null)
-        {
-            renderSaved = renderTarget.Canvas.Save();
-            renderTarget.Canvas.ClipRect(new RectD(ScenePosition - (SceneSize / 2f), SceneSize));
-        }
-        
+        int renderSaved = renderTarget.Canvas.Save();
+        VecD scenePos = GetScenePosition(context.FrameTime);
+        VecD sceneSize = GetSceneSize(context.FrameTime);
+        renderTarget.Canvas.ClipRect(new RectD(scenePos - (sceneSize / 2f), sceneSize));
+
         Render(renderObjectContext);
         Render(renderObjectContext);
 
 
         renderTarget?.Canvas.RestoreToCount(renderSaved);
         renderTarget?.Canvas.RestoreToCount(renderSaved);
-
-        return renderTarget;
     }
     }
 
 
     protected SceneObjectRenderContext CreateSceneContext(RenderContext context, DrawingSurface renderTarget,
     protected SceneObjectRenderContext CreateSceneContext(RenderContext context, DrawingSurface renderTarget,
         RenderOutputProperty output)
         RenderOutputProperty output)
     {
     {
-        RectD localBounds = new RectD(0, 0, SceneSize.X, SceneSize.Y);
-        
+        var sceneSize = GetSceneSize(context.FrameTime);
+        RectD localBounds = new RectD(0, 0, sceneSize.X, sceneSize.Y);
+
         SceneObjectRenderContext renderObjectContext = new SceneObjectRenderContext(output, renderTarget, localBounds,
         SceneObjectRenderContext renderObjectContext = new SceneObjectRenderContext(output, renderTarget, localBounds,
             context.FrameTime, context.ChunkResolution, context.DocumentSize, renderTarget == context.RenderSurface,
             context.FrameTime, context.ChunkResolution, context.DocumentSize, renderTarget == context.RenderSurface,
             context.Opacity);
             context.Opacity);
@@ -135,7 +138,7 @@ public abstract class StructureNode : RenderNode, IReadOnlyStructureNode, IRende
                     EmbeddedMask.DrawMostUpToDateRegionOn(
                     EmbeddedMask.DrawMostUpToDateRegionOn(
                         new RectI(0, 0, EmbeddedMask.LatestSize.X, EmbeddedMask.LatestSize.Y),
                         new RectI(0, 0, EmbeddedMask.LatestSize.X, EmbeddedMask.LatestSize.Y),
                         ChunkResolution.Full,
                         ChunkResolution.Full,
-                        surface, VecI.Zero, maskPaint);   
+                        surface, VecI.Zero, maskPaint);
                 }
                 }
                 else
                 else
                 {
                 {
@@ -186,15 +189,16 @@ public abstract class StructureNode : RenderNode, IReadOnlyStructureNode, IRende
                 replacePaint))
                 replacePaint))
         {
         {
             var chunkSize = ChunkResolution.Full.PixelSize();
             var chunkSize = ChunkResolution.Full.PixelSize();
-            renderSurface.DrawingSurface.Canvas.DrawRect(new RectD(chunkPos * chunkSize, new VecD(chunkSize)), clearPaint);
+            renderSurface.DrawingSurface.Canvas.DrawRect(new RectD(chunkPos * chunkSize, new VecD(chunkSize)),
+                clearPaint);
         }
         }
 
 
-        renderSurface.DrawingSurface.Flush();
+        renderSurface.DrawingSurface.Canvas.Flush();
     }
     }
 
 
     protected void ApplyRasterClip(DrawingSurface toClip, DrawingSurface clipSource)
     protected void ApplyRasterClip(DrawingSurface toClip, DrawingSurface clipSource)
     {
     {
-        if (ClipToPreviousMember && RenderTarget.Value != null)
+        if (ClipToPreviousMember && Background.Value != null)
         {
         {
             toClip.Canvas.DrawSurface(clipSource, 0, 0, maskPaint);
             toClip.Canvas.DrawSurface(clipSource, 0, 0, maskPaint);
         }
         }
@@ -262,14 +266,14 @@ public abstract class StructureNode : RenderNode, IReadOnlyStructureNode, IRende
         {
         {
             return false;
             return false;
         }
         }
-        
+
         var img = EmbeddedMask;
         var img = EmbeddedMask;
 
 
         if (img is null)
         if (img is null)
         {
         {
             return false;
             return false;
         }
         }
-        
+
         renderOn.Canvas.DrawSurface(renderedMask.DrawingSurface, VecI.Zero, maskPreviewPaint);
         renderOn.Canvas.DrawSurface(renderedMask.DrawingSurface, VecI.Zero, maskPreviewPaint);
 
 
         return true;
         return true;

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

@@ -37,8 +37,8 @@ public class VectorLayerNode : LayerNode, ITransformableObject, IReadOnlyVectorN
 
 
     private int lastCacheHash;
     private int lastCacheHash;
 
 
-    public override VecD ScenePosition => ShapeData?.TransformedAABB.Center ?? VecD.Zero;
-    public override VecD SceneSize => ShapeData?.TransformedAABB.Size ?? VecD.Zero;
+    public override VecD GetScenePosition(KeyFrameTime time) => ShapeData?.TransformedAABB.Center ?? VecD.Zero;
+    public override VecD GetSceneSize(KeyFrameTime time) => ShapeData?.TransformedAABB.Size ?? VecD.Zero;
     
     
     protected override VecI GetTargetSize(RenderContext ctx)
     protected override VecI GetTargetSize(RenderContext ctx)
     {
     {

+ 3 - 9
src/PixiEditor.ChangeableDocument/Changeables/Graph/RenderInputProperty.cs

@@ -4,16 +4,10 @@ using PixiEditor.DrawingApi.Core.Surfaces;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph;
 
 
-public class RenderInputProperty : InputProperty<DrawingSurface?>
+public class RenderInputProperty : InputProperty<Painter?>
 {
 {
-    Func<RenderContext, DrawingSurface> getRenderTarget;
-    internal RenderInputProperty(Node node, string internalName, string displayName, DrawingSurface? defaultValue, Func<RenderContext, DrawingSurface> getRenderTarget) : base(node, internalName, displayName, defaultValue)
+    internal RenderInputProperty(Node node, string internalName, string displayName, Painter? defaultValue) : base(node, internalName, displayName, defaultValue)
     {
     {
-        this.getRenderTarget = getRenderTarget;
-    }
-
-    public DrawingSurface GetRenderTarget(RenderContext context)
-    {
-        return getRenderTarget(context);
+        
     }
     }
 }
 }

+ 17 - 15
src/PixiEditor.ChangeableDocument/Changeables/Graph/RenderOutputProperty.cs

@@ -4,27 +4,29 @@ using PixiEditor.DrawingApi.Core.Surfaces;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph;
 
 
-public class RenderOutputProperty : OutputProperty<DrawingSurface>
-{
-    internal RenderOutputProperty(Node node, string internalName, string displayName, DrawingSurface defaultValue) : base(node, internalName, displayName, defaultValue)
+public class RenderOutputProperty : OutputProperty<Painter>
+{ 
+    public Func<Painter?>? FirstInChain { get; set; }
+    public Func<Painter?>? NextInChain { get; set; }
+    
+    internal RenderOutputProperty(Node node, string internalName, string displayName, Painter defaultValue) : base(node, internalName, displayName, defaultValue)
     {
     {
         
         
     }
     }
-    
-    public DrawingSurface GetFirstRenderTarget(RenderContext ctx)
+
+    public void ChainToPainterValue()
     {
     {
-        foreach (var connection in Connections)
+        if (FirstInChain != null)
         {
         {
-            if (connection is RenderInputProperty renderInput)
+            Value = new Painter((ctx, surface) =>
             {
             {
-                var target = renderInput.GetRenderTarget(ctx);
-                if (target != null)
-                {
-                    return target;
-                }
-            }
+                FirstInChain()?.Paint(ctx, surface);
+                NextInChain()?.Paint(ctx, surface);
+            });
+        }
+        else
+        {
+            Value = NextInChain?.Invoke();
         }
         }
-
-        return null;
     }
     }
 }
 }

+ 7 - 7
src/PixiEditor.ChangeableDocument/Changes/NodeGraph/NodeOperations.cs

@@ -70,9 +70,9 @@ public static class NodeOperations
     }
     }
 
 
     public static List<ConnectProperty_ChangeInfo> AppendMember(
     public static List<ConnectProperty_ChangeInfo> AppendMember(
-        InputProperty<DrawingSurface?> parentInput,
-        OutputProperty<DrawingSurface> toAddOutput,
-        InputProperty<DrawingSurface> toAddInput, Guid memberId)
+        InputProperty<Painter?> parentInput,
+        OutputProperty<Painter> toAddOutput,
+        InputProperty<Painter> toAddInput, Guid memberId)
     {
     {
         List<ConnectProperty_ChangeInfo> changes = new();
         List<ConnectProperty_ChangeInfo> changes = new();
         IOutputProperty? previouslyConnected = null;
         IOutputProperty? previouslyConnected = null;
@@ -100,13 +100,13 @@ public static class NodeOperations
     {
     {
         List<IChangeInfo> changes = new();
         List<IChangeInfo> changes = new();
 
 
-        if (structureNode.RenderTarget.Connection != null)
+        if (structureNode.Background.Connection != null)
         {
         {
             // connect connection to next input if possible
             // connect connection to next input if possible
 
 
             var connections = structureNode.Output.Connections.ToArray();
             var connections = structureNode.Output.Connections.ToArray();
 
 
-            var output = structureNode.RenderTarget.Connection;
+            var output = structureNode.Background.Connection;
 
 
             foreach (var input in connections)
             foreach (var input in connections)
             {
             {
@@ -115,9 +115,9 @@ public static class NodeOperations
                     output.InternalPropertyName, input.InternalPropertyName));
                     output.InternalPropertyName, input.InternalPropertyName));
             }
             }
 
 
-            structureNode.RenderTarget.Connection.DisconnectFrom(structureNode.RenderTarget);
+            structureNode.Background.Connection.DisconnectFrom(structureNode.Background);
             changes.Add(new ConnectProperty_ChangeInfo(null, structureNode.Id, null,
             changes.Add(new ConnectProperty_ChangeInfo(null, structureNode.Id, null,
-                structureNode.RenderTarget.InternalPropertyName));
+                structureNode.Background.InternalPropertyName));
         }
         }
 
 
         var outputs = structureNode.Output.Connections.ToArray();
         var outputs = structureNode.Output.Connections.ToArray();

+ 9 - 13
src/PixiEditor.ChangeableDocument/Changes/Structure/CreateStructureMember_Change.cs

@@ -4,10 +4,6 @@ using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.ChangeInfos.NodeGraph;
 using PixiEditor.ChangeableDocument.ChangeInfos.NodeGraph;
 using PixiEditor.ChangeableDocument.ChangeInfos.Structure;
 using PixiEditor.ChangeableDocument.ChangeInfos.Structure;
 using PixiEditor.ChangeableDocument.Changes.NodeGraph;
 using PixiEditor.ChangeableDocument.Changes.NodeGraph;
-using PixiEditor.ChangeableDocument.Enums;
-using PixiEditor.DrawingApi.Core;
-using PixiEditor.DrawingApi.Core.Surfaces;
-using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changes.Structure;
 namespace PixiEditor.ChangeableDocument.Changes.Structure;
 
 
@@ -45,8 +41,8 @@ internal class CreateStructureMember_Change : Change
 
 
         List<IChangeInfo> changes = new() { CreateChangeInfo(member) };
         List<IChangeInfo> changes = new() { CreateChangeInfo(member) };
         
         
-        InputProperty<DrawingSurface> targetInput = parentNode.InputProperties.FirstOrDefault(x => 
-            x.ValueType == typeof(DrawingSurface)) as InputProperty<DrawingSurface>;
+        InputProperty<Painter> targetInput = parentNode.InputProperties.FirstOrDefault(x => 
+            x.ValueType == typeof(Painter)) as InputProperty<Painter>;
         
         
         
         
         if (member is FolderNode folder)
         if (member is FolderNode folder)
@@ -58,7 +54,7 @@ internal class CreateStructureMember_Change : Change
         {
         {
             document.NodeGraph.AddNode(member);
             document.NodeGraph.AddNode(member);
             List<ConnectProperty_ChangeInfo> connectPropertyChangeInfo =
             List<ConnectProperty_ChangeInfo> connectPropertyChangeInfo =
-                NodeOperations.AppendMember(targetInput, member.Output, member.RenderTarget, member.Id);
+                NodeOperations.AppendMember(targetInput, member.Output, member.Background, member.Id);
             changes.AddRange(connectPropertyChangeInfo);
             changes.AddRange(connectPropertyChangeInfo);
         }
         }
 
 
@@ -87,7 +83,7 @@ internal class CreateStructureMember_Change : Change
         }
         }
 
 
         StructureNode child = document.FindMemberOrThrow(newMemberGuid);
         StructureNode child = document.FindMemberOrThrow(newMemberGuid);
-        var childBackgroundConnection = child.RenderTarget.Connection;
+        var childBackgroundConnection = child.Background.Connection;
         child.Dispose();
         child.Dispose();
 
 
         document.NodeGraph.RemoveNode(child);
         document.NodeGraph.RemoveNode(child);
@@ -96,19 +92,19 @@ internal class CreateStructureMember_Change : Change
 
 
         if (childBackgroundConnection != null)
         if (childBackgroundConnection != null)
         {
         {
-            childBackgroundConnection?.ConnectTo(backgroundInput.RenderTarget);
+            childBackgroundConnection?.ConnectTo(backgroundInput.Background);
             ConnectProperty_ChangeInfo change = new(childBackgroundConnection.Node.Id,
             ConnectProperty_ChangeInfo change = new(childBackgroundConnection.Node.Id,
-                backgroundInput.RenderTarget.Node.Id, childBackgroundConnection.InternalPropertyName,
-                backgroundInput.RenderTarget.InternalPropertyName);
+                backgroundInput.Background.Node.Id, childBackgroundConnection.InternalPropertyName,
+                backgroundInput.Background.InternalPropertyName);
             changes.Add(change);
             changes.Add(change);
         }
         }
 
 
         return changes;
         return changes;
     }
     }
 
 
-    private static void AppendFolder(InputProperty<DrawingSurface> backgroundInput, FolderNode folder, List<IChangeInfo> changes)
+    private static void AppendFolder(InputProperty<Painter> backgroundInput, FolderNode folder, List<IChangeInfo> changes)
     {
     {
-        var appened = NodeOperations.AppendMember(backgroundInput, folder.Output, folder.RenderTarget, folder.Id);
+        var appened = NodeOperations.AppendMember(backgroundInput, folder.Output, folder.Background, folder.Id);
         changes.AddRange(appened);
         changes.AddRange(appened);
     }
     }
 
 

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Structure/DeleteStructureMember_Change.cs

@@ -44,7 +44,7 @@ internal class DeleteStructureMember_Change : Change
     {
     {
         StructureNode node = document.FindMember(memberGuid);
         StructureNode node = document.FindMember(memberGuid);
 
 
-        var bgConnection = node.RenderTarget.Connection;
+        var bgConnection = node.Background.Connection;
         var outputConnections = node.Output.Connections.ToArray();
         var outputConnections = node.Output.Connections.ToArray();
 
 
         document.NodeGraph.RemoveNode(node);
         document.NodeGraph.RemoveNode(node);

+ 4 - 7
src/PixiEditor.ChangeableDocument/Changes/Structure/DuplicateLayer_Change.cs

@@ -1,10 +1,7 @@
 using PixiEditor.ChangeableDocument.Changeables.Graph;
 using PixiEditor.ChangeableDocument.Changeables.Graph;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
-using PixiEditor.ChangeableDocument.ChangeInfos.NodeGraph;
 using PixiEditor.ChangeableDocument.ChangeInfos.Structure;
 using PixiEditor.ChangeableDocument.ChangeInfos.Structure;
 using PixiEditor.ChangeableDocument.Changes.NodeGraph;
 using PixiEditor.ChangeableDocument.Changes.NodeGraph;
-using PixiEditor.DrawingApi.Core;
-using PixiEditor.DrawingApi.Core.Surfaces;
 
 
 namespace PixiEditor.ChangeableDocument.Changes.Structure;
 namespace PixiEditor.ChangeableDocument.Changes.Structure;
 
 
@@ -41,9 +38,9 @@ internal class DuplicateLayer_Change : Change
         LayerNode clone = (LayerNode)existingLayer.Clone();
         LayerNode clone = (LayerNode)existingLayer.Clone();
         clone.Id = duplicateGuid;
         clone.Id = duplicateGuid;
 
 
-        InputProperty<DrawingSurface?> targetInput = parent.InputProperties.FirstOrDefault(x =>
-            x.ValueType == typeof(DrawingSurface) &&
-            x.Connection.Node is StructureNode) as InputProperty<DrawingSurface?>;
+        InputProperty<Painter?> targetInput = parent.InputProperties.FirstOrDefault(x =>
+            x.ValueType == typeof(Painter) &&
+            x.Connection.Node is StructureNode) as InputProperty<Painter?>;
 
 
         List<IChangeInfo> operations = new();
         List<IChangeInfo> operations = new();
 
 
@@ -51,7 +48,7 @@ internal class DuplicateLayer_Change : Change
 
 
         operations.Add(CreateLayer_ChangeInfo.FromLayer(clone));
         operations.Add(CreateLayer_ChangeInfo.FromLayer(clone));
 
 
-        operations.AddRange(NodeOperations.AppendMember(targetInput, clone.Output, clone.RenderTarget, clone.Id));
+        operations.AddRange(NodeOperations.AppendMember(targetInput, clone.Output, clone.Background, clone.Id));
 
 
         ignoreInUndo = false;
         ignoreInUndo = false;
 
 

+ 3 - 5
src/PixiEditor.ChangeableDocument/Changes/Structure/MoveStructureMember_Change.cs

@@ -3,8 +3,6 @@ using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.ChangeInfos.Structure;
 using PixiEditor.ChangeableDocument.ChangeInfos.Structure;
 using PixiEditor.ChangeableDocument.Changes.NodeGraph;
 using PixiEditor.ChangeableDocument.Changes.NodeGraph;
-using PixiEditor.DrawingApi.Core;
-using PixiEditor.DrawingApi.Core.Surfaces;
 
 
 namespace PixiEditor.ChangeableDocument.Changes.Structure;
 namespace PixiEditor.ChangeableDocument.Changes.Structure;
 
 
@@ -50,9 +48,9 @@ internal class MoveStructureMember_Change : Change
 
 
         List<IChangeInfo> changes = new();
         List<IChangeInfo> changes = new();
         
         
-        Guid oldBackgroundId = sourceNode.RenderTarget.Node.Id;
+        Guid oldBackgroundId = sourceNode.Background.Node.Id;
 
 
-        InputProperty<DrawingSurface?> inputProperty = backgroundInput.RenderTarget;
+        InputProperty<Painter?> inputProperty = backgroundInput.Background;
 
 
         if (targetNode is FolderNode folder && putInsideFolder)
         if (targetNode is FolderNode folder && putInsideFolder)
         {
         {
@@ -63,7 +61,7 @@ internal class MoveStructureMember_Change : Change
         
         
         changes.AddRange(NodeOperations.DetachStructureNode(sourceNode));
         changes.AddRange(NodeOperations.DetachStructureNode(sourceNode));
         changes.AddRange(NodeOperations.AppendMember(inputProperty, sourceNode.Output,
         changes.AddRange(NodeOperations.AppendMember(inputProperty, sourceNode.Output,
-            sourceNode.RenderTarget,
+            sourceNode.Background,
             sourceNode.Id));
             sourceNode.Id));
         
         
         changes.Add(changeInfo);
         changes.Add(changeInfo);

+ 5 - 5
src/PixiEditor.ChangeableDocument/Changes/Structure/RasterizeMember_Change.cs

@@ -56,12 +56,12 @@ internal class RasterizeMember_Change : Change
         image.EnqueueDrawImage(VecI.Zero, surface);
         image.EnqueueDrawImage(VecI.Zero, surface);
         image.CommitChanges();
         image.CommitChanges();
 
 
-        OutputProperty<DrawingSurface>? outputConnection = node.OutputProperties.FirstOrDefault(x => x is OutputProperty<DrawingSurface>) as OutputProperty<DrawingSurface>;
-        InputProperty<DrawingSurface>? outputConnectedInput =
-            outputConnection?.Connections.FirstOrDefault(x => x is InputProperty<DrawingSurface>) as InputProperty<DrawingSurface>;
+        OutputProperty<Painter>? outputConnection = node.OutputProperties.FirstOrDefault(x => x is OutputProperty<Painter>) as OutputProperty<Painter>;
+        InputProperty<Painter>? outputConnectedInput =
+            outputConnection?.Connections.FirstOrDefault(x => x is InputProperty<Painter>) as InputProperty<Painter>;
 
 
-        InputProperty<DrawingSurface> backgroundInput = imageLayer.RenderTarget;
-        OutputProperty<DrawingSurface> toAddOutput = imageLayer.Output;
+        InputProperty<Painter> backgroundInput = imageLayer.Background;
+        OutputProperty<Painter> toAddOutput = imageLayer.Output;
 
 
         List<IChangeInfo> changeInfos = new();
         List<IChangeInfo> changeInfos = new();
         changeInfos.Add(CreateNode_ChangeInfo.CreateFromNode(imageLayer));
         changeInfos.Add(CreateNode_ChangeInfo.CreateFromNode(imageLayer));

+ 2 - 2
src/PixiEditor.ChangeableDocument/Rendering/DocumentRenderer.cs

@@ -109,7 +109,7 @@ public class DocumentRenderer : IPreviewRenderable
             }
             }
         });
         });
 
 
-        IInputProperty<DrawingSurface> lastInput = outputNode.Input;
+        IInputProperty<Painter> lastInput = outputNode.Input;
 
 
         foreach (var layer in layersInOrder)
         foreach (var layer in layersInOrder)
         {
         {
@@ -117,7 +117,7 @@ public class DocumentRenderer : IPreviewRenderable
             membersOnlyGraph.AddNode(clone);
             membersOnlyGraph.AddNode(clone);
 
 
             clone.Output.ConnectTo(lastInput);
             clone.Output.ConnectTo(lastInput);
-            lastInput = clone.RenderTarget;
+            lastInput = clone.Background;
         }
         }
 
 
         return membersOnlyGraph;
         return membersOnlyGraph;