Browse Source

Very basic rendering works

flabbet 10 months ago
parent
commit
be7f9156f0
62 changed files with 424 additions and 431 deletions
  1. 1 1
      src/ChunkyImageLib/Operations/EllipseOperation.cs
  2. 3 3
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Context/FuncContext.cs
  3. 2 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/IBackgroundInput.cs
  4. 1 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/IReadOnlyNode.cs
  5. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/IReadOnlyNodeGraph.cs
  6. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/IReadOnlyStructureNode.cs
  7. 15 0
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/ISceneObject.cs
  8. 16 0
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/SceneObjectRenderContext.cs
  9. 2 4
      src/PixiEditor.ChangeableDocument/Changeables/Graph/NodeGraph.cs
  10. 1 3
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Animable/TimeNode.cs
  11. 2 4
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineChannelsNode.cs
  12. 1 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineColorNode.cs
  13. 1 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineVecDNode.cs
  14. 1 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineVecINode.cs
  15. 2 4
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/SeparateChannelsNode.cs
  16. 1 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/SeparateColorNode.cs
  17. 1 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/SeparateVecDNode.cs
  18. 1 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/SeparateVecINode.cs
  19. 2 4
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CreateImageNode.cs
  20. 2 4
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/DebugBlendModeNode.cs
  21. 2 3
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/FilterNodes/ApplyFilterNode.cs
  22. 2 4
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/FilterNodes/FilterNode.cs
  23. 35 19
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/FolderNode.cs
  24. 16 15
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ImageLayerNode.cs
  25. 28 21
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/LayerNode.cs
  26. 1 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/LerpColorNode.cs
  27. 1 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/MathNode.cs
  28. 6 9
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/MergeNode.cs
  29. 5 5
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ModifyImageLeftNode.cs
  30. 9 10
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ModifyImageRightNode.cs
  31. 9 36
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Node.cs
  32. 4 6
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/NoiseNode.cs
  33. 5 5
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/OutputNode.cs
  34. 2 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/SampleImageNode.cs
  35. 3 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/EllipseVectorData.cs
  36. 3 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/RectangleVectorData.cs
  37. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/DistributePointsNode.cs
  38. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/EllipseNode.cs
  39. 3 3
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/RasterizeShapeNode.cs
  40. 1 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/RemoveClosePointsNode.cs
  41. 5 5
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/ShapeNode.cs
  42. 58 32
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/StructureNode.cs
  43. 15 9
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/VectorLayerNode.cs
  44. 4 3
      src/PixiEditor.ChangeableDocument/Changes/NodeGraph/NodeOperations.cs
  45. 4 3
      src/PixiEditor.ChangeableDocument/Changes/Structure/CreateStructureMember_Change.cs
  46. 4 3
      src/PixiEditor.ChangeableDocument/Changes/Structure/DuplicateLayer_Change.cs
  47. 2 1
      src/PixiEditor.ChangeableDocument/Changes/Structure/MoveStructureMember_Change.cs
  48. 6 5
      src/PixiEditor.ChangeableDocument/Changes/Structure/RasterizeMember_Change.cs
  49. 19 12
      src/PixiEditor.ChangeableDocument/Rendering/DocumentRenderer.cs
  50. 2 2
      src/PixiEditor.ChangeableDocument/Rendering/RenderContext.cs
  51. 25 0
      src/PixiEditor.ChangeableDocument/Rendering/SceneRenderer.cs
  52. 11 12
      src/PixiEditor.DrawingApi.Core/Bridge/Operations/ICanvasImplementation.cs
  53. 14 20
      src/PixiEditor.DrawingApi.Core/Surfaces/Canvas.cs
  54. 20 13
      src/PixiEditor.DrawingApi.Skia/Implementations/SkiaCanvasImplementation.cs
  55. 0 9
      src/PixiEditor/Models/DocumentModels/DocumentUpdater.cs
  56. 9 5
      src/PixiEditor/Models/Rendering/CanvasUpdater.cs
  57. 7 7
      src/PixiEditor/Models/Rendering/MemberPreviewUpdater.cs
  58. 1 1
      src/PixiEditor/PixiEditor.csproj
  59. 2 0
      src/PixiEditor/ViewModels/Document/DocumentViewModel.cs
  60. 1 1
      src/PixiEditor/Views/Main/ViewportControls/Viewport.axaml
  61. 0 29
      src/PixiEditor/Views/Rendering/SceneObject.cs
  62. 21 66
      src/PixiEditor/Views/Rendering/UniversalScene.cs

+ 1 - 1
src/ChunkyImageLib/Operations/EllipseOperation.cs

@@ -86,7 +86,7 @@ internal class EllipseOperation : IMirroredDrawOperation
                 {
                 {
                     paint.Color = fillColor;
                     paint.Color = fillColor;
                     surf.Canvas.DrawPoints(PointMode.Lines, ellipseFill!, paint);
                     surf.Canvas.DrawPoints(PointMode.Lines, ellipseFill!, paint);
-                    surf.Canvas.DrawRect(ellipseFillRect!.Value, paint);
+                    surf.Canvas.DrawRect((RectD)ellipseFillRect!.Value, paint);
                 }
                 }
                 
                 
                 paint.Color = strokeColor;
                 paint.Color = strokeColor;

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

@@ -26,7 +26,7 @@ public class FuncContext
     public Float2 SamplePosition { get; private set; }
     public Float2 SamplePosition { get; private set; }
     public VecI Size { get; private set; }
     public VecI Size { get; private set; }
     public bool HasContext { get; private set; }
     public bool HasContext { get; private set; }
-    public RenderingContext RenderingContext { get; set; }
+    public RenderContext RenderContext { get; set; }
 
 
     public ShaderBuilder Builder { get; set; }
     public ShaderBuilder Builder { get; set; }
 
 
@@ -42,9 +42,9 @@ public class FuncContext
     {
     {
     }
     }
 
 
-    public FuncContext(RenderingContext renderingContext, ShaderBuilder builder)
+    public FuncContext(RenderContext renderContext, ShaderBuilder builder)
     {
     {
-        RenderingContext = renderingContext;
+        RenderContext = renderContext;
         Builder = builder;
         Builder = builder;
         HasContext = true;
         HasContext = true;
         OriginalPosition = new Float2("coords"); // input argument 'half4 main(float2 coords)'
         OriginalPosition = new Float2("coords"); // input argument 'half4 main(float2 coords)'

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

@@ -1,9 +1,10 @@
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core;
+using PixiEditor.DrawingApi.Core.Surfaces;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 
 
 public interface IBackgroundInput
 public interface IBackgroundInput
 {
 {
-    InputProperty<Texture?> Background { get; }
+    InputProperty<DrawingSurface?> Background { get; }
 }
 }

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

@@ -13,10 +13,9 @@ public interface IReadOnlyNode
     public IReadOnlyList<IOutputProperty> OutputProperties { get; }
     public IReadOnlyList<IOutputProperty> OutputProperties { get; }
     public IReadOnlyList<IReadOnlyKeyFrameData> KeyFrames { get; }
     public IReadOnlyList<IReadOnlyKeyFrameData> KeyFrames { get; }
     public VecD Position { get; }
     public VecD Position { get; }
-    public Texture? CachedResult { get; }
     string DisplayName { get; }
     string DisplayName { get; }
 
 
-    public Texture? Execute(RenderingContext context);
+    public void Execute(RenderContext context);
     
     
     /// <summary>
     /// <summary>
     ///     Checks if the inputs are legal. If they are not, the node should not be executed.
     ///     Checks if the inputs are legal. If they are not, the node should not be executed.

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

@@ -10,6 +10,6 @@ public interface IReadOnlyNodeGraph
     public void AddNode(IReadOnlyNode node);
     public void AddNode(IReadOnlyNode node);
     public void RemoveNode(IReadOnlyNode node);
     public void RemoveNode(IReadOnlyNode node);
     public bool TryTraverse(Action<IReadOnlyNode> action);
     public bool TryTraverse(Action<IReadOnlyNode> action);
-    public Texture? Execute(RenderingContext context);
+    public void Execute(RenderContext context);
     Queue<IReadOnlyNode> CalculateExecutionQueue(IReadOnlyNode endNode);
     Queue<IReadOnlyNode> CalculateExecutionQueue(IReadOnlyNode endNode);
 }
 }

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

@@ -5,7 +5,7 @@ using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 
 
-public interface IReadOnlyStructureNode : IReadOnlyNode
+public interface IReadOnlyStructureNode : IReadOnlyNode, ISceneObject
 {
 {
     public InputProperty<float> Opacity { get; }
     public InputProperty<float> Opacity { get; }
     public InputProperty<bool> IsVisible { get; }
     public InputProperty<bool> IsVisible { get; }

+ 15 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/ISceneObject.cs

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

+ 16 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/SceneObjectRenderContext.cs

@@ -0,0 +1,16 @@
+using PixiEditor.ChangeableDocument.Changeables.Animations;
+using PixiEditor.ChangeableDocument.Rendering;
+using PixiEditor.DrawingApi.Core.Surfaces;
+using PixiEditor.Numerics;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
+
+public class SceneObjectRenderContext : RenderContext
+{
+    public RectD LocalBounds { get; }
+
+    public SceneObjectRenderContext(DrawingSurface surface, RectD localBounds, KeyFrameTime frameTime, VecI chunkToUpdate, ChunkResolution chunkResolution, VecI docSize) : base(surface, frameTime, chunkToUpdate, chunkResolution, docSize)
+    {
+        LocalBounds = localBounds;
+    }
+}

+ 2 - 4
src/PixiEditor.ChangeableDocument/Changeables/Graph/NodeGraph.cs

@@ -119,9 +119,9 @@ public class NodeGraph : IReadOnlyNodeGraph, IDisposable
         return true;
         return true;
     }
     }
 
 
-    public Texture? Execute(RenderingContext context)
+    public void Execute(RenderContext context)
     {
     {
-        if (OutputNode == null) return null;
+        if (OutputNode == null) return;
 
 
         var queue = CalculateExecutionQueue(OutputNode);
         var queue = CalculateExecutionQueue(OutputNode);
         
         
@@ -138,7 +138,5 @@ public class NodeGraph : IReadOnlyNodeGraph, IDisposable
                 node.Execute(context);
                 node.Execute(context);
             }
             }
         }
         }
-
-        return OutputNode.Input.Value;
     }
     }
 }
 }

+ 1 - 3
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Animable/TimeNode.cs

@@ -17,12 +17,10 @@ public class TimeNode : Node
         NormalizedTime = CreateOutput("NormalizedTime", "NORMALIZED_TIME", 0.0);
         NormalizedTime = CreateOutput("NormalizedTime", "NORMALIZED_TIME", 0.0);
     }
     }
     
     
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
         ActiveFrame.Value = context.FrameTime.Frame;
         ActiveFrame.Value = context.FrameTime.Frame;
         NormalizedTime.Value = context.FrameTime.NormalizedTime;
         NormalizedTime.Value = context.FrameTime.NormalizedTime;
-        
-        return null;
     }
     }
 
 
     public override Node CreateCopy()
     public override Node CreateCopy()

+ 2 - 4
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineChannelsNode.cs

@@ -40,12 +40,12 @@ public class CombineChannelsNode : Node
         Grayscale = CreateInput(nameof(Grayscale), "GRAYSCALE", false);
         Grayscale = CreateInput(nameof(Grayscale), "GRAYSCALE", false);
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
         var size = GetSize();
         var size = GetSize();
 
 
         if (size == VecI.Zero)
         if (size == VecI.Zero)
-            return null;
+            return;
         
         
         var workingSurface = RequestTexture(0, size); 
         var workingSurface = RequestTexture(0, size); 
 
 
@@ -75,8 +75,6 @@ public class CombineChannelsNode : Node
         }
         }
 
 
         Image.Value = workingSurface;
         Image.Value = workingSurface;
-
-        return workingSurface;
     }
     }
 
 
     private VecI GetSize()
     private VecI GetSize()

+ 1 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineColorNode.cs

@@ -79,9 +79,8 @@ public class CombineColorNode : Node
         return ctx.HslaToRgba(h, s, l, a);
         return ctx.HslaToRgba(h, s, l, a);
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
-        return null;
     }
     }
 
 
 
 

+ 1 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineVecDNode.cs

@@ -32,9 +32,8 @@ public class CombineVecDNode : Node
         return ctx.NewFloat2(x, y); 
         return ctx.NewFloat2(x, y); 
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
-        return null;
     }
     }
 
 
 
 

+ 1 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineVecINode.cs

@@ -32,9 +32,8 @@ public class CombineVecINode : Node
     }
     }
 
 
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
-        return null;
     }
     }
 
 
 
 

+ 2 - 4
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/SeparateChannelsNode.cs

@@ -43,12 +43,12 @@ public class SeparateChannelsNode : Node
         Grayscale = CreateInput(nameof(Grayscale), "GRAYSCALE", false);
         Grayscale = CreateInput(nameof(Grayscale), "GRAYSCALE", false);
     }
     }
     
     
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
         var image = Image.Value;
         var image = Image.Value;
 
 
         if (image == null)
         if (image == null)
-            return null;
+            return;
         
         
         var grayscale = Grayscale.Value;
         var grayscale = Grayscale.Value;
 
 
@@ -75,8 +75,6 @@ public class SeparateChannelsNode : Node
         previewSurface.DrawingSurface.Canvas.DrawSurface(Green.Value.DrawingSurface, greenPos, context.ReplacingPaintWithOpacity);
         previewSurface.DrawingSurface.Canvas.DrawSurface(Green.Value.DrawingSurface, greenPos, context.ReplacingPaintWithOpacity);
         previewSurface.DrawingSurface.Canvas.DrawSurface(Blue.Value.DrawingSurface, bluePos, context.ReplacingPaintWithOpacity);
         previewSurface.DrawingSurface.Canvas.DrawSurface(Blue.Value.DrawingSurface, bluePos, context.ReplacingPaintWithOpacity);
         previewSurface.DrawingSurface.Canvas.DrawSurface(Alpha.Value.DrawingSurface, alphaPos, context.ReplacingPaintWithOpacity);
         previewSurface.DrawingSurface.Canvas.DrawSurface(Alpha.Value.DrawingSurface, alphaPos, context.ReplacingPaintWithOpacity);
-        
-        return previewSurface;
     }
     }
 
 
     private Texture GetImage(Texture image, ColorFilter filter, int id)
     private Texture GetImage(Texture image, ColorFilter filter, int id)

+ 1 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/SeparateColorNode.cs

@@ -43,9 +43,8 @@ public class SeparateColorNode : Node
         Color = CreateFuncInput<Half4>(nameof(Color), "COLOR", new Color());
         Color = CreateFuncInput<Half4>(nameof(Color), "COLOR", new Color());
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
-        return null;
     }
     }
     
     
     private Half4 GetColor(FuncContext ctx) =>
     private Half4 GetColor(FuncContext ctx) =>

+ 1 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/SeparateVecDNode.cs

@@ -22,9 +22,8 @@ public class SeparateVecDNode : Node
         Vector = CreateFuncInput<Float2>("Vector", "VECTOR", VecD.Zero);
         Vector = CreateFuncInput<Float2>("Vector", "VECTOR", VecD.Zero);
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
-        return null;
     }
     }
 
 
 
 

+ 1 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/SeparateVecINode.cs

@@ -21,9 +21,8 @@ public class SeparateVecINode : Node
         Vector = CreateFuncInput<Int2>("Vector", "VECTOR", new VecI(0, 0));
         Vector = CreateFuncInput<Int2>("Vector", "VECTOR", new VecI(0, 0));
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
-        return null;
     }
     }
 
 
 
 

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

@@ -25,11 +25,11 @@ public class CreateImageNode : Node
         Fill = CreateInput(nameof(Fill), "FILL", new Color(0, 0, 0, 255));
         Fill = CreateInput(nameof(Fill), "FILL", new Color(0, 0, 0, 255));
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
         if (Size.Value.X <= 0 || Size.Value.Y <= 0)
         if (Size.Value.X <= 0 || Size.Value.Y <= 0)
         {
         {
-            return null;
+            return;
         }
         }
 
 
         var surface = RequestTexture(0, Size.Value); 
         var surface = RequestTexture(0, Size.Value); 
@@ -38,8 +38,6 @@ public class CreateImageNode : Node
         surface.DrawingSurface.Canvas.DrawPaint(_paint);
         surface.DrawingSurface.Canvas.DrawPaint(_paint);
 
 
         Output.Value = surface;
         Output.Value = surface;
-
-        return Output.Value;
     }
     }
  
  
     public override Node CreateCopy() => new CreateImageNode();
     public override Node CreateCopy() => new CreateImageNode();

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

@@ -29,10 +29,10 @@ public class DebugBlendModeNode : Node
         Result = CreateOutput<Texture>(nameof(Result), "Result", null);
         Result = CreateOutput<Texture>(nameof(Result), "Result", null);
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
         if (Dst.Value is not { } dst || Src.Value is not { } src)
         if (Dst.Value is not { } dst || Src.Value is not { } src)
-            return null;
+            return;
 
 
         var size = new VecI(Math.Max(src.Size.X, dst.Size.X), int.Max(src.Size.Y, dst.Size.Y));
         var size = new VecI(Math.Max(src.Size.X, dst.Size.X), int.Max(src.Size.Y, dst.Size.Y));
         var workingSurface = RequestTexture(0, size);
         var workingSurface = RequestTexture(0, size);
@@ -43,8 +43,6 @@ public class DebugBlendModeNode : Node
         workingSurface.DrawingSurface.Canvas.DrawSurface(src.DrawingSurface, 0, 0, _paint);
         workingSurface.DrawingSurface.Canvas.DrawSurface(src.DrawingSurface, 0, 0, _paint);
         
         
         Result.Value = workingSurface;
         Result.Value = workingSurface;
-
-        return workingSurface;
     }
     }
 
 
 
 

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

@@ -26,11 +26,11 @@ public class ApplyFilterNode : Node
         Filter = CreateInput<Filter>(nameof(Filter), "FILTER", null);
         Filter = CreateInput<Filter>(nameof(Filter), "FILTER", null);
     }
     }
     
     
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
         if (Input.Value is not { } input)
         if (Input.Value is not { } input)
         {
         {
-            return null;
+            return;
         }
         }
         
         
         _paint.SetFilters(Filter.Value);
         _paint.SetFilters(Filter.Value);
@@ -40,7 +40,6 @@ public class ApplyFilterNode : Node
         _workingSurface.DrawingSurface.Canvas.DrawSurface(input.DrawingSurface, 0, 0, _paint);
         _workingSurface.DrawingSurface.Canvas.DrawSurface(input.DrawingSurface, 0, 0, _paint);
 
 
         Output.Value = _workingSurface;
         Output.Value = _workingSurface;
-        return _workingSurface;
     }
     }
 
 
     public override Node CreateCopy() => new ApplyFilterNode();
     public override Node CreateCopy() => new ApplyFilterNode();

+ 2 - 4
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/FilterNodes/FilterNode.cs

@@ -16,7 +16,7 @@ public abstract class FilterNode : Node
         Input = CreateInput<Filter>(nameof(Input), "PREVIOUS", null);
         Input = CreateInput<Filter>(nameof(Input), "PREVIOUS", null);
     }
     }
     
     
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
         var colorFilter = GetColorFilter();
         var colorFilter = GetColorFilter();
         var imageFilter = GetImageFilter();
         var imageFilter = GetImageFilter();
@@ -24,14 +24,12 @@ public abstract class FilterNode : Node
         if (colorFilter == null && imageFilter == null)
         if (colorFilter == null && imageFilter == null)
         {
         {
             Output.Value = Input.Value;
             Output.Value = Input.Value;
-            return null;
+            return;
         }
         }
 
 
         var filter = Input.Value;
         var filter = Input.Value;
 
 
         Output.Value = filter == null ? new Filter(colorFilter, imageFilter) : filter.Add(colorFilter, imageFilter);
         Output.Value = filter == null ? new Filter(colorFilter, imageFilter) : filter.Add(colorFilter, imageFilter);
-        
-        return null;
     }
     }
 
 
     protected virtual ColorFilter? GetColorFilter() => null;
     protected virtual ColorFilter? GetColorFilter() => null;

+ 35 - 19
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/FolderNode.cs

@@ -3,6 +3,7 @@ using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Rendering;
 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.Numerics;
 using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
@@ -10,48 +11,53 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 [NodeInfo("Folder")]
 [NodeInfo("Folder")]
 public class FolderNode : StructureNode, IReadOnlyFolderNode
 public class FolderNode : StructureNode, IReadOnlyFolderNode
 {
 {
-    public InputProperty<Texture?> Content { get; }
+    public InputProperty<DrawingSurface?> Content { get; }
 
 
     public FolderNode()
     public FolderNode()
     {
     {
-        Content = CreateInput<Texture?>("Content", "CONTENT", null);
+        Content = CreateInput<DrawingSurface?>("Content", "CONTENT", null);
     }
     }
 
 
     public override Node CreateCopy() => new FolderNode { MemberName = MemberName };
     public override Node CreateCopy() => new FolderNode { MemberName = MemberName };
 
 
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
-        if(Background.Value == null && Content.Value == null)
+        /*if(Background.Value == null && Content.Value == null)
         {
         {
             Output.Value = null;
             Output.Value = null;
-            return null;
+            return;
         }
         }
         
         
         if (!IsVisible.Value || Opacity.Value <= 0 || IsEmptyMask())
         if (!IsVisible.Value || Opacity.Value <= 0 || IsEmptyMask())
         {
         {
             Output.Value = Background.Value;
             Output.Value = Background.Value;
-            return Output.Value;
+            return;
         }
         }
         
         
         blendPaint.Color = new Color(255, 255, 255, 255);
         blendPaint.Color = new Color(255, 255, 255, 255);
         blendPaint.BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src;
         blendPaint.BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src;
 
 
-        VecI size = Content.Value?.Size ?? Background.Value?.Size ?? VecI.Zero;
+        if (Content.Value == null)
+        {
+            return;
+        }
+
+        VecI size = Content.Value?.Size ?? VecI.Zero;
         
         
         var outputWorkingSurface = RequestTexture(0, size); 
         var outputWorkingSurface = RequestTexture(0, size); 
         var filterlessWorkingSurface = RequestTexture(1, size); 
         var filterlessWorkingSurface = RequestTexture(1, size); 
         
         
         if (Background.Value != null)
         if (Background.Value != null)
         {
         {
-            DrawBackground(filterlessWorkingSurface, context);
+            DrawBackground(filterlessWorkingSurface.DrawingSurface, context);
             blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
             blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
         }
         }
 
 
         if (Content.Value != null)
         if (Content.Value != null)
         {
         {
             blendPaint.Color = blendPaint.Color.WithAlpha((byte)Math.Round(Opacity.Value * 255)); 
             blendPaint.Color = blendPaint.Color.WithAlpha((byte)Math.Round(Opacity.Value * 255)); 
-            DrawSurface(filterlessWorkingSurface, Content.Value, context, null);
+            DrawSurface(filterlessWorkingSurface.DrawingSurface, Content.Value, context, null);
         }
         }
 
 
         FilterlessOutput.Value = filterlessWorkingSurface;
         FilterlessOutput.Value = filterlessWorkingSurface;
@@ -62,23 +68,22 @@ public class FolderNode : StructureNode, IReadOnlyFolderNode
             {
             {
                 blendPaint.Color = new Color(255, 255, 255, 255);
                 blendPaint.Color = new Color(255, 255, 255, 255);
                 blendPaint.BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src;
                 blendPaint.BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src;
-                DrawBackground(outputWorkingSurface, context);
+                DrawBackground(outputWorkingSurface.DrawingSurface, context);
                 blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
                 blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
             }
             }
             
             
             if (Content.Value != null)
             if (Content.Value != null)
             {
             {
                 blendPaint.Color = blendPaint.Color.WithAlpha((byte)Math.Round(Opacity.Value * 255)); 
                 blendPaint.Color = blendPaint.Color.WithAlpha((byte)Math.Round(Opacity.Value * 255)); 
-                DrawSurface(outputWorkingSurface, Content.Value, context, Filters.Value);
+                DrawSurface(outputWorkingSurface.DrawingSurface, Content.Value.DrawingSurface, context, Filters.Value);
             }
             }
             
             
-            Output.Value = outputWorkingSurface;
-            return Output.Value;
+            Output.Value = outputWorkingSurface.DrawingSurface;
         }
         }
         
         
         if (Content.Value != null)
         if (Content.Value != null)
         {
         {
-            DrawSurface(outputWorkingSurface, Content.Value, context, Filters.Value);
+            DrawSurface(outputWorkingSurface.DrawingSurface, Content.Value.DrawingSurface, context, Filters.Value);
             
             
             ApplyMaskIfPresent(outputWorkingSurface, context);
             ApplyMaskIfPresent(outputWorkingSurface, context);
         }
         }
@@ -86,7 +91,7 @@ public class FolderNode : StructureNode, IReadOnlyFolderNode
         if (Background.Value != null)
         if (Background.Value != null)
         {
         {
             Texture tempSurface = RequestTexture(2, outputWorkingSurface.Size);
             Texture tempSurface = RequestTexture(2, outputWorkingSurface.Size);
-            DrawBackground(tempSurface, context);
+            DrawBackground(tempSurface.DrawingSurface, context);
             
             
             ApplyRasterClip(outputWorkingSurface, tempSurface);
             ApplyRasterClip(outputWorkingSurface, tempSurface);
             
             
@@ -94,12 +99,19 @@ public class FolderNode : StructureNode, IReadOnlyFolderNode
             blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
             blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
             tempSurface.DrawingSurface.Canvas.DrawSurface(outputWorkingSurface.DrawingSurface, 0, 0, blendPaint);
             tempSurface.DrawingSurface.Canvas.DrawSurface(outputWorkingSurface.DrawingSurface, 0, 0, blendPaint);
 
 
-            Output.Value = tempSurface;
-            return tempSurface;
+            Output.Value = tempSurface.DrawingSurface;
+            return;
         }
         }
 
 
-        Output.Value = outputWorkingSurface;
-        return Output.Value;
+        Output.Value = outputWorkingSurface.DrawingSurface;*/
+    }
+
+    public override VecD ScenePosition => throw new NotImplementedException(); 
+    public override VecD SceneSize => throw new NotImplementedException();
+
+    public override void Render(SceneObjectRenderContext sceneContext)
+    {
+        throw new NotImplementedException();
     }
     }
 
 
     public override RectD? GetTightBounds(KeyFrameTime frameTime)
     public override RectD? GetTightBounds(KeyFrameTime frameTime)
@@ -124,7 +136,11 @@ public class FolderNode : StructureNode, IReadOnlyFolderNode
             return (RectD)bounds;
             return (RectD)bounds;
         }
         }
         
         
+        return null;
+        // TODO: Implement this
+        /*
         return (RectD)RectI.Create(0, 0, Content.Value?.Size.X ?? 0, Content.Value?.Size.Y ?? 0);
         return (RectD)RectI.Create(0, 0, Content.Value?.Size.X ?? 0, Content.Value?.Size.Y ?? 0);
+    */
     }
     }
 
 
     public HashSet<Guid> GetLayerNodeGuids()
     public HashSet<Guid> GetLayerNodeGuids()

+ 16 - 15
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ImageLayerNode.cs

@@ -57,27 +57,28 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
         return (RectD?)GetLayerImageAtFrame(frameTime.Frame).FindTightCommittedBounds();
         return (RectD?)GetLayerImageAtFrame(frameTime.Frame).FindTightCommittedBounds();
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
-        var rendered = base.OnExecute(context);
+        base.OnExecute(context);
 
 
-        if (RawOutput.Connections.Count > 0)
+        /*if (RawOutput.Connections.Count > 0)
         {
         {
-            var rawWorkingSurface = TryInitWorkingSurface(GetTargetSize(context), context, 2);
+            var rawWorkingSurface = TryInitWorkingSurface(GetTargetSize(context), context.ChunkResolution, 2);
             DrawLayer(context, rawWorkingSurface, true, useFilters: false);
             DrawLayer(context, rawWorkingSurface, true, useFilters: false);
 
 
             RawOutput.Value = rawWorkingSurface;
             RawOutput.Value = rawWorkingSurface;
-        }
-
-        return rendered;
+        }*/
     }
     }
 
 
-    protected override VecI GetTargetSize(RenderingContext ctx)
+    public override VecD ScenePosition => VecD.Zero;
+    public override VecD SceneSize => size;
+
+    protected override VecI GetTargetSize(RenderContext ctx)
     {
     {
         return (GetFrameWithImage(ctx.FrameTime).Data as ChunkyImage).LatestSize;
         return (GetFrameWithImage(ctx.FrameTime).Data as ChunkyImage).LatestSize;
     }
     }
 
 
-    protected override void DrawWithoutFilters(RenderingContext ctx, Texture workingSurface, bool shouldClear,
+    protected override void DrawWithoutFilters(RenderContext ctx, Texture workingSurface, bool shouldClear,
         Paint paint)
         Paint paint)
     {
     {
         var frameImage = GetFrameWithImage(ctx.FrameTime).Data as ChunkyImage;
         var frameImage = GetFrameWithImage(ctx.FrameTime).Data as ChunkyImage;
@@ -88,13 +89,13 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
                 ctx.ChunkToUpdate * ctx.ChunkResolution.PixelSize(),
                 ctx.ChunkToUpdate * ctx.ChunkResolution.PixelSize(),
                 blendPaint) && shouldClear)
                 blendPaint) && shouldClear)
         {
         {
-            workingSurface.DrawingSurface.Canvas.DrawRect(CalculateDestinationRect(ctx), clearPaint);
+            workingSurface.DrawingSurface.Canvas.DrawRect((RectD)CalculateDestinationRect(ctx), clearPaint);
         }
         }
     }
     }
 
 
     // Draw with filters is a bit tricky since some filters sample data from chunks surrounding the chunk being drawn,
     // Draw with filters is a bit tricky since some filters sample data from chunks surrounding the chunk being drawn,
     // this is why we need to do intermediate drawing to a temporary surface and then apply filters to that surface
     // this is why we need to do intermediate drawing to a temporary surface and then apply filters to that surface
-    protected override void DrawWithFilters(RenderingContext context, Texture workingSurface,
+    protected override void DrawWithFilters(RenderContext context, Texture workingSurface,
         bool shouldClear, Paint paint)
         bool shouldClear, Paint paint)
     {
     {
         var frameImage = GetFrameWithImage(context.FrameTime).Data as ChunkyImage;
         var frameImage = GetFrameWithImage(context.FrameTime).Data as ChunkyImage;
@@ -137,7 +138,7 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
         if (shouldClear)
         if (shouldClear)
         {
         {
             workingSurface.DrawingSurface.Canvas.DrawRect(
             workingSurface.DrawingSurface.Canvas.DrawRect(
-                new RectI(
+                new RectD(
                     VecI.Zero,
                     VecI.Zero,
                     tempSize),
                     tempSize),
                 clearPaint);
                 clearPaint);
@@ -210,7 +211,7 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
     }
     }
 
 
 
 
-    private void DrawChunk(ChunkyImage frameImage, RenderingContext context, Texture tempSurface, VecI vecI,
+    private void DrawChunk(ChunkyImage frameImage, RenderContext context, Texture tempSurface, VecI vecI,
         Paint paint)
         Paint paint)
     {
     {
         VecI chunkPos = context.ChunkToUpdate + vecI;
         VecI chunkPos = context.ChunkToUpdate + vecI;
@@ -237,14 +238,14 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
         return frameImage;
         return frameImage;
     }
     }
 
 
-    protected override bool CacheChanged(RenderingContext context)
+    protected override bool CacheChanged(RenderContext context)
     {
     {
         var frame = GetFrameWithImage(context.FrameTime);
         var frame = GetFrameWithImage(context.FrameTime);
 
 
         return base.CacheChanged(context) || frame?.RequiresUpdate == true;
         return base.CacheChanged(context) || frame?.RequiresUpdate == true;
     }
     }
 
 
-    protected override void UpdateCache(RenderingContext context)
+    protected override void UpdateCache(RenderContext context)
     {
     {
         base.UpdateCache(context);
         base.UpdateCache(context);
         var imageFrame = GetFrameWithImage(context.FrameTime);
         var imageFrame = GetFrameWithImage(context.FrameTime);

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

@@ -14,27 +14,32 @@ public abstract class LayerNode : StructureNode, IReadOnlyLayerNode
     protected Dictionary<(ChunkResolution, int), Texture> workingSurfaces =
     protected Dictionary<(ChunkResolution, int), Texture> workingSurfaces =
         new Dictionary<(ChunkResolution, int), Texture>();
         new Dictionary<(ChunkResolution, int), Texture>();
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
+    {
+        base.OnExecute(context);
+    }
+
+    public override void Render(SceneObjectRenderContext sceneContext)
     {
     {
         if (!IsVisible.Value || Opacity.Value <= 0 || IsEmptyMask())
         if (!IsVisible.Value || Opacity.Value <= 0 || IsEmptyMask())
         {
         {
             Output.Value = Background.Value;
             Output.Value = Background.Value;
-            return Output.Value;
+            return;
         }
         }
 
 
         blendPaint.Color = new Color(255, 255, 255, 255);
         blendPaint.Color = new Color(255, 255, 255, 255);
         blendPaint.BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src;
         blendPaint.BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src;
 
 
-        VecI targetSize = GetTargetSize(context);
+        VecI targetSize = GetTargetSize(sceneContext);
         bool shouldClear = Background.Value == null;
         bool shouldClear = Background.Value == null;
 
 
-        if (FilterlessOutput.Connections.Count > 0)
+        /*if (FilterlessOutput.Connections.Count > 0)
         {
         {
             var filterlessWorkingSurface = TryInitWorkingSurface(targetSize, context, 0);
             var filterlessWorkingSurface = TryInitWorkingSurface(targetSize, context, 0);
 
 
             if (Background.Value != null)
             if (Background.Value != null)
             {
             {
-                DrawBackground(filterlessWorkingSurface, context);
+                DrawBackground(filterlessWorkingSurface.DrawingSurface, context);
                 blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
                 blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
             }
             }
 
 
@@ -42,26 +47,28 @@ public abstract class LayerNode : StructureNode, IReadOnlyLayerNode
             blendPaint.BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src;
             blendPaint.BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src;
 
 
             FilterlessOutput.Value = filterlessWorkingSurface;
             FilterlessOutput.Value = filterlessWorkingSurface;
-        }
+        }*/
 
 
-        var rendered = RenderImage(targetSize, context, shouldClear);
-        Output.Value = rendered;
+        var rendered = RenderImage(targetSize, sceneContext, shouldClear);
+        //TODO: optimize
+        sceneContext.TargetSurface.Canvas.DrawSurface(rendered.DrawingSurface, 0, 0);
+        
+        Output.Value = sceneContext.TargetSurface;
 
 
-        return rendered;
     }
     }
 
 
-    private Texture RenderImage(VecI size, RenderingContext context, bool shouldClear)
+    private Texture RenderImage(VecI size, RenderContext context, bool shouldClear)
     {
     {
         if (Output.Connections.Count > 0)
         if (Output.Connections.Count > 0)
         {
         {
-            var outputWorkingSurface = TryInitWorkingSurface(size, context, 1);
+            var outputWorkingSurface = TryInitWorkingSurface(size, context.ChunkResolution, 1);
 
 
             if (!HasOperations())
             if (!HasOperations())
             {
             {
                 if (Background.Value != null)
                 if (Background.Value != null)
                 {
                 {
-                    DrawBackground(outputWorkingSurface, context);
-                    blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
+                    DrawBackground(outputWorkingSurface.DrawingSurface, context);
+                    blendPaint.BlendMode = RenderContext.GetDrawingBlendMode(BlendMode.Value);
                 }
                 }
 
 
                 DrawLayer(context, outputWorkingSurface, shouldClear);
                 DrawLayer(context, outputWorkingSurface, shouldClear);
@@ -77,9 +84,9 @@ public abstract class LayerNode : StructureNode, IReadOnlyLayerNode
             if (Background.Value != null)
             if (Background.Value != null)
             {
             {
                 Texture tempSurface = RequestTexture(4, outputWorkingSurface.Size, true);
                 Texture tempSurface = RequestTexture(4, outputWorkingSurface.Size, true);
-                DrawBackground(tempSurface, context);
+                DrawBackground(tempSurface.DrawingSurface, context);
                 ApplyRasterClip(outputWorkingSurface, tempSurface);
                 ApplyRasterClip(outputWorkingSurface, tempSurface);
-                blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
+                blendPaint.BlendMode = RenderContext.GetDrawingBlendMode(BlendMode.Value);
                 tempSurface.DrawingSurface.Canvas.DrawSurface(outputWorkingSurface.DrawingSurface, 0, 0,
                 tempSurface.DrawingSurface.Canvas.DrawSurface(outputWorkingSurface.DrawingSurface, 0, 0,
                     blendPaint);
                     blendPaint);
 
 
@@ -92,9 +99,9 @@ public abstract class LayerNode : StructureNode, IReadOnlyLayerNode
         return null;
         return null;
     }
     }
 
 
-    protected abstract VecI GetTargetSize(RenderingContext ctx);
+    protected abstract VecI GetTargetSize(RenderContext ctx);
 
 
-    protected virtual void DrawLayer(RenderingContext ctx, Texture workingSurface, bool shouldClear,
+    protected virtual void DrawLayer(RenderContext ctx, Texture workingSurface, bool shouldClear,
         bool useFilters = true)
         bool useFilters = true)
     {
     {
         blendPaint.Color = blendPaint.Color.WithAlpha((byte)Math.Round(Opacity.Value * 255));
         blendPaint.Color = blendPaint.Color.WithAlpha((byte)Math.Round(Opacity.Value * 255));
@@ -111,15 +118,15 @@ public abstract class LayerNode : StructureNode, IReadOnlyLayerNode
         }
         }
     }
     }
     
     
-    protected abstract void DrawWithoutFilters(RenderingContext ctx, Texture workingSurface, bool shouldClear,
+    protected abstract void DrawWithoutFilters(RenderContext ctx, Texture workingSurface, bool shouldClear,
         Paint paint);
         Paint paint);
     
     
-    protected abstract void DrawWithFilters(RenderingContext ctx, Texture workingSurface, bool shouldClear,
+    protected abstract void DrawWithFilters(RenderContext ctx, Texture workingSurface, bool shouldClear,
         Paint paint);
         Paint paint);
 
 
-    protected Texture TryInitWorkingSurface(VecI imageSize, RenderingContext context, int id)
+    protected Texture TryInitWorkingSurface(VecI imageSize, ChunkResolution resolution, int id)
     {
     {
-        ChunkResolution targetResolution = context.ChunkResolution;
+        ChunkResolution targetResolution = resolution;
         bool hasSurface = workingSurfaces.TryGetValue((targetResolution, id), out Texture workingSurface);
         bool hasSurface = workingSurfaces.TryGetValue((targetResolution, id), out Texture workingSurface);
         VecI targetSize = (VecI)(imageSize * targetResolution.Multiplier());
         VecI targetSize = (VecI)(imageSize * targetResolution.Multiplier());
         
         

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

@@ -32,9 +32,8 @@ public class LerpColorNode : Node // TODO: ILerpable as inputs?
         return arg.NewHalf4(ShaderMath.Lerp(from, to, time)); 
         return arg.NewHalf4(ShaderMath.Lerp(from, to, time)); 
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
-        return null;
     }
     }
 
 
     public override Node CreateCopy()
     public override Node CreateCopy()

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

@@ -78,9 +78,8 @@ public class MathNode : Node
     }
     }
 
 
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
-        return null;
     }
     }
 
 
 
 

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

@@ -1,15 +1,16 @@
 using PixiEditor.ChangeableDocument.Changeables.Animations;
 using PixiEditor.ChangeableDocument.Changeables.Animations;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
-using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core;
+using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.DrawingApi.Core.Surfaces.PaintImpl;
 using PixiEditor.DrawingApi.Core.Surfaces.PaintImpl;
 using PixiEditor.Numerics;
 using PixiEditor.Numerics;
+using BlendMode = PixiEditor.ChangeableDocument.Enums.BlendMode;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 
 
 [NodeInfo("Merge")]
 [NodeInfo("Merge")]
-public class MergeNode : Node, IBackgroundInput
+public class MergeNode : Node
 {
 {
     private Paint _paint = new();
     private Paint _paint = new();
 
 
@@ -32,12 +33,12 @@ public class MergeNode : Node, IBackgroundInput
     }
     }
 
 
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
         if(Top.Value == null && Bottom.Value == null)
         if(Top.Value == null && Bottom.Value == null)
         {
         {
             Output.Value = null;
             Output.Value = null;
-            return null;
+            return;
         }
         }
         
         
         int width = Math.Max(Top.Value?.Size.X ?? Bottom.Value.Size.X, Bottom.Value?.Size.X ?? Top.Value.Size.X);
         int width = Math.Max(Top.Value?.Size.X ?? Bottom.Value.Size.X, Bottom.Value?.Size.X ?? Top.Value.Size.X);
@@ -52,14 +53,10 @@ public class MergeNode : Node, IBackgroundInput
 
 
         if(Top.Value != null)
         if(Top.Value != null)
         {
         {
-            _paint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
+            _paint.BlendMode = RenderContext.GetDrawingBlendMode(BlendMode.Value);
             workingSurface.DrawingSurface.Canvas.DrawSurface(Top.Value.DrawingSurface, 0, 0, _paint);
             workingSurface.DrawingSurface.Canvas.DrawSurface(Top.Value.DrawingSurface, 0, 0, _paint);
         }
         }
 
 
         Output.Value = workingSurface;
         Output.Value = workingSurface;
-        
-        return Output.Value;
     }
     }
-
-    InputProperty<Texture> IBackgroundInput.Background => Bottom;
 }
 }

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

@@ -25,7 +25,7 @@ public class ModifyImageLeftNode : Node, IPairNode
 
 
     public Guid OtherNode { get; set; }
     public Guid OtherNode { get; set; }
 
 
-    private ConcurrentDictionary<RenderingContext, Pixmap> pixmapCache = new();
+    private ConcurrentDictionary<RenderContext, Pixmap> pixmapCache = new();
 
 
     public ModifyImageLeftNode()
     public ModifyImageLeftNode()
     {
     {
@@ -51,12 +51,12 @@ public class ModifyImageLeftNode : Node, IPairNode
         return targetPixmap.GetPixelColor((int)x, (int)y);*/
         return targetPixmap.GetPixelColor((int)x, (int)y);*/
     }
     }
 
 
-    internal void PreparePixmap(RenderingContext forContext)
+    internal void PreparePixmap(RenderContext forContext)
     {
     {
         pixmapCache[forContext] = Image.Value?.PeekReadOnlyPixels();
         pixmapCache[forContext] = Image.Value?.PeekReadOnlyPixels();
     }
     }
 
 
-    internal void DisposePixmap(RenderingContext forContext)
+    internal void DisposePixmap(RenderContext forContext)
     {
     {
         if (pixmapCache.TryRemove(forContext, out var targetPixmap))
         if (pixmapCache.TryRemove(forContext, out var targetPixmap))
         {
         {
@@ -64,9 +64,9 @@ public class ModifyImageLeftNode : Node, IPairNode
         }
         }
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
-        return Image.Value;
+        //return Image.Value;
     }
     }
 
 
     public override Node CreateCopy() => new ModifyImageLeftNode();
     public override Node CreateCopy() => new ModifyImageLeftNode();

+ 9 - 10
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ModifyImageRightNode.cs

@@ -38,26 +38,26 @@ public class ModifyImageRightNode : Node, IPairNode, ICustomShaderNode
         Output = CreateOutput<Texture>(nameof(Output), "OUTPUT", null);
         Output = CreateOutput<Texture>(nameof(Output), "OUTPUT", null);
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext renderingContext)
+    protected override void OnExecute(RenderContext renderContext)
     {
     {
         if (OtherNode == null)
         if (OtherNode == null)
         {
         {
             FindStartNode();
             FindStartNode();
             if (OtherNode == null)
             if (OtherNode == null)
             {
             {
-                return null;
+                return;
             }
             }
         }
         }
 
 
         var startNode = FindStartNode(); 
         var startNode = FindStartNode(); 
         if (startNode == null)
         if (startNode == null)
         {
         {
-            return null;
+            return;
         }
         }
         
         
         if (startNode.Image.Value is not { Size: var size })
         if (startNode.Image.Value is not { Size: var size })
         {
         {
-            return null;
+            return;
         }
         }
 
 
         var width = size.X;
         var width = size.X;
@@ -67,18 +67,18 @@ public class ModifyImageRightNode : Node, IPairNode, ICustomShaderNode
 
 
         if (!surface.IsHardwareAccelerated)
         if (!surface.IsHardwareAccelerated)
         {
         {
-            startNode.PreparePixmap(renderingContext);
+            startNode.PreparePixmap(renderContext);
 
 
             using Pixmap targetPixmap = surface.PeekReadOnlyPixels();
             using Pixmap targetPixmap = surface.PeekReadOnlyPixels();
 
 
-            ModifyImageInParallel(renderingContext, targetPixmap, width, height);
+            ModifyImageInParallel(renderContext, targetPixmap, width, height);
 
 
-            startNode.DisposePixmap(renderingContext);
+            startNode.DisposePixmap(renderContext);
         }
         }
         else
         else
         {
         {
             ShaderBuilder builder = new(size);
             ShaderBuilder builder = new(size);
-            FuncContext context = new(renderingContext, builder);
+            FuncContext context = new(renderContext, builder);
 
 
             if (Coordinate.Connection != null)
             if (Coordinate.Connection != null)
             {
             {
@@ -129,10 +129,9 @@ public class ModifyImageRightNode : Node, IPairNode, ICustomShaderNode
         }
         }
         
         
         Output.Value = surface;
         Output.Value = surface;
-        return surface;
     }
     }
 
 
-    private unsafe void ModifyImageInParallel(RenderingContext renderingContext, Pixmap targetPixmap, int width,
+    private unsafe void ModifyImageInParallel(RenderContext renderContext, Pixmap targetPixmap, int width,
         int height)
         int height)
     {
     {
         int threads = Environment.ProcessorCount;
         int threads = Environment.ProcessorCount;

+ 9 - 36
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Node.cs

@@ -26,19 +26,6 @@ public abstract class Node : IReadOnlyNode, IDisposable
     public IReadOnlyList<OutputProperty> OutputProperties => outputs;
     public IReadOnlyList<OutputProperty> OutputProperties => outputs;
     public IReadOnlyList<KeyFrameData> KeyFrames => keyFrames;
     public IReadOnlyList<KeyFrameData> KeyFrames => keyFrames;
 
 
-    public Texture? CachedResult
-    {
-        get
-        {
-            if (_lastCachedResult == null || _lastCachedResult.IsDisposed) return null;
-            return _lastCachedResult;
-        }
-        private set
-        {
-            _lastCachedResult = value;
-        }
-    }
-
     protected virtual bool AffectedByAnimation { get; }
     protected virtual bool AffectedByAnimation { get; }
 
 
     protected virtual bool AffectedByChunkResolution { get; }
     protected virtual bool AffectedByChunkResolution { get; }
@@ -65,38 +52,23 @@ public abstract class Node : IReadOnlyNode, IDisposable
 
 
     private Dictionary<int, Texture> _managedTextures = new();
     private Dictionary<int, Texture> _managedTextures = new();
 
 
-    public Texture? Execute(RenderingContext context)
+    public void Execute(RenderContext context)
     {
     {
-        var result = ExecuteInternal(context);
-
-        if (result is null)
-        {
-            return null;
-        }
-
-        var copy = new Texture(result);
-        return copy;
+        ExecuteInternal(context);
     }
     }
 
 
-    internal Texture? ExecuteInternal(RenderingContext context)
+    internal void ExecuteInternal(RenderContext context)
     {
     {
         if (_isDisposed) throw new ObjectDisposedException("Node was disposed before execution.");
         if (_isDisposed) throw new ObjectDisposedException("Node was disposed before execution.");
 
 
-        if (!CacheChanged(context)) return CachedResult;
-
-        CachedResult = OnExecute(context);
-        if (CachedResult is { IsDisposed: true })
-        {
-            throw new ObjectDisposedException("Texture was disposed after execution.");
-        }
+        OnExecute(context);
 
 
         UpdateCache(context);
         UpdateCache(context);
-        return CachedResult;
     }
     }
 
 
-    protected abstract Texture? OnExecute(RenderingContext context);
+    protected abstract void OnExecute(RenderContext context);
 
 
-    protected virtual bool CacheChanged(RenderingContext context)
+    protected virtual bool CacheChanged(RenderContext context)
     {
     {
         return (!context.FrameTime.Equals(_lastFrameTime) && AffectedByAnimation)
         return (!context.FrameTime.Equals(_lastFrameTime) && AffectedByAnimation)
                || (AffectedByAnimation && _keyFramesDirty)
                || (AffectedByAnimation && _keyFramesDirty)
@@ -105,7 +77,7 @@ public abstract class Node : IReadOnlyNode, IDisposable
                || inputs.Any(x => x.CacheChanged);
                || inputs.Any(x => x.CacheChanged);
     }
     }
 
 
-    protected virtual void UpdateCache(RenderingContext context)
+    protected virtual void UpdateCache(RenderContext context)
     {
     {
         foreach (var input in inputs)
         foreach (var input in inputs)
         {
         {
@@ -421,7 +393,8 @@ public abstract class Node : IReadOnlyNode, IDisposable
     {
     {
     }
     }
 
 
-    internal virtual OneOf<None, IChangeInfo, List<IChangeInfo>> DeserializeAdditionalData(IReadOnlyDocument target, IReadOnlyDictionary<string, object> data)
+    internal virtual OneOf<None, IChangeInfo, List<IChangeInfo>> DeserializeAdditionalData(IReadOnlyDocument target,
+        IReadOnlyDictionary<string, object> data)
     {
     {
         return new None();
         return new None();
     }
     }

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

@@ -53,7 +53,7 @@ public class NoiseNode : Node
         Seed = CreateInput(nameof(Seed), "SEED", 0d);
         Seed = CreateInput(nameof(Seed), "SEED", 0d);
     }
     }
 
 
-    protected override Texture OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
         if (Math.Abs(previousScale - Scale.Value) > 0.000001
         if (Math.Abs(previousScale - Scale.Value) > 0.000001
             || previousSeed != Seed.Value
             || previousSeed != Seed.Value
@@ -65,14 +65,14 @@ public class NoiseNode : Node
             if (Scale.Value < 0.000001)
             if (Scale.Value < 0.000001)
             {
             {
                 Noise.Value = null;
                 Noise.Value = null;
-                return null;
+                return;
             }
             }
 
 
             var shader = SelectShader();
             var shader = SelectShader();
             if (shader == null)
             if (shader == null)
             {
             {
                 Noise.Value = null;
                 Noise.Value = null;
-                return null;
+                return;
             }
             }
 
 
             paint.Shader = shader;
             paint.Shader = shader;
@@ -91,7 +91,7 @@ public class NoiseNode : Node
         if (size.X < 1 || size.Y < 1)
         if (size.X < 1 || size.Y < 1)
         {
         {
             Noise.Value = null;
             Noise.Value = null;
-            return null;
+            return;
         }
         }
 
 
         var workingSurface = RequestTexture(0, size);
         var workingSurface = RequestTexture(0, size);
@@ -104,8 +104,6 @@ public class NoiseNode : Node
         workingSurface.DrawingSurface.Canvas.Restore();
         workingSurface.DrawingSurface.Canvas.Restore();
 
 
         Noise.Value = workingSurface;
         Noise.Value = workingSurface;
-
-        return Noise.Value;
     }
     }
 
 
     private Shader SelectShader()
     private Shader SelectShader()

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

@@ -2,6 +2,7 @@
 using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core;
+using PixiEditor.DrawingApi.Core.Surfaces;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 
 
@@ -10,10 +11,10 @@ public class OutputNode : Node, IBackgroundInput
 {
 {
     public const string InputPropertyName = "Background";
     public const string InputPropertyName = "Background";
 
 
-    public InputProperty<Texture?> Input { get; } 
+    public InputProperty<DrawingSurface?> Input { get; } 
     public OutputNode()
     public OutputNode()
     {
     {
-        Input = CreateInput<Texture>(InputPropertyName, "INPUT", null);
+        Input = CreateInput<DrawingSurface>(InputPropertyName, "INPUT", null);
     }
     }
 
 
     public override Node CreateCopy()
     public override Node CreateCopy()
@@ -21,10 +22,9 @@ public class OutputNode : Node, IBackgroundInput
         return new OutputNode();
         return new OutputNode();
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
-        return Input.Value;
     }
     }
 
 
-    InputProperty<Texture?> IBackgroundInput.Background => Input;
+    InputProperty<DrawingSurface?> IBackgroundInput.Background => Input;
 }
 }

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

@@ -38,9 +38,9 @@ public class SampleImageNode : Node
         return context.SampleTexture(Image.Value, uv);
         return context.SampleTexture(Image.Value, uv);
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
-        return Image.Value;
+        //return Image.Value;
     }
     }
 
 
     public override Node CreateCopy() => new SampleImageNode();
     public override Node CreateCopy() => new SampleImageNode();

+ 3 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/EllipseVectorData.cs

@@ -37,7 +37,8 @@ public class EllipseVectorData : ShapeVectorData, IReadOnlyEllipseData
 
 
     private void Rasterize(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint, bool applyTransform)
     private void Rasterize(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint, bool applyTransform)
     {
     {
-        var imageSize = (VecI)(Radius * 2);
+        drawingSurface.Canvas.DrawOval(Radius, Radius, paint);
+        /*var imageSize = (VecI)(Radius * 2);
         
         
         using ChunkyImage img = new ChunkyImage((VecI)GeometryAABB.Size);
         using ChunkyImage img = new ChunkyImage((VecI)GeometryAABB.Size);
 
 
@@ -71,7 +72,7 @@ public class EllipseVectorData : ShapeVectorData, IReadOnlyEllipseData
         if (applyTransform)
         if (applyTransform)
         {
         {
             drawingSurface.Canvas.RestoreToCount(num);
             drawingSurface.Canvas.RestoreToCount(num);
-        }
+        }*/
     }
     }
 
 
     public override bool IsValid()
     public override bool IsValid()

+ 3 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/RectangleVectorData.cs

@@ -37,7 +37,8 @@ public class RectangleVectorData : ShapeVectorData, IReadOnlyRectangleData
 
 
     private void Rasterize(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint, bool applyTransform)
     private void Rasterize(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint, bool applyTransform)
     {
     {
-        var imageSize = (VecI)Size; 
+        drawingSurface.Canvas.DrawRect(0, 0, (int)Size.X, (int)Size.Y, paint);
+        /*var imageSize = (VecI)Size; 
 
 
         using ChunkyImage img = new ChunkyImage(imageSize);
         using ChunkyImage img = new ChunkyImage(imageSize);
 
 
@@ -67,7 +68,7 @@ public class RectangleVectorData : ShapeVectorData, IReadOnlyRectangleData
         if (applyTransform)
         if (applyTransform)
         {
         {
             drawingSurface.Canvas.RestoreToCount(num);
             drawingSurface.Canvas.RestoreToCount(num);
-        }
+        }*/
     }
     }
 
 
     public override bool IsValid()
     public override bool IsValid()

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/DistributePointsNode.cs

@@ -18,7 +18,7 @@ public class DistributePointsNode : ShapeNode<PointsVectorData>
         Seed = CreateInput("Seed", "SEED", 0);
         Seed = CreateInput("Seed", "SEED", 0);
     }
     }
 
 
-    protected override PointsVectorData? GetShapeData(RenderingContext context)
+    protected override PointsVectorData? GetShapeData(RenderContext context)
     {
     {
         return GetPointsRandomly(context.DocumentSize);
         return GetPointsRandomly(context.DocumentSize);
     }
     }

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/EllipseNode.cs

@@ -24,7 +24,7 @@ public class EllipseNode : ShapeNode<EllipseVectorData>
         StrokeWidth = CreateInput<int>("StrokeWidth", "STROKE_WIDTH", 1);
         StrokeWidth = CreateInput<int>("StrokeWidth", "STROKE_WIDTH", 1);
     }
     }
 
 
-    protected override EllipseVectorData? GetShapeData(RenderingContext context)
+    protected override EllipseVectorData? GetShapeData(RenderContext context)
     {
     {
         return new EllipseVectorData(Position.Value, Radius.Value)
         return new EllipseVectorData(Position.Value, Radius.Value)
             { StrokeColor = StrokeColor.Value, FillColor = FillColor.Value, StrokeWidth = StrokeWidth.Value };
             { StrokeColor = StrokeColor.Value, FillColor = FillColor.Value, StrokeWidth = StrokeWidth.Value };

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

@@ -25,12 +25,12 @@ public class RasterizeShapeNode : Node
         Data = CreateInput<ShapeVectorData>("Points", "SHAPE", null);
         Data = CreateInput<ShapeVectorData>("Points", "SHAPE", null);
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
         var shape = Data.Value;
         var shape = Data.Value;
 
 
         if (shape == null || !shape.IsValid())
         if (shape == null || !shape.IsValid())
-            return null;
+            return;
 
 
         var size = context.DocumentSize;
         var size = context.DocumentSize;
         var image = RequestTexture(0, size);
         var image = RequestTexture(0, size);
@@ -39,7 +39,7 @@ public class RasterizeShapeNode : Node
 
 
         Image.Value = image;
         Image.Value = image;
         
         
-        return image;
+        return;
     }
     }
 
 
     public override Node CreateCopy() => new RasterizeShapeNode();
     public override Node CreateCopy() => new RasterizeShapeNode();

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/RemoveClosePointsNode.cs

@@ -21,7 +21,7 @@ public class RemoveClosePointsNode : ShapeNode<PointsVectorData>
         Seed = CreateInput("Seed", "SEED", 0);
         Seed = CreateInput("Seed", "SEED", 0);
     }
     }
 
 
-    protected override PointsVectorData? GetShapeData(RenderingContext context)
+    protected override PointsVectorData? GetShapeData(RenderContext context)
     {
     {
         var data = Input.Value;
         var data = Input.Value;
 
 

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

@@ -15,19 +15,19 @@ public abstract class ShapeNode<T> : Node where T : ShapeVectorData
         Output = CreateOutput<T>("Output", "OUTPUT", null);
         Output = CreateOutput<T>("Output", "OUTPUT", null);
     }
     }
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
         var data = GetShapeData(context);
         var data = GetShapeData(context);
 
 
         Output.Value = data;
         Output.Value = data;
         
         
-        if (data == null || !data.IsValid())
-            return null;
+        /*if (data == null || !data.IsValid())
+            return;
 
 
-        return RasterizePreview(data, context.DocumentSize);
+        return RasterizePreview(data, context.DocumentSize);*/
     }
     }
     
     
-    protected abstract T? GetShapeData(RenderingContext context);
+    protected abstract T? GetShapeData(RenderContext context);
 
 
     public Texture RasterizePreview(ShapeVectorData vectorData, VecI size)
     public Texture RasterizePreview(ShapeVectorData vectorData, VecI size)
     {
     {

+ 58 - 32
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/StructureNode.cs

@@ -1,22 +1,25 @@
-using ChunkyImageLib.Operations;
-using PixiEditor.ChangeableDocument.Changeables.Animations;
+using PixiEditor.ChangeableDocument.Changeables.Animations;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using PixiEditor.ChangeableDocument.ChangeInfos.Properties;
 using PixiEditor.ChangeableDocument.ChangeInfos.Properties;
-using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.ChangeableDocument.Helpers;
 using PixiEditor.ChangeableDocument.Helpers;
 using PixiEditor.ChangeableDocument.Rendering;
 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.PaintImpl;
 using PixiEditor.DrawingApi.Core.Surfaces.PaintImpl;
 using PixiEditor.Numerics;
 using PixiEditor.Numerics;
+using BlendMode = PixiEditor.ChangeableDocument.Enums.BlendMode;
 
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 
 
 public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundInput
 public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundInput
 {
 {
+    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<Texture?> Background { get; }
+    public InputProperty<DrawingSurface?> Background { get; }
     public InputProperty<float> Opacity { get; }
     public InputProperty<float> Opacity { get; }
     public InputProperty<bool> IsVisible { get; }
     public InputProperty<bool> IsVisible { get; }
     public bool ClipToPreviousMember { get; set; }
     public bool ClipToPreviousMember { get; set; }
@@ -24,11 +27,12 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
     public InputProperty<Texture?> CustomMask { get; }
     public InputProperty<Texture?> CustomMask { get; }
     public InputProperty<bool> MaskIsVisible { get; }
     public InputProperty<bool> MaskIsVisible { get; }
     public InputProperty<Filter> Filters { get; }
     public InputProperty<Filter> Filters { get; }
-    public OutputProperty<Texture?> Output { get; }
+    public OutputProperty<DrawingSurface?> Output { get; }
 
 
     public OutputProperty<Texture?> FilterlessOutput { get; }
     public OutputProperty<Texture?> FilterlessOutput { get; }
 
 
     public ChunkyImage? EmbeddedMask { get; set; }
     public ChunkyImage? EmbeddedMask { get; set; }
+
     public virtual ShapeCorners GetTransformationCorners(KeyFrameTime frameTime)
     public virtual ShapeCorners GetTransformationCorners(KeyFrameTime frameTime)
     {
     {
         return new ShapeCorners(GetTightBounds(frameTime).GetValueOrDefault());
         return new ShapeCorners(GetTightBounds(frameTime).GetValueOrDefault());
@@ -38,41 +42,59 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
     {
     {
         get => DisplayName;
         get => DisplayName;
         set => DisplayName = value;
         set => DisplayName = value;
-    } 
-    
+    }
+
     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();
     protected Paint blendPaint = new Paint();
-    
+
     private int maskCacheHash = 0;
     private int maskCacheHash = 0;
 
 
     protected StructureNode()
     protected StructureNode()
     {
     {
-        Background = CreateInput<Texture?>("Background", "BACKGROUND", null);
+        Background = CreateInput<DrawingSurface?>("Background", "BACKGROUND", null);
         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>("BlendMode", "BLEND_MODE", Enums.BlendMode.Normal);
+        BlendMode = CreateInput("BlendMode", "BLEND_MODE", Enums.BlendMode.Normal);
         CustomMask = CreateInput<Texture?>("Mask", "MASK", null);
         CustomMask = CreateInput<Texture?>("Mask", "MASK", null);
         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);
 
 
-        Output = CreateOutput<Texture?>("Output", "OUTPUT", null);
+        Output = CreateOutput<DrawingSurface?>("Output", "OUTPUT", null);
         FilterlessOutput = CreateOutput<Texture?>(nameof(FilterlessOutput), "WITHOUT_FILTERS", null);
         FilterlessOutput = CreateOutput<Texture?>(nameof(FilterlessOutput), "WITHOUT_FILTERS", null);
-        
+
         MemberName = DefaultMemberName;
         MemberName = DefaultMemberName;
     }
     }
 
 
     protected override bool AffectedByChunkResolution => true;
     protected override bool AffectedByChunkResolution => true;
     protected override bool AffectedByChunkToUpdate => true;
     protected override bool AffectedByChunkToUpdate => true;
 
 
-    protected abstract override Texture? OnExecute(RenderingContext context);
+    protected override void OnExecute(RenderContext context)
+    {
+        RectD localBounds = new RectD(0, 0, SceneSize.X, SceneSize.Y);
 
 
-    protected void ApplyMaskIfPresent(Texture surface, RenderingContext context)
+        DrawingSurface sceneSurface = context.TargetSurface;
+        
+        int savedNum = sceneSurface.Canvas.Save();
+        sceneSurface.Canvas.ClipRect(RectD.Create((VecI)ScenePosition.Floor(), (VecI)SceneSize.Ceiling()));
+        sceneSurface.Canvas.Translate((float)ScenePosition.X, (float)ScenePosition.Y);
+        
+        SceneObjectRenderContext renderObjectContext = new SceneObjectRenderContext(sceneSurface, localBounds, 
+            context.FrameTime, context.ChunkToUpdate, context.ChunkResolution, context.DocumentSize);
+        
+        Render(renderObjectContext);
+        
+        sceneSurface.Canvas.RestoreToCount(savedNum);
+    }
+
+    public abstract void Render(SceneObjectRenderContext sceneContext);
+
+    protected void ApplyMaskIfPresent(Texture surface, RenderContext context)
     {
     {
         if (MaskIsVisible.Value)
         if (MaskIsVisible.Value)
         {
         {
             if (CustomMask.Value != null)
             if (CustomMask.Value != null)
             {
             {
-                surface.DrawingSurface.Canvas.DrawSurface(CustomMask.Value.DrawingSurface, 0, 0, maskPaint); 
+                surface.DrawingSurface.Canvas.DrawSurface(CustomMask.Value.DrawingSurface, 0, 0, maskPaint);
             }
             }
             else if (EmbeddedMask != null)
             else if (EmbeddedMask != null)
             {
             {
@@ -86,13 +108,13 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
         }
         }
     }
     }
 
 
-    protected override bool CacheChanged(RenderingContext context)
+    protected override bool CacheChanged(RenderContext context)
     {
     {
         int cacheHash = EmbeddedMask?.GetCacheHash() ?? 0;
         int cacheHash = EmbeddedMask?.GetCacheHash() ?? 0;
         return base.CacheChanged(context) || maskCacheHash != cacheHash;
         return base.CacheChanged(context) || maskCacheHash != cacheHash;
     }
     }
 
 
-    protected override void UpdateCache(RenderingContext context)
+    protected override void UpdateCache(RenderContext context)
     {
     {
         base.UpdateCache(context);
         base.UpdateCache(context);
         maskCacheHash = EmbeddedMask?.GetCacheHash() ?? 0;
         maskCacheHash = EmbeddedMask?.GetCacheHash() ?? 0;
@@ -102,7 +124,7 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
     {
     {
         if (ClipToPreviousMember && Background.Value != null)
         if (ClipToPreviousMember && Background.Value != null)
         {
         {
-             toClip.DrawingSurface.Canvas.DrawSurface(clipSource.DrawingSurface, 0, 0, maskPaint);
+            toClip.DrawingSurface.Canvas.DrawSurface(clipSource.DrawingSurface, 0, 0, maskPaint);
         }
         }
     }
     }
 
 
@@ -116,32 +138,35 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
         return (MaskIsVisible.Value && (EmbeddedMask != null || CustomMask.Value != null)) || ClipToPreviousMember;
         return (MaskIsVisible.Value && (EmbeddedMask != null || CustomMask.Value != null)) || ClipToPreviousMember;
     }
     }
 
 
-    protected void DrawBackground(Texture workingSurface, RenderingContext context)
+    protected void DrawBackground(DrawingSurface drawOnto, RenderContext context)
     {
     {
         blendPaint.Color = Colors.White;
         blendPaint.Color = Colors.White;
-        DrawSurface(workingSurface, Background.Value, context, null); 
+        DrawSurface(drawOnto, Background.Value, context, null);
     }
     }
 
 
-    protected void DrawSurface(Texture workingSurface, Texture source, RenderingContext context, Filter? filter)
+    protected void DrawSurface(DrawingSurface workingSurface, DrawingSurface source, RenderContext context,
+        Filter? filter)
     {
     {
         // Maybe clip rect will allow to avoid snapshotting? Idk if it will be faster
         // Maybe clip rect will allow to avoid snapshotting? Idk if it will be faster
+        /*
         RectI sourceRect = CalculateSourceRect(workingSurface.Size, source.Size, context);
         RectI sourceRect = CalculateSourceRect(workingSurface.Size, source.Size, context);
         RectI targetRect = CalculateDestinationRect(context);
         RectI targetRect = CalculateDestinationRect(context);
         using var snapshot = source.DrawingSurface.Snapshot(sourceRect);
         using var snapshot = source.DrawingSurface.Snapshot(sourceRect);
+        */
 
 
         blendPaint.SetFilters(filter);
         blendPaint.SetFilters(filter);
-        workingSurface.DrawingSurface.Canvas.DrawImage(snapshot, targetRect.X, targetRect.Y, blendPaint);
+        workingSurface.Canvas.DrawSurface(source, 0, 0, blendPaint);
     }
     }
 
 
-    protected RectI CalculateSourceRect(VecI targetSize, VecI sourceSize, RenderingContext context)
+    protected RectI CalculateSourceRect(VecI targetSize, VecI sourceSize, RenderContext context)
     {
     {
         float divider = 1;
         float divider = 1;
-        
-        if(sourceSize.X < targetSize.X || sourceSize.Y < targetSize.Y)
+
+        if (sourceSize.X < targetSize.X || sourceSize.Y < targetSize.Y)
         {
         {
             divider = Math.Min((float)targetSize.X / sourceSize.X, (float)targetSize.Y / sourceSize.Y);
             divider = Math.Min((float)targetSize.X / sourceSize.X, (float)targetSize.Y / sourceSize.Y);
         }
         }
-        
+
         int chunkSize = (int)Math.Round(context.ChunkResolution.PixelSize() / divider);
         int chunkSize = (int)Math.Round(context.ChunkResolution.PixelSize() / divider);
         VecI chunkPos = context.ChunkToUpdate;
         VecI chunkPos = context.ChunkToUpdate;
 
 
@@ -152,11 +177,11 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
 
 
         x = Math.Clamp(x, 0, Math.Max(sourceSize.X - width, 0));
         x = Math.Clamp(x, 0, Math.Max(sourceSize.X - width, 0));
         y = Math.Clamp(y, 0, Math.Max(sourceSize.Y - height, 0));
         y = Math.Clamp(y, 0, Math.Max(sourceSize.Y - height, 0));
-        
+
         return new RectI(x, y, width, height);
         return new RectI(x, y, width, height);
     }
     }
 
 
-    protected RectI CalculateDestinationRect(RenderingContext context)
+    protected RectI CalculateDestinationRect(RenderContext context)
     {
     {
         int chunkSize = context.ChunkResolution.PixelSize();
         int chunkSize = context.ChunkResolution.PixelSize();
         VecI chunkPos = context.ChunkToUpdate;
         VecI chunkPos = context.ChunkToUpdate;
@@ -181,17 +206,18 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
         }
         }
     }
     }
 
 
-    internal override OneOf<None, IChangeInfo, List<IChangeInfo>> DeserializeAdditionalData(IReadOnlyDocument target, IReadOnlyDictionary<string, object> data)
+    internal override OneOf<None, IChangeInfo, List<IChangeInfo>> DeserializeAdditionalData(IReadOnlyDocument target,
+        IReadOnlyDictionary<string, object> data)
     {
     {
         base.DeserializeAdditionalData(target, data);
         base.DeserializeAdditionalData(target, data);
         bool hasMask = data.ContainsKey("embeddedMask");
         bool hasMask = data.ContainsKey("embeddedMask");
         if (hasMask)
         if (hasMask)
         {
         {
             ChunkyImage? mask = (ChunkyImage?)data["embeddedMask"];
             ChunkyImage? mask = (ChunkyImage?)data["embeddedMask"];
-            
+
             EmbeddedMask?.Dispose();
             EmbeddedMask?.Dispose();
-            EmbeddedMask = mask; 
-            
+            EmbeddedMask = mask;
+
             return new List<IChangeInfo> { new StructureMemberMask_ChangeInfo(Id, mask != null) };
             return new List<IChangeInfo> { new StructureMemberMask_ChangeInfo(Id, mask != null) };
         }
         }
 
 

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

@@ -37,21 +37,27 @@ public class VectorLayerNode : LayerNode, ITransformableObject, IReadOnlyVectorN
 
 
     private int lastCacheHash;
     private int lastCacheHash;
 
 
-    protected override Texture? OnExecute(RenderingContext context)
+    protected override void OnExecute(RenderContext context)
     {
     {
-        var rendered = base.OnExecute(context);
+        base.OnExecute(context);
+        
+        Output.Value = context.TargetSurface;
+    }
 
 
-        Output.Value = rendered;
+    public override VecD ScenePosition => ShapeData?.TransformedAABB.TopLeft ?? VecD.Zero;
+    public override VecD SceneSize => ShapeData?.TransformedAABB.Size ?? VecD.Zero;
 
 
-        return rendered;
+    public override void Render(SceneObjectRenderContext sceneContext)
+    {
+        Rasterize(sceneContext.TargetSurface, ChunkResolution.Full, blendPaint);
     }
     }
 
 
-    protected override VecI GetTargetSize(RenderingContext ctx)
+    protected override VecI GetTargetSize(RenderContext ctx)
     {
     {
         return ctx.DocumentSize;
         return ctx.DocumentSize;
     }
     }
 
 
-    protected override void DrawWithoutFilters(RenderingContext ctx, Texture workingSurface, bool shouldClear,
+    protected override void DrawWithoutFilters(RenderContext ctx, Texture workingSurface, bool shouldClear,
         Paint paint)
         Paint paint)
     {
     {
         if (ShapeData == null)
         if (ShapeData == null)
@@ -67,7 +73,7 @@ public class VectorLayerNode : LayerNode, ITransformableObject, IReadOnlyVectorN
         Rasterize(workingSurface.DrawingSurface, ctx.ChunkResolution, paint);
         Rasterize(workingSurface.DrawingSurface, ctx.ChunkResolution, paint);
     }
     }
 
 
-    protected override void DrawWithFilters(RenderingContext ctx, Texture workingSurface, bool shouldClear, Paint paint)
+    protected override void DrawWithFilters(RenderContext ctx, Texture workingSurface, bool shouldClear, Paint paint)
     {
     {
         if (ShapeData == null)
         if (ShapeData == null)
         {
         {
@@ -134,12 +140,12 @@ public class VectorLayerNode : LayerNode, ITransformableObject, IReadOnlyVectorN
         return new VectorShape_ChangeInfo(Id, affected);
         return new VectorShape_ChangeInfo(Id, affected);
     }
     }
 
 
-    protected override bool CacheChanged(RenderingContext context)
+    protected override bool CacheChanged(RenderContext context)
     {
     {
         return base.CacheChanged(context) || (ShapeData?.GetCacheHash() ?? -1) != lastCacheHash;
         return base.CacheChanged(context) || (ShapeData?.GetCacheHash() ?? -1) != lastCacheHash;
     }
     }
 
 
-    protected override void UpdateCache(RenderingContext context)
+    protected override void UpdateCache(RenderContext context)
     {
     {
         base.UpdateCache(context);
         base.UpdateCache(context);
         lastCacheHash = ShapeData?.GetCacheHash() ?? -1;
         lastCacheHash = ShapeData?.GetCacheHash() ?? -1;

+ 4 - 3
src/PixiEditor.ChangeableDocument/Changes/NodeGraph/NodeOperations.cs

@@ -7,6 +7,7 @@ using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using PixiEditor.ChangeableDocument.ChangeInfos.NodeGraph;
 using PixiEditor.ChangeableDocument.ChangeInfos.NodeGraph;
 using PixiEditor.ChangeableDocument.Changes.Structure;
 using PixiEditor.ChangeableDocument.Changes.Structure;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core;
+using PixiEditor.DrawingApi.Core.Surfaces;
 
 
 namespace PixiEditor.ChangeableDocument.Changes.NodeGraph;
 namespace PixiEditor.ChangeableDocument.Changes.NodeGraph;
 
 
@@ -69,9 +70,9 @@ public static class NodeOperations
     }
     }
 
 
     public static List<ConnectProperty_ChangeInfo> AppendMember(
     public static List<ConnectProperty_ChangeInfo> AppendMember(
-        InputProperty<Texture?> parentInput,
-        OutputProperty<Texture> toAddOutput,
-        InputProperty<Texture> toAddInput, Guid memberId)
+        InputProperty<DrawingSurface?> parentInput,
+        OutputProperty<DrawingSurface> toAddOutput,
+        InputProperty<DrawingSurface> toAddInput, Guid memberId)
     {
     {
         List<ConnectProperty_ChangeInfo> changes = new();
         List<ConnectProperty_ChangeInfo> changes = new();
         IOutputProperty? previouslyConnected = null;
         IOutputProperty? previouslyConnected = null;

+ 4 - 3
src/PixiEditor.ChangeableDocument/Changes/Structure/CreateStructureMember_Change.cs

@@ -6,6 +6,7 @@ using PixiEditor.ChangeableDocument.ChangeInfos.Structure;
 using PixiEditor.ChangeableDocument.Changes.NodeGraph;
 using PixiEditor.ChangeableDocument.Changes.NodeGraph;
 using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core;
+using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.Numerics;
 using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changes.Structure;
 namespace PixiEditor.ChangeableDocument.Changes.Structure;
@@ -44,8 +45,8 @@ internal class CreateStructureMember_Change : Change
 
 
         List<IChangeInfo> changes = new() { CreateChangeInfo(member) };
         List<IChangeInfo> changes = new() { CreateChangeInfo(member) };
         
         
-        InputProperty<Texture> targetInput = parentNode.InputProperties.FirstOrDefault(x => 
-            x.ValueType == typeof(Texture)) as InputProperty<Texture>;
+        InputProperty<DrawingSurface> targetInput = parentNode.InputProperties.FirstOrDefault(x => 
+            x.ValueType == typeof(DrawingSurface)) as InputProperty<DrawingSurface>;
         
         
         
         
         if (member is FolderNode folder)
         if (member is FolderNode folder)
@@ -105,7 +106,7 @@ internal class CreateStructureMember_Change : Change
         return changes;
         return changes;
     }
     }
 
 
-    private static void AppendFolder(InputProperty<Texture> backgroundInput, FolderNode folder, List<IChangeInfo> changes)
+    private static void AppendFolder(InputProperty<DrawingSurface> backgroundInput, FolderNode folder, List<IChangeInfo> changes)
     {
     {
         var appened = NodeOperations.AppendMember(backgroundInput, folder.Output, folder.Background, folder.Id);
         var appened = NodeOperations.AppendMember(backgroundInput, folder.Output, folder.Background, folder.Id);
         changes.AddRange(appened);
         changes.AddRange(appened);

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

@@ -4,6 +4,7 @@ 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;
+using PixiEditor.DrawingApi.Core.Surfaces;
 
 
 namespace PixiEditor.ChangeableDocument.Changes.Structure;
 namespace PixiEditor.ChangeableDocument.Changes.Structure;
 
 
@@ -40,9 +41,9 @@ internal class DuplicateLayer_Change : Change
         LayerNode clone = (LayerNode)existingLayer.Clone();
         LayerNode clone = (LayerNode)existingLayer.Clone();
         clone.Id = duplicateGuid;
         clone.Id = duplicateGuid;
 
 
-        InputProperty<Texture?> targetInput = parent.InputProperties.FirstOrDefault(x =>
-            x.ValueType == typeof(Texture) &&
-            x.Connection.Node is StructureNode) as InputProperty<Texture?>;
+        InputProperty<DrawingSurface?> targetInput = parent.InputProperties.FirstOrDefault(x =>
+            x.ValueType == typeof(DrawingSurface) &&
+            x.Connection.Node is StructureNode) as InputProperty<DrawingSurface?>;
 
 
         List<IChangeInfo> operations = new();
         List<IChangeInfo> operations = new();
 
 

+ 2 - 1
src/PixiEditor.ChangeableDocument/Changes/Structure/MoveStructureMember_Change.cs

@@ -4,6 +4,7 @@ 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;
+using PixiEditor.DrawingApi.Core.Surfaces;
 
 
 namespace PixiEditor.ChangeableDocument.Changes.Structure;
 namespace PixiEditor.ChangeableDocument.Changes.Structure;
 
 
@@ -51,7 +52,7 @@ internal class MoveStructureMember_Change : Change
         
         
         Guid oldBackgroundId = sourceNode.Background.Node.Id;
         Guid oldBackgroundId = sourceNode.Background.Node.Id;
 
 
-        InputProperty<Texture?> inputProperty = backgroundInput.Background;
+        InputProperty<DrawingSurface?> inputProperty = backgroundInput.Background;
 
 
         if (targetNode is FolderNode folder && putInsideFolder)
         if (targetNode is FolderNode folder && putInsideFolder)
         {
         {

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

@@ -5,6 +5,7 @@ using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using PixiEditor.ChangeableDocument.ChangeInfos.NodeGraph;
 using PixiEditor.ChangeableDocument.ChangeInfos.NodeGraph;
 using PixiEditor.ChangeableDocument.Changes.NodeGraph;
 using PixiEditor.ChangeableDocument.Changes.NodeGraph;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core;
+using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.Numerics;
 using PixiEditor.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Changes.Structure;
 namespace PixiEditor.ChangeableDocument.Changes.Structure;
@@ -55,12 +56,12 @@ internal class RasterizeMember_Change : Change
         image.EnqueueDrawImage(VecI.Zero, surface);
         image.EnqueueDrawImage(VecI.Zero, surface);
         image.CommitChanges();
         image.CommitChanges();
 
 
-        OutputProperty<Texture>? outputConnection = node.OutputProperties.FirstOrDefault(x => x is OutputProperty<Texture>) as OutputProperty<Texture>;
-        InputProperty<Texture>? outputConnectedInput =
-            outputConnection?.Connections.FirstOrDefault(x => x is InputProperty<Texture>) as InputProperty<Texture>;
+        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>;
 
 
-        InputProperty<Texture> backgroundInput = imageLayer.Background;
-        OutputProperty<Texture> toAddOutput = imageLayer.Output;
+        InputProperty<DrawingSurface> backgroundInput = imageLayer.Background;
+        OutputProperty<DrawingSurface> toAddOutput = imageLayer.Output;
 
 
         List<IChangeInfo> changeInfos = new();
         List<IChangeInfo> changeInfos = new();
         changeInfos.Add(CreateNode_ChangeInfo.CreateFromNode(imageLayer));
         changeInfos.Add(CreateNode_ChangeInfo.CreateFromNode(imageLayer));

+ 19 - 12
src/PixiEditor.ChangeableDocument/Rendering/DocumentRenderer.cs

@@ -26,7 +26,7 @@ public class DocumentRenderer
     private IReadOnlyDocument Document { get; }
     private IReadOnlyDocument Document { get; }
     public Texture OnionSkinTexture { get; set; }
     public Texture OnionSkinTexture { get; set; }
 
 
-    public Texture RenderDocument(KeyFrameTime frameTime, ChunkResolution resolution, Texture toDrawOn = null,
+    /*public Texture RenderDocument(KeyFrameTime frameTime, ChunkResolution resolution, Texture toDrawOn = null,
         Paint paint = null)
         Paint paint = null)
     {
     {
         VecI sizeInChunks = Document.Size / resolution.PixelSize();
         VecI sizeInChunks = Document.Size / resolution.PixelSize();
@@ -65,15 +65,16 @@ public class DocumentRenderer
         }
         }
 
 
         return toDrawOn;
         return toDrawOn;
-    }
+    }*/
     
     
     public OneOf<Chunk, EmptyChunk> RenderChunk(VecI chunkPos, ChunkResolution resolution, KeyFrameTime frameTime,
     public OneOf<Chunk, EmptyChunk> RenderChunk(VecI chunkPos, ChunkResolution resolution, KeyFrameTime frameTime,
         RectI? globalClippingRect = null)
         RectI? globalClippingRect = null)
     {
     {
-        RenderingContext context = new(frameTime, chunkPos, resolution, Document.Size);
+        //RenderingContext context = new(frameTime, chunkPos, resolution, Document.Size);
         try
         try
         {
         {
-            return RenderChunkOnGraph(chunkPos, resolution, globalClippingRect, Document.NodeGraph, context);
+            //return RenderChunkOnGraph(chunkPos, resolution, globalClippingRect, Document.NodeGraph, context);
+            return new EmptyChunk();
         }
         }
         catch (ObjectDisposedException)
         catch (ObjectDisposedException)
         {
         {
@@ -81,17 +82,17 @@ public class DocumentRenderer
         }
         }
         finally
         finally
         {
         {
-            context.Dispose();
+            //context.Dispose();
         }
         }
     }
     }
 
 
     public OneOf<Chunk, EmptyChunk> RenderChunk(VecI chunkPos, ChunkResolution resolution,
     public OneOf<Chunk, EmptyChunk> RenderChunk(VecI chunkPos, ChunkResolution resolution,
         IReadOnlyNode node, KeyFrameTime frameTime, RectI? globalClippingRect = null)
         IReadOnlyNode node, KeyFrameTime frameTime, RectI? globalClippingRect = null)
     {
     {
-        using RenderingContext context = new(frameTime, chunkPos, resolution, Document.Size);
+        //using RenderingContext context = new(frameTime, chunkPos, resolution, Document.Size);
         try
         try
         {
         {
-            RectI? transformedClippingRect = TransformClipRect(globalClippingRect, resolution, chunkPos);
+            /*RectI? transformedClippingRect = TransformClipRect(globalClippingRect, resolution, chunkPos);
 
 
             Texture? evaluated = node.Execute(context);
             Texture? evaluated = node.Execute(context);
             if (evaluated is null)
             if (evaluated is null)
@@ -103,7 +104,8 @@ public class DocumentRenderer
                 context);
                 context);
             evaluated.Dispose();
             evaluated.Dispose();
 
 
-            return result;
+            return result;*/
+            return new EmptyChunk();
         }
         }
         catch (ObjectDisposedException)
         catch (ObjectDisposedException)
         {
         {
@@ -111,6 +113,7 @@ public class DocumentRenderer
         }
         }
     }
     }
 
 
+    
     private static RectI? TransformClipRect(RectI? globalClippingRect, ChunkResolution resolution, VecI chunkPos)
     private static RectI? TransformClipRect(RectI? globalClippingRect, ChunkResolution resolution, VecI chunkPos)
     {
     {
         if (globalClippingRect is not RectI rect)
         if (globalClippingRect is not RectI rect)
@@ -124,11 +127,12 @@ public class DocumentRenderer
     public OneOf<Chunk, EmptyChunk> RenderLayersChunk(VecI chunkPos, ChunkResolution resolution, KeyFrameTime frame,
     public OneOf<Chunk, EmptyChunk> RenderLayersChunk(VecI chunkPos, ChunkResolution resolution, KeyFrameTime frame,
         HashSet<Guid> layersToCombine, RectI? globalClippingRect)
         HashSet<Guid> layersToCombine, RectI? globalClippingRect)
     {
     {
-        using RenderingContext context = new(frame, chunkPos, resolution, Document.Size);
+        //using RenderingContext context = new(frame, chunkPos, resolution, Document.Size);
         IReadOnlyNodeGraph membersOnlyGraph = ConstructMembersOnlyGraph(layersToCombine, Document.NodeGraph);
         IReadOnlyNodeGraph membersOnlyGraph = ConstructMembersOnlyGraph(layersToCombine, Document.NodeGraph);
         try
         try
         {
         {
-            return RenderChunkOnGraph(chunkPos, resolution, globalClippingRect, membersOnlyGraph, context);
+            //return RenderChunkOnGraph(chunkPos, resolution, globalClippingRect, membersOnlyGraph, context);
+            return new EmptyChunk();
         }
         }
         catch (ObjectDisposedException)
         catch (ObjectDisposedException)
         {
         {
@@ -136,6 +140,7 @@ public class DocumentRenderer
         }
         }
     }
     }
     
     
+    
     public Texture? RenderLayer(Guid nodeId, ChunkResolution resolution, KeyFrameTime frameTime)
     public Texture? RenderLayer(Guid nodeId, ChunkResolution resolution, KeyFrameTime frameTime)
     {
     {
         var node = Document.FindNode(nodeId);
         var node = Document.FindNode(nodeId);
@@ -177,6 +182,7 @@ public class DocumentRenderer
         return texture;
         return texture;
     }
     }
 
 
+    /*
     private static OneOf<Chunk, EmptyChunk> RenderChunkOnGraph(VecI chunkPos, ChunkResolution resolution,
     private static OneOf<Chunk, EmptyChunk> RenderChunkOnGraph(VecI chunkPos, ChunkResolution resolution,
         RectI? globalClippingRect,
         RectI? globalClippingRect,
         IReadOnlyNodeGraph graph, RenderingContext context)
         IReadOnlyNodeGraph graph, RenderingContext context)
@@ -227,6 +233,7 @@ public class DocumentRenderer
 
 
         return chunk;
         return chunk;
     }
     }
+    */
 
 
     public static IReadOnlyNodeGraph ConstructMembersOnlyGraph(IReadOnlyNodeGraph fullGraph)
     public static IReadOnlyNodeGraph ConstructMembersOnlyGraph(IReadOnlyNodeGraph fullGraph)
     {
     {
@@ -252,7 +259,7 @@ public class DocumentRenderer
             }
             }
         });
         });
 
 
-        IInputProperty<Texture> lastInput = outputNode.Input;
+        IInputProperty<DrawingSurface> lastInput = outputNode.Input;
 
 
         foreach (var layer in layersInOrder)
         foreach (var layer in layersInOrder)
         {
         {
@@ -269,7 +276,7 @@ public class DocumentRenderer
     private static OneOf<Chunk, EmptyChunk> ChunkFromResult(
     private static OneOf<Chunk, EmptyChunk> ChunkFromResult(
         ChunkResolution resolution,
         ChunkResolution resolution,
         RectI? transformedClippingRect, Image evaluated,
         RectI? transformedClippingRect, Image evaluated,
-        RenderingContext context)
+        RenderContext context)
     {
     {
         Chunk chunk = Chunk.Create(resolution);
         Chunk chunk = Chunk.Create(resolution);
 
 

+ 2 - 2
src/PixiEditor.ChangeableDocument/Rendering/RenderingContext.cs → src/PixiEditor.ChangeableDocument/Rendering/RenderContext.cs

@@ -12,7 +12,7 @@ using DrawingApiBlendMode = PixiEditor.DrawingApi.Core.Surfaces.BlendMode;
 
 
 namespace PixiEditor.ChangeableDocument.Rendering;
 namespace PixiEditor.ChangeableDocument.Rendering;
 
 
-public class RenderingContext : IDisposable
+public class RenderContext : IDisposable
 {
 {
     public Paint BlendModePaint = new() { BlendMode = DrawingApiBlendMode.SrcOver };
     public Paint BlendModePaint = new() { BlendMode = DrawingApiBlendMode.SrcOver };
     public Paint BlendModeOpacityPaint = new() { BlendMode = DrawingApiBlendMode.SrcOver };
     public Paint BlendModeOpacityPaint = new() { BlendMode = DrawingApiBlendMode.SrcOver };
@@ -27,7 +27,7 @@ public class RenderingContext : IDisposable
 
 
     public bool IsDisposed { get; private set; }
     public bool IsDisposed { get; private set; }
     
     
-    public RenderingContext(DrawingSurface targetSurface, KeyFrameTime frameTime, VecI chunkToUpdate, ChunkResolution chunkResolution, VecI docSize)
+    public RenderContext(DrawingSurface targetSurface, KeyFrameTime frameTime, VecI chunkToUpdate, ChunkResolution chunkResolution, VecI docSize)
     {
     {
         TargetSurface = targetSurface;
         TargetSurface = targetSurface;
         FrameTime = frameTime;
         FrameTime = frameTime;

+ 25 - 0
src/PixiEditor.ChangeableDocument/Rendering/SceneRenderer.cs

@@ -0,0 +1,25 @@
+using PixiEditor.ChangeableDocument.Changeables.Animations;
+using PixiEditor.ChangeableDocument.Changeables.Interfaces;
+using PixiEditor.DrawingApi.Core.Surfaces;
+using PixiEditor.Numerics;
+
+namespace PixiEditor.ChangeableDocument.Rendering;
+
+public class SceneRenderer
+{
+    public IReadOnlyDocument Document { get; }
+    
+    private readonly Func<KeyFrameTime> _frameTimeGetter;
+    
+    public SceneRenderer(IReadOnlyDocument document, Func<KeyFrameTime> frameTimeGetter)
+    {
+        Document = document;
+        _frameTimeGetter = frameTimeGetter;
+    }
+
+    public void RenderScene(DrawingSurface target)
+    {
+        using RenderContext ctx = new(target, _frameTimeGetter(), VecI.Zero, ChunkResolution.Full, Document.Size);
+        Document.NodeGraph.Execute(ctx);
+    }
+}

+ 11 - 12
src/PixiEditor.DrawingApi.Core/Bridge/Operations/ICanvasImplementation.cs

@@ -11,24 +11,24 @@ namespace PixiEditor.DrawingApi.Core.Bridge.Operations
 {
 {
     public interface ICanvasImplementation
     public interface ICanvasImplementation
     {
     {
-        public void DrawPixel(IntPtr objPtr, int posX, int posY, Paint drawingPaint);
-        public void DrawSurface(IntPtr objPtr, DrawingSurface drawingSurface, int x, int y, Paint? paint);
-        public void DrawImage(IntPtr objPtr, Image image, int x, int y);
+        public void DrawPixel(IntPtr objPtr, float posX, float posY, Paint drawingPaint);
+        public void DrawSurface(IntPtr objPtr, DrawingSurface drawingSurface, float x, float y, Paint? paint);
+        public void DrawImage(IntPtr objPtr, Image image, float x, float y);
         public int Save(IntPtr objPtr);
         public int Save(IntPtr objPtr);
         public void Restore(IntPtr objPtr);
         public void Restore(IntPtr objPtr);
         public void Scale(IntPtr objPtr, float sizeX, float sizeY);
         public void Scale(IntPtr objPtr, float sizeX, float sizeY);
         public void Translate(IntPtr objPtr, float translationX, float translationY);
         public void Translate(IntPtr objPtr, float translationX, float translationY);
         public void DrawPath(IntPtr objPtr, VectorPath path, Paint paint);
         public void DrawPath(IntPtr objPtr, VectorPath path, Paint paint);
-        public void DrawPoint(IntPtr objPtr, VecI pos, Paint paint);
+        public void DrawPoint(IntPtr objPtr, VecD pos, Paint paint);
         public void DrawPoints(IntPtr objPtr, PointMode pointMode, Point[] points, Paint paint);
         public void DrawPoints(IntPtr objPtr, PointMode pointMode, Point[] points, Paint paint);
-        public void DrawRect(IntPtr objPtr, int x, int y, int width, int height, Paint paint);
-        public void DrawCircle(IntPtr objPtr, int cx, int cy, int radius, Paint paint);
-        public void DrawOval(IntPtr objPtr, int cx, int cy, int width, int height, Paint paint);
+        public void DrawRect(IntPtr objPtr, float x, float y, float width, float height, Paint paint);
+        public void DrawCircle(IntPtr objPtr, float cx, float cy, float radius, Paint paint);
+        public void DrawOval(IntPtr objPtr, float cx, float cy, float width, float height, Paint paint);
         public void ClipPath(IntPtr objPtr, VectorPath clipPath, ClipOperation clipOperation, bool antialias);
         public void ClipPath(IntPtr objPtr, VectorPath clipPath, ClipOperation clipOperation, bool antialias);
         public void ClipRect(IntPtr objPtr, RectD rect, ClipOperation clipOperation);
         public void ClipRect(IntPtr objPtr, RectD rect, ClipOperation clipOperation);
         public void Clear(IntPtr objPtr);
         public void Clear(IntPtr objPtr);
         public void Clear(IntPtr objPtr, Color color);
         public void Clear(IntPtr objPtr, Color color);
-        public void DrawLine(IntPtr objPtr, VecI from, VecI to, Paint paint);
+        public void DrawLine(IntPtr objPtr, VecD from, VecD to, Paint paint);
         public void Flush(IntPtr objPtr);
         public void Flush(IntPtr objPtr);
         public void SetMatrix(IntPtr objPtr, Matrix3X3 finalMatrix);
         public void SetMatrix(IntPtr objPtr, Matrix3X3 finalMatrix);
         public void RestoreToCount(IntPtr objPtr, int count);
         public void RestoreToCount(IntPtr objPtr, int count);
@@ -37,12 +37,11 @@ namespace PixiEditor.DrawingApi.Core.Bridge.Operations
         public void RotateDegrees(IntPtr objectPointer, float degrees, float centerX, float centerY);
         public void RotateDegrees(IntPtr objectPointer, float degrees, float centerX, float centerY);
         public void DrawImage(IntPtr objPtr, Image image, RectD destRect, Paint paint);
         public void DrawImage(IntPtr objPtr, Image image, RectD destRect, Paint paint);
         public void DrawImage(IntPtr objPtr, Image image, RectD sourceRect, RectD destRect, Paint paint);
         public void DrawImage(IntPtr objPtr, Image image, RectD sourceRect, RectD destRect, Paint paint);
-        public void DrawBitmap(IntPtr objPtr, Bitmap bitmap, int x, int y);
+        public void DrawBitmap(IntPtr objPtr, Bitmap bitmap, float x, float y);
         public void Dispose(IntPtr objectPointer);
         public void Dispose(IntPtr objectPointer);
         public object GetNativeCanvas(IntPtr objectPointer);
         public object GetNativeCanvas(IntPtr objectPointer);
         public void DrawPaint(IntPtr objectPointer, Paint paint);
         public void DrawPaint(IntPtr objectPointer, Paint paint);
-        public void DrawImage(IntPtr objectPointer, Image image, int x, int y, Paint paint);
-        public Matrix3X3 GetActiveMatrix(IntPtr objectPointer);
-        public Canvas FromNative(object native);
+        public void DrawImage(IntPtr objectPointer, Image image, float x, float y, Paint paint);
+        public void DrawRoundRect(IntPtr objectPointer, float x, float y, float width, float height, float radiusX, float radiusY, Paint paint);
     }
     }
 }
 }

+ 14 - 20
src/PixiEditor.DrawingApi.Core/Surfaces/Canvas.cs

@@ -14,7 +14,6 @@ namespace PixiEditor.DrawingApi.Core.Surfaces
     public class Canvas : NativeObject
     public class Canvas : NativeObject
     {
     {
         public override object Native => DrawingBackendApi.Current.CanvasImplementation.GetNativeCanvas(ObjectPointer);
         public override object Native => DrawingBackendApi.Current.CanvasImplementation.GetNativeCanvas(ObjectPointer);
-        public Matrix3X3 ActiveMatrix => DrawingBackendApi.Current.CanvasImplementation.GetActiveMatrix(ObjectPointer);
 
 
         public event SurfaceChangedEventHandler? Changed;
         public event SurfaceChangedEventHandler? Changed;
 
 
@@ -30,23 +29,23 @@ namespace PixiEditor.DrawingApi.Core.Surfaces
             Changed?.Invoke(new RectD(posX, posY, 1, 1));
             Changed?.Invoke(new RectD(posX, posY, 1, 1));
         }
         }
 
 
-        public void DrawSurface(DrawingSurface original, int x, int y, Paint? paint)
+        public void DrawSurface(DrawingSurface original, float x, float y, Paint? paint)
         {
         {
             DrawingBackendApi.Current.CanvasImplementation.DrawSurface(ObjectPointer, original, x, y, paint);
             DrawingBackendApi.Current.CanvasImplementation.DrawSurface(ObjectPointer, original, x, y, paint);
             Changed?.Invoke(null);
             Changed?.Invoke(null);
         }
         }
 
 
-        public void DrawSurface(DrawingSurface original, int x, int y) => DrawSurface(original, x, y, null);
+        public void DrawSurface(DrawingSurface original, float x, float y) => DrawSurface(original, x, y, null);
 
 
         public void DrawSurface(DrawingSurface surfaceToDraw, VecI size, Paint paint)
         public void DrawSurface(DrawingSurface surfaceToDraw, VecI size, Paint paint)
         {
         {
             DrawSurface(surfaceToDraw, size.X, size.Y, paint);
             DrawSurface(surfaceToDraw, size.X, size.Y, paint);
         }
         }
 
 
-        public void DrawImage(Image image, int x, int y) =>
+        public void DrawImage(Image image, float x, float y) =>
             DrawingBackendApi.Current.CanvasImplementation.DrawImage(ObjectPointer, image, x, y);
             DrawingBackendApi.Current.CanvasImplementation.DrawImage(ObjectPointer, image, x, y);
         
         
-        public void DrawImage(Image image, int x, int y, Paint paint) =>
+        public void DrawImage(Image image, float x, float y, Paint paint) =>
             DrawingBackendApi.Current.CanvasImplementation.DrawImage(ObjectPointer, image, x, y, paint);
             DrawingBackendApi.Current.CanvasImplementation.DrawImage(ObjectPointer, image, x, y, paint);
 
 
         public void DrawImage(Image image, RectD destRect, Paint paint) =>
         public void DrawImage(Image image, RectD destRect, Paint paint) =>
@@ -104,7 +103,7 @@ namespace PixiEditor.DrawingApi.Core.Surfaces
             Changed?.Invoke(path.Bounds);
             Changed?.Invoke(path.Bounds);
         }
         }
 
 
-        public void DrawPoint(VecI pos, Paint paint)
+        public void DrawPoint(VecD pos, Paint paint)
         {
         {
             DrawingBackendApi.Current.CanvasImplementation.DrawPoint(ObjectPointer, pos, paint);
             DrawingBackendApi.Current.CanvasImplementation.DrawPoint(ObjectPointer, pos, paint);
             Changed?.Invoke(new RectD(pos.X, pos.Y, 1, 1));
             Changed?.Invoke(new RectD(pos.X, pos.Y, 1, 1));
@@ -116,31 +115,31 @@ namespace PixiEditor.DrawingApi.Core.Surfaces
             Changed?.Invoke(RectD.FromPoints(points));
             Changed?.Invoke(RectD.FromPoints(points));
         }
         }
 
 
-        public void DrawRect(int x, int y, int width, int height, Paint paint)
+        public void DrawRect(float x, float y, float width, float height, Paint paint)
         {
         {
             DrawingBackendApi.Current.CanvasImplementation.DrawRect(ObjectPointer, x, y, width, height, paint);
             DrawingBackendApi.Current.CanvasImplementation.DrawRect(ObjectPointer, x, y, width, height, paint);
             Changed?.Invoke(new RectD(x, y, width, height));
             Changed?.Invoke(new RectD(x, y, width, height));
         }
         }
 
 
-        public void DrawCircle(int centerX, int centerY, int radius, Paint paint)
+        public void DrawCircle(float centerX, float centerY, float radius, Paint paint)
         {
         {
             DrawingBackendApi.Current.CanvasImplementation.DrawCircle(ObjectPointer, centerX, centerY, radius, paint);
             DrawingBackendApi.Current.CanvasImplementation.DrawCircle(ObjectPointer, centerX, centerY, radius, paint);
             Changed?.Invoke(new RectD(centerX - radius, centerY - radius, radius * 2, radius * 2));
             Changed?.Invoke(new RectD(centerX - radius, centerY - radius, radius * 2, radius * 2));
         }
         }
 
 
-        public void DrawCircle(VecI center, int radius, Paint paint) =>
-            DrawCircle(center.X, center.Y, radius, paint);
+        public void DrawCircle(VecD center, float radius, Paint paint) =>
+            DrawCircle((float)center.X, (float)center.Y, radius, paint);
 
 
-        public void DrawOval(int centerX, int centerY, int radiusX, int radiusY, Paint paint)
+        public void DrawOval(float centerX, float centerY, float radiusX, float radiusY, Paint paint)
         {
         {
             DrawingBackendApi.Current.CanvasImplementation.DrawOval(ObjectPointer, centerX, centerY, radiusX, radiusY, paint);
             DrawingBackendApi.Current.CanvasImplementation.DrawOval(ObjectPointer, centerX, centerY, radiusX, radiusY, paint);
             Changed?.Invoke(new RectD(centerX - radiusX, centerY - radiusY, radiusX * 2, radiusY * 2));
             Changed?.Invoke(new RectD(centerX - radiusX, centerY - radiusY, radiusX * 2, radiusY * 2));
         }
         }
 
 
-        public void DrawOval(VecI center, VecI radius, Paint paint) =>
-            DrawOval(center.X, center.Y, radius.X, radius.Y, paint);
+        public void DrawOval(VecD center, VecD radius, Paint paint) =>
+            DrawOval((float)center.X, (float)center.Y, (float)radius.X, (float)radius.Y, paint);
 
 
-        public void DrawRect(RectI rect, Paint paint) => DrawRect(rect.X, rect.Y, rect.Width, rect.Height, paint);
+        public void DrawRect(RectD rect, Paint paint) => DrawRect((float)rect.X, (float)rect.Y, (float)rect.Width, (float)rect.Height, paint);
 
 
         public void ClipPath(VectorPath clipPath) => ClipPath(clipPath, ClipOperation.Intersect);
         public void ClipPath(VectorPath clipPath) => ClipPath(clipPath, ClipOperation.Intersect);
 
 
@@ -169,7 +168,7 @@ namespace PixiEditor.DrawingApi.Core.Surfaces
             Changed?.Invoke(null);
             Changed?.Invoke(null);
         }
         }
 
 
-        public void DrawLine(VecI from, VecI to, Paint paint)
+        public void DrawLine(VecD from, VecD to, Paint paint)
         {
         {
             DrawingBackendApi.Current.CanvasImplementation.DrawLine(ObjectPointer, from, to, paint);
             DrawingBackendApi.Current.CanvasImplementation.DrawLine(ObjectPointer, from, to, paint);
             Changed?.Invoke(new RectD(from, to));
             Changed?.Invoke(new RectD(from, to));
@@ -222,10 +221,5 @@ namespace PixiEditor.DrawingApi.Core.Surfaces
         {
         {
             DrawingBackendApi.Current.CanvasImplementation.Dispose(ObjectPointer);
             DrawingBackendApi.Current.CanvasImplementation.Dispose(ObjectPointer);
         }
         }
-
-        public static Canvas FromNative(object native)
-        {
-            return DrawingBackendApi.Current.CanvasImplementation.FromNative(native);
-        }
     }
     }
 }
 }

+ 20 - 13
src/PixiEditor.DrawingApi.Skia/Implementations/SkiaCanvasImplementation.cs

@@ -34,13 +34,13 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
             _surfaceImpl = surfaceImpl;
             _surfaceImpl = surfaceImpl;
         }
         }
 
 
-        public void DrawPixel(IntPtr objectPointer, int posX, int posY, Paint drawingPaint)
+        public void DrawPixel(IntPtr objectPointer, float posX, float posY, Paint drawingPaint)
         {
         {
             var canvas = ManagedInstances[objectPointer];
             var canvas = ManagedInstances[objectPointer];
             canvas.DrawPoint(posX, posY, _paintImpl.ManagedInstances[drawingPaint.ObjectPointer]);
             canvas.DrawPoint(posX, posY, _paintImpl.ManagedInstances[drawingPaint.ObjectPointer]);
         }
         }
 
 
-        public void DrawSurface(IntPtr objPtr, DrawingSurface drawingSurface, int x, int y, Paint? paint)
+        public void DrawSurface(IntPtr objPtr, DrawingSurface drawingSurface, float x, float y, Paint? paint)
         {
         {
             var canvas = ManagedInstances[objPtr];
             var canvas = ManagedInstances[objPtr];
             canvas.DrawSurface(
             canvas.DrawSurface(
@@ -49,13 +49,13 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
                 paint != null ? _paintImpl.ManagedInstances[paint.ObjectPointer] : null);
                 paint != null ? _paintImpl.ManagedInstances[paint.ObjectPointer] : null);
         }
         }
 
 
-        public void DrawImage(IntPtr objPtr, Image image, int x, int y)
+        public void DrawImage(IntPtr objPtr, Image image, float x, float y)
         {
         {
             var canvas = ManagedInstances[objPtr];
             var canvas = ManagedInstances[objPtr];
             canvas.DrawImage(_imageImpl.ManagedInstances[image.ObjectPointer], x, y);
             canvas.DrawImage(_imageImpl.ManagedInstances[image.ObjectPointer], x, y);
         }
         }
 
 
-        public void DrawImage(IntPtr objPtr, Image image, int x, int y, Paint paint)
+        public void DrawImage(IntPtr objPtr, Image image, float x, float y, Paint paint)
         {
         {
             if(!ManagedInstances.TryGetValue(objPtr, out var canvas))
             if(!ManagedInstances.TryGetValue(objPtr, out var canvas))
             {
             {
@@ -75,6 +75,13 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
             canvas.DrawImage(img, x, y, skPaint);
             canvas.DrawImage(img, x, y, skPaint);
         }
         }
 
 
+        public void DrawRoundRect(IntPtr objectPointer, float x, float y, float width, float height, float radiusX, float radiusY,
+            Paint paint)
+        {
+            ManagedInstances[objectPointer].DrawRoundRect(
+                x, y, width, height, radiusX, radiusY, _paintImpl[paint.ObjectPointer]);
+        }
+
         public Matrix3X3 GetActiveMatrix(IntPtr objectPointer)
         public Matrix3X3 GetActiveMatrix(IntPtr objectPointer)
         {
         {
             return ManagedInstances[objectPointer].TotalMatrix.ToMatrix3X3();
             return ManagedInstances[objectPointer].TotalMatrix.ToMatrix3X3();
@@ -118,11 +125,11 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
                 _paintImpl[paint.ObjectPointer]);
                 _paintImpl[paint.ObjectPointer]);
         }
         }
 
 
-        public void DrawPoint(IntPtr objPtr, VecI pos, Paint paint)
+        public void DrawPoint(IntPtr objPtr, VecD pos, Paint paint)
         {
         {
             ManagedInstances[objPtr].DrawPoint(
             ManagedInstances[objPtr].DrawPoint(
-                pos.X,
-                pos.Y,
+                (float)pos.X,
+                (float)pos.Y,
                 _paintImpl[paint.ObjectPointer]);
                 _paintImpl[paint.ObjectPointer]);
         }
         }
 
 
@@ -135,7 +142,7 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
                 _paintImpl[paint.ObjectPointer]);
                 _paintImpl[paint.ObjectPointer]);
         }
         }
 
 
-        public void DrawRect(IntPtr objPtr, int x, int y, int width, int height, Paint paint)
+        public void DrawRect(IntPtr objPtr, float x, float y, float width, float height, Paint paint)
         {
         {
             SKPaint skPaint = _paintImpl[paint.ObjectPointer];
             SKPaint skPaint = _paintImpl[paint.ObjectPointer];
             
             
@@ -143,13 +150,13 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
             canvas.DrawRect(x, y, width, height, skPaint);
             canvas.DrawRect(x, y, width, height, skPaint);
         }
         }
 
 
-        public void DrawCircle(IntPtr objPtr, int cx, int cy, int radius, Paint paint)
+        public void DrawCircle(IntPtr objPtr, float cx, float cy, float radius, Paint paint)
         {
         {
             var canvas = ManagedInstances[objPtr];
             var canvas = ManagedInstances[objPtr];
             canvas.DrawCircle(cx, cy, radius, _paintImpl[paint.ObjectPointer]);
             canvas.DrawCircle(cx, cy, radius, _paintImpl[paint.ObjectPointer]);
         }
         }
 
 
-        public void DrawOval(IntPtr objPtr, int cx, int cy, int width, int height, Paint paint)
+        public void DrawOval(IntPtr objPtr, float cx, float cy, float width, float height, Paint paint)
         {
         {
             var canvas = ManagedInstances[objPtr];
             var canvas = ManagedInstances[objPtr];
             canvas.DrawOval(cx, cy, width, height, _paintImpl[paint.ObjectPointer]);
             canvas.DrawOval(cx, cy, width, height, _paintImpl[paint.ObjectPointer]);
@@ -177,10 +184,10 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
             ManagedInstances[objPtr].Clear(color.ToSKColor());
             ManagedInstances[objPtr].Clear(color.ToSKColor());
         }
         }
 
 
-        public void DrawLine(IntPtr objPtr, VecI from, VecI to, Paint paint)
+        public void DrawLine(IntPtr objPtr, VecD from, VecD to, Paint paint)
         {
         {
             var canvas = ManagedInstances[objPtr];
             var canvas = ManagedInstances[objPtr];
-            canvas.DrawLine(from.X, from.Y, to.X, to.Y, _paintImpl[paint.ObjectPointer]);
+            canvas.DrawLine((float)from.X, (float)from.Y, (float)to.X, (float)to.Y, _paintImpl[paint.ObjectPointer]);
         }
         }
 
 
         public void DrawPaint(IntPtr objectPointer, Paint paint)
         public void DrawPaint(IntPtr objectPointer, Paint paint)
@@ -237,7 +244,7 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
                 _paintImpl[paint.ObjectPointer]);
                 _paintImpl[paint.ObjectPointer]);
         }
         }
 
 
-        public void DrawBitmap(IntPtr objPtr, Bitmap bitmap, int x, int y)
+        public void DrawBitmap(IntPtr objPtr, Bitmap bitmap, float x, float y)
         {
         {
             ManagedInstances[objPtr].DrawBitmap(_bitmapImpl[bitmap.ObjectPointer], x, y);
             ManagedInstances[objPtr].DrawBitmap(_bitmapImpl[bitmap.ObjectPointer], x, y);
         }
         }

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

@@ -353,15 +353,6 @@ internal class DocumentUpdater
 
 
     private void ProcessSize(Size_ChangeInfo info)
     private void ProcessSize(Size_ChangeInfo info)
     {
     {
-        VecI oldSize = doc.SizeBindable;
-
-        foreach ((ChunkResolution res, Texture surf) in doc.Surfaces)
-        {
-            surf.Dispose();
-            VecI size = (VecI)(info.Size * res.Multiplier());
-            doc.Surfaces[res] = new Texture(new VecI(Math.Max(size.X, 1), Math.Max(size.Y, 1)));
-        }
-
         doc.SetSize(info.Size);
         doc.SetSize(info.Size);
         doc.SetVerticalSymmetryAxisX(info.VerticalSymmetryAxisX);
         doc.SetVerticalSymmetryAxisX(info.VerticalSymmetryAxisX);
         doc.SetHorizontalSymmetryAxisY(info.HorizontalSymmetryAxisY);
         doc.SetHorizontalSymmetryAxisY(info.HorizontalSymmetryAxisY);

+ 9 - 5
src/PixiEditor/Models/Rendering/CanvasUpdater.cs

@@ -166,7 +166,8 @@ internal class CanvasUpdater
             FindGlobalChunksToRerender(chunkGatherer, rerenderDelayed);
             FindGlobalChunksToRerender(chunkGatherer, rerenderDelayed);
         
         
         ChunkResolution onionSkinResolution = chunksToRerender.Min(x => x.Key);
         ChunkResolution onionSkinResolution = chunksToRerender.Min(x => x.Key);
-        UpdateOnionSkinning(doc.Surfaces[onionSkinResolution]);
+        // TODO: Don't forget to implement this
+        //UpdateOnionSkinning(doc.Surfaces[onionSkinResolution]);
 
 
         bool updatingStoredChunks = false;
         bool updatingStoredChunks = false;
         foreach (var (res, stored) in affectedAndNonRerenderedChunks)
         foreach (var (res, stored) in affectedAndNonRerenderedChunks)
@@ -211,6 +212,7 @@ internal class CanvasUpdater
                 globalScaledClippingRectangle =
                 globalScaledClippingRectangle =
                     (RectI?)((RectI)globalClippingRectangle).Scale(resolution.Multiplier()).RoundOutwards();
                     (RectI?)((RectI)globalClippingRectangle).Scale(resolution.Multiplier()).RoundOutwards();
 
 
+            /*
             Texture screenSurface = doc.Surfaces[resolution];
             Texture screenSurface = doc.Surfaces[resolution];
             foreach (var chunkPos in chunks)
             foreach (var chunkPos in chunks)
             {
             {
@@ -226,6 +228,7 @@ internal class CanvasUpdater
                     resolution
                     resolution
                 ));
                 ));
             }
             }
+        */
         }
         }
     }
     }
 
 
@@ -299,8 +302,9 @@ internal class CanvasUpdater
 
 
         KeyFrameTime newFrameTime = new(frameIndex, newNormalizedTime);
         KeyFrameTime newFrameTime = new(frameIndex, newNormalizedTime);
 
 
-        using Texture rendered = doc.Renderer.RenderDocument(newFrameTime, ChunkResolution.Full);
-        UpdateLastRenderedFrame(rendered, frameIndex);
+        //TODO: fix this
+        //using Texture rendered = doc.Renderer.RenderDocument(newFrameTime, ChunkResolution.Full);
+        //UpdateLastRenderedFrame(rendered, frameIndex);
     }
     }
 
 
     private void UpdateLastRenderedFrame(Texture rendered, int index)
     private void UpdateLastRenderedFrame(Texture rendered, int index)
@@ -327,7 +331,7 @@ internal class CanvasUpdater
         }
         }
     }
     }
 
 
-    private void RenderChunk(VecI chunkPos, Texture screenSurface, ChunkResolution resolution,
+    /*private void RenderChunk(VecI chunkPos, Texture screenSurface, ChunkResolution resolution,
         RectI? globalClippingRectangle, RectI? globalScaledClippingRectangle)
         RectI? globalClippingRectangle, RectI? globalScaledClippingRectangle)
     {
     {
         if (screenSurface is null || screenSurface.IsDisposed)
         if (screenSurface is null || screenSurface.IsDisposed)
@@ -372,5 +376,5 @@ internal class CanvasUpdater
                     if (globalScaledClippingRectangle is not null)
                     if (globalScaledClippingRectangle is not null)
                         screenSurface.DrawingSurface.Canvas.Restore();
                         screenSurface.DrawingSurface.Canvas.Restore();
                 });
                 });
-    }
+    }*/
 }
 }

+ 7 - 7
src/PixiEditor/Models/Rendering/MemberPreviewUpdater.cs

@@ -435,12 +435,12 @@ internal class MemberPreviewUpdater
                 _ => ChunkResolution.Eighth,
                 _ => ChunkResolution.Eighth,
             };
             };
             var pos = chunkPos * resolution.PixelSize();
             var pos = chunkPos * resolution.PixelSize();
-            var rendered = doc.Renderer.RenderChunk(chunkPos, resolution, doc.AnimationHandler.ActiveFrameTime);
+            //var rendered = doc.Renderer.RenderChunk(chunkPos, resolution, doc.AnimationHandler.ActiveFrameTime);
             doc.PreviewSurface.DrawingSurface.Canvas.Save();
             doc.PreviewSurface.DrawingSurface.Canvas.Save();
             doc.PreviewSurface.DrawingSurface.Canvas.Scale(scaling);
             doc.PreviewSurface.DrawingSurface.Canvas.Scale(scaling);
             doc.PreviewSurface.DrawingSurface.Canvas.ClipRect((RectD)cumulative.GlobalArea);
             doc.PreviewSurface.DrawingSurface.Canvas.ClipRect((RectD)cumulative.GlobalArea);
             doc.PreviewSurface.DrawingSurface.Canvas.Scale(1 / (float)resolution.Multiplier());
             doc.PreviewSurface.DrawingSurface.Canvas.Scale(1 / (float)resolution.Multiplier());
-            if (rendered.IsT1)
+            /*if (rendered.IsT1)
             {
             {
                 doc.PreviewSurface.DrawingSurface.Canvas.DrawRect(pos.X, pos.Y, resolution.PixelSize(),
                 doc.PreviewSurface.DrawingSurface.Canvas.DrawRect(pos.X, pos.Y, resolution.PixelSize(),
                     resolution.PixelSize(), ClearPaint);
                     resolution.PixelSize(), ClearPaint);
@@ -449,7 +449,7 @@ internal class MemberPreviewUpdater
             {
             {
                 using var renderedChunk = rendered.AsT0;
                 using var renderedChunk = rendered.AsT0;
                 renderedChunk.DrawChunkOn(doc.PreviewSurface.DrawingSurface, pos, SmoothReplacingPaint);
                 renderedChunk.DrawChunkOn(doc.PreviewSurface.DrawingSurface, pos, SmoothReplacingPaint);
-            }
+            }*/
 
 
             doc.PreviewSurface.DrawingSurface.Canvas.Restore();
             doc.PreviewSurface.DrawingSurface.Canvas.Restore();
         }
         }
@@ -560,7 +560,7 @@ internal class MemberPreviewUpdater
         AffectedArea area,
         AffectedArea area,
         VecI position, float scaling)
         VecI position, float scaling)
     {
     {
-        QueueRender(() =>
+        /*QueueRender(() =>
         {
         {
             memberVM.PreviewSurface.DrawingSurface.Canvas.Save();
             memberVM.PreviewSurface.DrawingSurface.Canvas.Save();
             memberVM.PreviewSurface.DrawingSurface.Canvas.Scale(scaling);
             memberVM.PreviewSurface.DrawingSurface.Canvas.Scale(scaling);
@@ -601,7 +601,7 @@ internal class MemberPreviewUpdater
             }
             }
 
 
             memberVM.PreviewSurface.DrawingSurface.Canvas.Restore();
             memberVM.PreviewSurface.DrawingSurface.Canvas.Restore();
-        });
+        });*/
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -731,7 +731,7 @@ internal class MemberPreviewUpdater
 
 
     private void RenderNodePreviews(List<IRenderInfo> infos)
     private void RenderNodePreviews(List<IRenderInfo> infos)
     {
     {
-        using RenderingContext previewContext = new(doc.AnimationHandler.ActiveFrameTime,  VecI.Zero, ChunkResolution.Full, doc.SizeBindable);
+        /*using RenderingContext previewContext = new(doc.AnimationHandler.ActiveFrameTime,  VecI.Zero, ChunkResolution.Full, doc.SizeBindable);
 
 
         var outputNode = internals.Tracker.Document.NodeGraph.OutputNode;
         var outputNode = internals.Tracker.Document.NodeGraph.OutputNode;
         
         
@@ -786,7 +786,7 @@ internal class MemberPreviewUpdater
             });
             });
 
 
             infos.Add(new NodePreviewDirty_RenderInfo(node.Id));
             infos.Add(new NodePreviewDirty_RenderInfo(node.Id));
-        }
+        }*/
     }
     }
 
 
     private void QueueRender(Action action)
     private void QueueRender(Action action)

+ 1 - 1
src/PixiEditor/PixiEditor.csproj

@@ -100,7 +100,7 @@
     <PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.9.2"/>
     <PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.9.2"/>
     <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2"/>
     <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2"/>
     <PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
     <PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
-    <PackageReference Include="PixiEditor.ColorPicker.Models" Version="1.0.5"/>
+    <PackageReference Include="PixiEditor.ColorPicker.Models" Version="1.0.6"/>
     <PackageReference Include="PixiEditor.ColorPicker.AvaloniaUI" Version="1.0.6"/>
     <PackageReference Include="PixiEditor.ColorPicker.AvaloniaUI" Version="1.0.6"/>
   </ItemGroup>
   </ItemGroup>
 
 

+ 2 - 0
src/PixiEditor/ViewModels/Document/DocumentViewModel.cs

@@ -171,6 +171,7 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
     public DocumentToolsModule Tools { get; }
     public DocumentToolsModule Tools { get; }
     public DocumentOperationsModule Operations { get; }
     public DocumentOperationsModule Operations { get; }
     public DocumentRenderer Renderer { get; }
     public DocumentRenderer Renderer { get; }
+    public SceneRenderer SceneRenderer { get; }
     public DocumentEventsModule EventInlet { get; }
     public DocumentEventsModule EventInlet { get; }
 
 
     public ActionDisplayList ActionDisplays { get; } =
     public ActionDisplayList ActionDisplays { get; } =
@@ -264,6 +265,7 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
         ReferenceLayerViewModel = new(this, Internals);
         ReferenceLayerViewModel = new(this, Internals);
 
 
         Renderer = new DocumentRenderer(Internals.Tracker.Document);
         Renderer = new DocumentRenderer(Internals.Tracker.Document);
+        SceneRenderer = new SceneRenderer(Internals.Tracker.Document, () => AnimationDataViewModel.ActiveFrameTime);
     }
     }
 
 
     /// <summary>
     /// <summary>

+ 1 - 1
src/PixiEditor/Views/Main/ViewportControls/Viewport.axaml

@@ -124,7 +124,7 @@
                            VerticalAlignment="Top"
                            VerticalAlignment="Top"
                            ToolSet="{Binding Source={viewModels:MainVM}, Path=ToolsSubViewModel.ActiveToolSet}" 
                            ToolSet="{Binding Source={viewModels:MainVM}, Path=ToolsSubViewModel.ActiveToolSet}" 
                            SwitchToolSetCommand="{xaml:Command Name=PixiEditor.Tools.SwitchToolSet, UseProvided=True}"/>
                            SwitchToolSetCommand="{xaml:Command Name=PixiEditor.Tools.SwitchToolSet, UseProvided=True}"/>
-        <rendering:UniversalScene Name="scene" ZIndex=""/>
+        <rendering:UniversalScene Name="scene" ZIndex="1" SceneRenderer="{Binding Source={viewModels:MainVM DocumentManagerSVM}, Path=ActiveDocument.SceneRenderer}"/>
         <!--<rendering:Scene
         <!--<rendering:Scene
             Focusable="False" Name="scene"
             Focusable="False" Name="scene"
             ZIndex="1"
             ZIndex="1"

+ 0 - 29
src/PixiEditor/Views/Rendering/SceneObject.cs

@@ -1,29 +0,0 @@
-using PixiEditor.DrawingApi.Core.Surfaces;
-using PixiEditor.Numerics;
-
-namespace PixiEditor.Views.Rendering;
-
-public interface ISceneObject
-{
-    public VecD Position { get; set; }
-    public VecD Size { get; set; }
-    
-    public RectD GlobalBounds => new RectD(Position, Size);
-    
-    public RenderGraph Graph { get; set; }
-
-    public void RenderInScene(DrawingSurface surface)
-    {
-        RectD localBounds = new RectD(0, 0, Size.X, Size.Y);
-        
-        int savedNum = surface.Canvas.Save();
-        surface.Canvas.ClipRect(RectD.Create((VecI)Position.Floor(), (VecI)Size.Ceiling()));
-        surface.Canvas.Translate((float)Position.X, (float)Position.Y);
-        
-        RenderContext context = new RenderContext(surface, localBounds);
-        
-        Graph.RenderInLocalSpace(context);
-        
-        surface.Canvas.RestoreToCount(savedNum);
-    }
-}

+ 21 - 66
src/PixiEditor/Views/Rendering/UniversalScene.cs

@@ -5,6 +5,7 @@ using Avalonia.Rendering.SceneGraph;
 using Avalonia.Skia;
 using Avalonia.Skia;
 using Avalonia.Threading;
 using Avalonia.Threading;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.DrawingApi.Core.Surfaces.PaintImpl;
 using PixiEditor.DrawingApi.Core.Surfaces.PaintImpl;
@@ -17,12 +18,25 @@ namespace PixiEditor.Views.Rendering;
 
 
 public class UniversalScene : Zoombox.Zoombox, ICustomHitTest
 public class UniversalScene : Zoombox.Zoombox, ICustomHitTest
 {
 {
-    public List<ISceneObject> SceneObjects { get; set; } = new List<ISceneObject>();
+    public static readonly StyledProperty<SceneRenderer> SceneRendererProperty = AvaloniaProperty.Register<UniversalScene, SceneRenderer>(
+        nameof(SceneRenderer));
+
+    public SceneRenderer SceneRenderer
+    {
+        get => GetValue(SceneRendererProperty);
+        set => SetValue(SceneRendererProperty, value);
+    }
 
 
     public override void Render(DrawingContext context)
     public override void Render(DrawingContext context)
     {
     {
         // TODO: Do bounds pass, that will be used to calculate dirty bounds
         // TODO: Do bounds pass, that will be used to calculate dirty bounds
-        var drawOperation = new DrawUniversalSceneOperation(SceneObjects, Bounds, CalculateTransformMatrix());
+        
+        if (SceneRenderer is null)
+        {
+            return;
+        }
+        
+        var drawOperation = new DrawUniversalSceneOperation(SceneRenderer.RenderScene, Bounds, CalculateTransformMatrix());
         context.Custom(drawOperation);
         context.Custom(drawOperation);
 
 
         Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Render);
         Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Render);
@@ -46,13 +60,13 @@ public class UniversalScene : Zoombox.Zoombox, ICustomHitTest
 
 
 class DrawUniversalSceneOperation : SkiaDrawOperation
 class DrawUniversalSceneOperation : SkiaDrawOperation
 {
 {
-    public List<ISceneObject> SceneObjects { get; set; }
+    public event Action<DrawingSurface> RenderScene;
     public Matrix TransformMatrix { get; set; }
     public Matrix TransformMatrix { get; set; }
 
 
-    public DrawUniversalSceneOperation(List<ISceneObject> sceneObjects, Rect dirtyBounds,
+    public DrawUniversalSceneOperation(Action<DrawingSurface> renderAction, Rect dirtyBounds,
         Matrix calculateTransformMatrix) : base(dirtyBounds)
         Matrix calculateTransformMatrix) : base(dirtyBounds)
     {
     {
-        SceneObjects = sceneObjects;
+        RenderScene += renderAction;
         TransformMatrix = calculateTransformMatrix;
         TransformMatrix = calculateTransformMatrix;
     }
     }
 
 
@@ -66,22 +80,13 @@ class DrawUniversalSceneOperation : SkiaDrawOperation
         var originalMatrix = lease.SkSurface.Canvas.TotalMatrix;
         var originalMatrix = lease.SkSurface.Canvas.TotalMatrix;
 
 
         lease.SkSurface.Canvas.SetMatrix(TransformMatrix.ToSKMatrix());
         lease.SkSurface.Canvas.SetMatrix(TransformMatrix.ToSKMatrix());
-
-        foreach (ISceneObject sceneObject in SceneObjects)
-        {
-            RenderObject(lease, sceneObject);
-        }
+        DrawingSurface surface = DrawingSurface.FromNative(lease.SkSurface);
+        RenderScene?.Invoke(surface);
 
 
         DrawDebugGrid(lease.SkSurface.Canvas);
         DrawDebugGrid(lease.SkSurface.Canvas);
         lease.SkSurface.Canvas.SetMatrix(originalMatrix);
         lease.SkSurface.Canvas.SetMatrix(originalMatrix);
     }
     }
 
 
-    private static void RenderObject(ISkiaSharpApiLease lease, ISceneObject sceneObject)
-    {
-        DrawingSurface surface = DrawingSurface.FromNative(lease.SkSurface);
-        sceneObject.RenderInScene(surface);
-    } 
-
     private void DrawDebugGrid(SKCanvas canvas)
     private void DrawDebugGrid(SKCanvas canvas)
     {
     {
         canvas.DrawText("(0, 0)", 5, -5, new SKPaint() { Color = SKColors.White });
         canvas.DrawText("(0, 0)", 5, -5, new SKPaint() { Color = SKColors.White });
@@ -106,53 +111,3 @@ class DrawUniversalSceneOperation : SkiaDrawOperation
         }
         }
     }
     }
 }
 }
-
-public class RenderContext
-{
-    public DrawingSurface Surface { get; }
-    public RectD LocalBounds { get; }
-    
-    public RenderContext(DrawingSurface surface, RectD localBounds)
-    {
-        Surface = surface;
-        LocalBounds = localBounds;
-    }
-}
-
-public class RenderGraph
-{
-    public List<EffectNode> Nodes { get; set; } = new List<EffectNode>();
-
-    public void RenderInLocalSpace(RenderContext context)
-    {
-        foreach (EffectNode node in Nodes)
-        {
-            node.Render(context);
-        }
-    }
-}
-
-public abstract class EffectNode
-{
-    public abstract void Render(RenderContext context);
-}
-
-class DrawRectNode : EffectNode
-{
-    public override void Render(RenderContext context)
-    {
-        context.Surface.Canvas.DrawRect(0, 0, (int)context.LocalBounds.Width, (int)context.LocalBounds.Height, new Paint 
-            { Color = Colors.Aquamarine, BlendMode = BlendMode.Difference} );
-    }
-}
-
-class ApplyEffectNode : EffectNode
-{
-    public override void Render(RenderContext context)
-    {
-        using Paint paint = new Paint();
-        paint.ColorFilter = Filters.RedGrayscaleFilter;
-
-        context.Surface.Canvas.DrawPaint(paint);
-    }
-}