Browse Source

Combine Channels node is working

flabbet 10 months ago
parent
commit
3675cfcd1b

+ 69 - 40
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineChannelsNode.cs

@@ -1,4 +1,5 @@
-using PixiEditor.ChangeableDocument.Rendering;
+using PixiEditor.ChangeableDocument.Helpers;
+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;
@@ -7,7 +8,7 @@ using PixiEditor.Numerics;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
 
 
 [NodeInfo("CombineChannels")]
 [NodeInfo("CombineChannels")]
-public class CombineChannelsNode : Node
+public class CombineChannelsNode : RenderNode
 {
 {
     private readonly Paint _screenPaint = new() { BlendMode = BlendMode.Screen };
     private readonly Paint _screenPaint = new() { BlendMode = BlendMode.Screen };
     private readonly Paint _clearPaint = new() { BlendMode = BlendMode.DstIn };
     private readonly Paint _clearPaint = new() { BlendMode = BlendMode.DstIn };
@@ -16,92 +17,120 @@ public class CombineChannelsNode : Node
     private readonly ColorFilter _greenFilter = ColorFilter.CreateColorMatrix(ColorMatrix.UseGreen + ColorMatrix.OpaqueAlphaOffset);
     private readonly ColorFilter _greenFilter = ColorFilter.CreateColorMatrix(ColorMatrix.UseGreen + ColorMatrix.OpaqueAlphaOffset);
     private readonly ColorFilter _blueFilter = ColorFilter.CreateColorMatrix(ColorMatrix.UseBlue + ColorMatrix.OpaqueAlphaOffset);
     private readonly ColorFilter _blueFilter = ColorFilter.CreateColorMatrix(ColorMatrix.UseBlue + ColorMatrix.OpaqueAlphaOffset);
 
 
-    public InputProperty<Texture> Red { get; }
+    public RenderInputProperty Red { get; }
     
     
-    public InputProperty<Texture> Green { get; }
+    public RenderInputProperty Green { get; }
     
     
-    public InputProperty<Texture> Blue { get; }
+    public RenderInputProperty Blue { get; }
     
     
-    public InputProperty<Texture> Alpha { get; }
+    public RenderInputProperty Alpha { get; }
 
 
-    public OutputProperty<Texture> Image { get; }
-    
     // TODO: Either use a shader to combine each, or find a way to automatically "detect" if alpha channel is grayscale or not, oooor find an even better solution
     // TODO: Either use a shader to combine each, or find a way to automatically "detect" if alpha channel is grayscale or not, oooor find an even better solution
     public InputProperty<bool> Grayscale { get; }
     public InputProperty<bool> Grayscale { get; }
 
 
     public CombineChannelsNode()
     public CombineChannelsNode()
     {
     {
-        Red = CreateInput<Texture>(nameof(Red), "RED", null);
-        Green = CreateInput<Texture>(nameof(Green), "GREEN", null);
-        Blue = CreateInput<Texture>(nameof(Blue), "BLUE", null);
-        Alpha = CreateInput<Texture>(nameof(Alpha), "ALPHA", null);
+        Red = CreateRenderInput("Red", "RED");
+        Green = CreateRenderInput("Green","GREEN");
+        Blue = CreateRenderInput("Blue", "BLUE");
+        Alpha = CreateRenderInput("Alpha", "ALPHA");
         
         
-        Image = CreateOutput<Texture>(nameof(Image), "IMAGE", null);
         Grayscale = CreateInput(nameof(Grayscale), "GRAYSCALE", false);
         Grayscale = CreateInput(nameof(Grayscale), "GRAYSCALE", false);
     }
     }
 
 
-    protected override void OnExecute(RenderContext context)
+    
+    protected override void OnPaint(RenderContext context, DrawingSurface surface)
     {
     {
-        var size = GetSize();
-
-        if (size == VecI.Zero)
-            return;
-        
-        var workingSurface = RequestTexture(0, size); 
-
+        int saved = surface.Canvas.SaveLayer();
         if (Red.Value is { } red)
         if (Red.Value is { } red)
         {
         {
             _screenPaint.ColorFilter = _redFilter;
             _screenPaint.ColorFilter = _redFilter;
-            workingSurface.DrawingSurface.Canvas.DrawSurface(red.DrawingSurface, 0, 0, _screenPaint);
+            
+            int savedRed = surface.Canvas.SaveLayer(_screenPaint);
+            red.Paint(context, surface);
+            
+            surface.Canvas.RestoreToCount(savedRed);
         }
         }
 
 
         if (Green.Value is { } green)
         if (Green.Value is { } green)
         {
         {
             _screenPaint.ColorFilter = _greenFilter;
             _screenPaint.ColorFilter = _greenFilter;
-            workingSurface.DrawingSurface.Canvas.DrawSurface(green.DrawingSurface, 0, 0, _screenPaint);
+            int savedGreen = surface.Canvas.SaveLayer(_screenPaint);
+            green.Paint(context, surface);
+            
+            surface.Canvas.RestoreToCount(savedGreen);
         }
         }
 
 
         if (Blue.Value is { } blue)
         if (Blue.Value is { } blue)
         {
         {
             _screenPaint.ColorFilter = _blueFilter;
             _screenPaint.ColorFilter = _blueFilter;
-            workingSurface.DrawingSurface.Canvas.DrawSurface(blue.DrawingSurface, 0, 0, _screenPaint);
+            int savedBlue = surface.Canvas.SaveLayer(_screenPaint);
+            blue.Paint(context, surface);
+            
+            surface.Canvas.RestoreToCount(savedBlue);
         }
         }
 
 
         if (Alpha.Value is { } alpha)
         if (Alpha.Value is { } alpha)
         {
         {
             _clearPaint.ColorFilter = Grayscale.Value ? Filters.AlphaGrayscaleFilter : null;
             _clearPaint.ColorFilter = Grayscale.Value ? Filters.AlphaGrayscaleFilter : null;
-
-            workingSurface.DrawingSurface.Canvas.DrawSurface(alpha.DrawingSurface, 0, 0, _clearPaint);
+            int savedAlpha = surface.Canvas.SaveLayer(_clearPaint);
+            alpha.Paint(context, surface);
+            
+            surface.Canvas.RestoreToCount(savedAlpha);
         }
         }
-
-        Image.Value = workingSurface;
+            
+        surface.Canvas.RestoreToCount(saved);
     }
     }
 
 
-    private VecI GetSize()
+    public override RectD? GetPreviewBounds(int frame, string elementToRenderName = "")
     {
     {
-        var final = new RectI();
+        RectD? redBounds = PreviewUtils.FindPreviewBounds(Red.Connection, frame, elementToRenderName);
+        RectD? greenBounds = PreviewUtils.FindPreviewBounds(Green.Connection, frame, elementToRenderName);
+        RectD? blueBounds = PreviewUtils.FindPreviewBounds(Blue.Connection, frame, elementToRenderName);
+        RectD? alphaBounds = PreviewUtils.FindPreviewBounds(Alpha.Connection, frame, elementToRenderName);
 
 
-        if (Red.Value is { } red)
+        RectD? finalBounds = null;
+        
+        if (redBounds == null && greenBounds == null && blueBounds == null && alphaBounds == null)
         {
         {
-            final = final.Union(new RectI(VecI.Zero, red.Size));
+            return null;
         }
         }
 
 
-        if (Green.Value is { } green)
+        if (redBounds.HasValue)
         {
         {
-            final = final.Union(new RectI(VecI.Zero, green.Size));
+            finalBounds = redBounds.Value;
         }
         }
-
-        if (Blue.Value is { } blue)
+        
+        if (greenBounds.HasValue)
         {
         {
-            final = final.Union(new RectI(VecI.Zero, blue.Size));
+            finalBounds = finalBounds?.Union(greenBounds.Value) ?? greenBounds.Value;
         }
         }
+        
+        if (blueBounds.HasValue)
+        {
+            finalBounds = finalBounds?.Union(blueBounds.Value) ?? blueBounds.Value;
+        }
+        
+        if (alphaBounds.HasValue)
+        {
+            finalBounds = finalBounds?.Union(alphaBounds.Value) ?? alphaBounds.Value;
+        }
+        
+        return finalBounds;
+    }
 
 
-        if (Alpha.Value is { } alpha)
+    public override bool RenderPreview(DrawingSurface renderOn, ChunkResolution resolution, int frame, string elementToRenderName)
+    {
+        if (Red.Value == null && Green.Value == null && Blue.Value == null && Alpha.Value == null)
         {
         {
-            final = final.Union(new RectI(VecI.Zero, alpha.Size));
+            return false;
         }
         }
 
 
-        return final.Size;
+        using RenderContext context = new(renderOn, frame, resolution, VecI.One);
+        
+        OnPaint(context, renderOn); 
+        
+        return true;
     }
     }
 
 
     public override Node CreateCopy() => new CombineChannelsNode();
     public override Node CreateCopy() => new CombineChannelsNode();

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

@@ -94,6 +94,11 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
 
 
     public override RectD? GetPreviewBounds(int frame, string elementFor = "")
     public override RectD? GetPreviewBounds(int frame, string elementFor = "")
     {
     {
+        if(IsDisposed)
+        {
+            return null;
+        }
+        
         if (elementFor == nameof(EmbeddedMask))
         if (elementFor == nameof(EmbeddedMask))
         {
         {
             return base.GetPreviewBounds(frame, elementFor);
             return base.GetPreviewBounds(frame, elementFor);
@@ -109,12 +114,24 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
             }
             }
         }
         }
 
 
-        return (RectD?)GetLayerImageAtFrame(frame).FindTightCommittedBounds();
+        try
+        {
+            return (RectD?)GetLayerImageAtFrame(frame).FindTightCommittedBounds();
+        }
+        catch (ObjectDisposedException)
+        {
+            return null;
+        }
     }
     }
 
 
     public override bool RenderPreview(DrawingSurface renderOnto, ChunkResolution resolution, int frame,
     public override bool RenderPreview(DrawingSurface renderOnto, ChunkResolution resolution, int frame,
         string elementToRenderName)
         string elementToRenderName)
     {
     {
+        if (IsDisposed)
+        {
+            return false;
+        }
+        
         if (elementToRenderName == nameof(EmbeddedMask))
         if (elementToRenderName == nameof(EmbeddedMask))
         {
         {
             return base.RenderPreview(renderOnto, resolution, frame, elementToRenderName);
             return base.RenderPreview(renderOnto, resolution, frame, elementToRenderName);

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

@@ -40,6 +40,7 @@ public abstract class Node : IReadOnlyNode, IDisposable
 
 
     protected virtual bool ExecuteOnlyOnCacheChange => false;
     protected virtual bool ExecuteOnlyOnCacheChange => false;
 
 
+    protected bool IsDisposed => _isDisposed;
     private bool _isDisposed;
     private bool _isDisposed;
 
 
     private Dictionary<int, Texture> _managedTextures = new();
     private Dictionary<int, Texture> _managedTextures = new();