Browse Source

merge node wip

flabbet 10 months ago
parent
commit
fbb4b2cb64

+ 90 - 19
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/MergeNode.cs

@@ -10,21 +10,45 @@ using BlendMode = PixiEditor.ChangeableDocument.Enums.BlendMode;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 
 [NodeInfo("Merge")]
-public class MergeNode : Node
+public class MergeNode : RenderNode
 {
-    private Paint _paint = new();
-
     public InputProperty<BlendMode> BlendMode { get; }
-    public InputProperty<Texture?> Top { get; }
-    public InputProperty<Texture?> Bottom { get; }
-    public OutputProperty<Texture?> Output { get; }
+    public RenderInputProperty Top { get; }
+    public RenderInputProperty Bottom { get; }
+
+    private Paint paint = new Paint();
+    
+    private static readonly Paint blendPaint = new Paint() { BlendMode = DrawingApi.Core.Surfaces.BlendMode.SrcOver };
+
+    private int topLayer;
+    private int bottomLayer;
     
     public MergeNode() 
     {
         BlendMode = CreateInput("BlendMode", "BlendMode", Enums.BlendMode.Normal);
-        Top = CreateInput<Texture?>("Top", "TOP", null);
-        Bottom = CreateInput<Texture?>("Bottom", "BOTTOM", null);
-        Output = CreateOutput<Texture?>("Output", "OUTPUT", null);
+        Top = CreateRenderInput("Top", "TOP", context =>
+        {
+            var output = Output.GetFirstRenderTarget(context);
+            if(output == null)
+            {
+                return null;
+            }
+
+            topLayer = output.Canvas.SaveLayer(blendPaint);
+            return output;
+        });
+        Bottom = CreateRenderInput("Bottom", "BOTTOM", context =>
+        {
+            var output = Output.GetFirstRenderTarget(context);
+            
+            if(output == null)
+            {
+                return null;
+            }
+            
+            bottomLayer = output.Canvas.SaveLayer(blendPaint);
+            return output;
+        });
     }
 
     public override Node CreateCopy()
@@ -33,30 +57,77 @@ public class MergeNode : Node
     }
 
 
-    protected override void OnExecute(RenderContext context)
+    protected override DrawingSurface? ExecuteRender(RenderContext context)
     {
         if(Top.Value == null && Bottom.Value == null)
         {
-            Output.Value = null;
-            return;
+            return null;
         }
         
-        int width = Math.Max(Top.Value?.Size.X ?? Bottom.Value.Size.X, Bottom.Value?.Size.X ?? Top.Value.Size.X);
-        int height = Math.Max(Top.Value?.Size.Y ?? Bottom.Value.Size.Y, Bottom.Value?.Size.Y ?? Top.Value.Size.Y);
+        var target = context.RenderSurface;
         
-        Texture workingSurface = RequestTexture(0, new VecI(width, height), true);
+        if(target == null || target.DeviceClipBounds.Size == VecI.Zero)
+        {
+            return null;
+        }
+
+        Merge(target);
+
+        return target;
+    }
+
+    private void Merge(DrawingSurface target)
+    {
+        if (Bottom.Value != null && Top.Value != null)
+        {
+            Texture texTop = RequestTexture(0, target.DeviceClipBounds.Size, false);
+            Texture texBottom = RequestTexture(1, target.DeviceClipBounds.Size, false);
+            
+            paint.BlendMode = RenderContext.GetDrawingBlendMode(BlendMode.Value);
+            texBottom.DrawingSurface.Canvas.DrawSurface(texTop.DrawingSurface, 0, 0, blendPaint);
+            
+            target.Canvas.DrawSurface(texTop.DrawingSurface, 0, 0);
+            return;
+        }
         
         if(Bottom.Value != null)
         {
-            workingSurface.DrawingSurface.Canvas.DrawSurface(Bottom.Value.DrawingSurface, 0, 0);
+            Texture tex = RequestTexture(1, target.DeviceClipBounds.Size, false);
+            target.Canvas.DrawSurface(tex.DrawingSurface, 0, 0);
         }
 
         if(Top.Value != null)
         {
-            _paint.BlendMode = RenderContext.GetDrawingBlendMode(BlendMode.Value);
-            workingSurface.DrawingSurface.Canvas.DrawSurface(Top.Value.DrawingSurface, 0, 0, _paint);
+            Texture tex = RequestTexture(0, target.DeviceClipBounds.Size, false);
+            target.Canvas.DrawSurface(tex.DrawingSurface, 0, 0);
         }
+    }
+
+    public override RectD? GetPreviewBounds(int frame, string elementToRenderName = "")
+    {
+        if(Top.Value == null && Bottom.Value == null)
+        {
+            return null;
+        }
+        
+        return new RectD(VecI.Zero, new VecI(128, 128)); 
+    }
 
-        Output.Value = workingSurface;
+    public override bool RenderPreview(DrawingSurface renderOn, ChunkResolution resolution, int frame, string elementToRenderName)
+    {
+        if (Top.Value == null && Bottom.Value == null)
+        {
+            return false;
+        }
+
+        Merge(renderOn);
+
+        return true;
+    }
+
+    public override void Dispose()
+    {
+        base.Dispose();
+        paint.Dispose();
     }
 }

+ 6 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/RenderNode.cs

@@ -16,7 +16,12 @@ public abstract class RenderNode : Node, IPreviewRenderable
 
     protected override void OnExecute(RenderContext context)
     {
-        Output.Value = ExecuteRender(context);
+        using RenderContext ctx = new RenderContext(
+            Output.GetFirstRenderTarget(context), 
+            context.FrameTime, context.ChunkResolution, context.DocumentSize, context.Opacity);
+        ctx.FullRerender = context.FullRerender;
+        
+        Output.Value = ExecuteRender(ctx);
     }
     
     protected abstract DrawingSurface? ExecuteRender(RenderContext context);

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

@@ -76,7 +76,7 @@ public abstract class StructureNode : RenderNode, IReadOnlyStructureNode, IRende
         DrawingSurface renderTarget = null;
         if (Output.Connections.Count > 0 || RenderTarget.Value != null)
         {
-            renderTarget = RenderTarget.Value ?? Output.GetFirstRenderTarget(context);
+            renderTarget = RenderTarget.Value ?? context.RenderSurface;
             RenderForOutput(context, renderTarget, Output);
         }
 

+ 1 - 0
src/PixiEditor.DrawingApi.Core/Bridge/Operations/ICanvasImplementation.cs

@@ -46,5 +46,6 @@ namespace PixiEditor.DrawingApi.Core.Bridge.Operations
         public Matrix3X3 GetTotalMatrix(IntPtr objectPointer);
         public int SaveLayer(IntPtr objectPtr);
         public int SaveLayer(IntPtr objectPtr, Paint paint);
+        public int SaveLayer(IntPtr objectPtr, Paint paint, RectD bounds);
     }
 }

+ 1 - 0
src/PixiEditor.DrawingApi.Core/Bridge/Operations/ISurfaceImplementation.cs

@@ -20,6 +20,7 @@ public interface ISurfaceImplementation
     public void Flush(DrawingSurface drawingSurface);
     public DrawingSurface FromNative(object native);
     public RectI GetDeviceClipBounds(DrawingSurface surface);
+    public RectD GetLocalClipBounds(DrawingSurface surface);
     public void Unmanage(DrawingSurface surface);
 }
 

+ 5 - 0
src/PixiEditor.DrawingApi.Core/Surfaces/Canvas.cs

@@ -227,6 +227,11 @@ namespace PixiEditor.DrawingApi.Core.Surfaces
         {
             return DrawingBackendApi.Current.CanvasImplementation.SaveLayer(ObjectPointer, paint);
         }
+        
+        public int SaveLayer(Paint paint, RectD bounds)
+        {
+            return DrawingBackendApi.Current.CanvasImplementation.SaveLayer(ObjectPointer, paint, bounds);
+        }
 
         public override void Dispose()
         {

+ 5 - 0
src/PixiEditor.DrawingApi.Core/Surfaces/DrawingSurface.cs

@@ -15,6 +15,11 @@ namespace PixiEditor.DrawingApi.Core.Surfaces
         {
             get => DrawingBackendApi.Current.SurfaceImplementation.GetDeviceClipBounds(this);
         }
+        
+        public RectD LocalClipBounds
+        {
+            get => DrawingBackendApi.Current.SurfaceImplementation.GetLocalClipBounds(this);
+        }
 
         public event SurfaceChangedEventHandler? Changed;
 

+ 5 - 0
src/PixiEditor.DrawingApi.Skia/Implementations/SkiaCanvasImplementation.cs

@@ -96,6 +96,11 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
         {
             return ManagedInstances[objectPtr].SaveLayer(_paintImpl.ManagedInstances[paint.ObjectPointer]);
         }
+        
+        public int SaveLayer(IntPtr objectPtr, Paint paint, RectD bounds)
+        {
+            return ManagedInstances[objectPtr].SaveLayer(bounds.ToSKRect(), _paintImpl.ManagedInstances[paint.ObjectPointer]);
+        }
 
         public Matrix3X3 GetActiveMatrix(IntPtr objectPointer)
         {

+ 6 - 0
src/PixiEditor.DrawingApi.Skia/Implementations/SkiaSurfaceImplementation.cs

@@ -172,6 +172,12 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
             SKRectI rect = ManagedInstances[surface.ObjectPointer].Canvas.DeviceClipBounds;
             return new RectI(rect.Left, rect.Top, rect.Width, rect.Height);
         }
+        
+        public RectD GetLocalClipBounds(DrawingSurface surface)
+        {
+            SKRect rect = ManagedInstances[surface.ObjectPointer].Canvas.LocalClipBounds;
+            return new RectD(rect.Left, rect.Top, rect.Width, rect.Height);
+        }
 
         public void Unmanage(DrawingSurface surface)
         {