Browse Source

Added filterless output to structure node

CPKreuz 1 year ago
parent
commit
53a7a78085

+ 28 - 10
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/FolderNode.cs

@@ -39,48 +39,66 @@ public class FolderNode : StructureNode, IReadOnlyFolderNode
 
         VecI size = Content.Value?.Size ?? Background.Value?.Size ?? VecI.Zero;
         
-        var workingSurface = TryInitWorkingSurface(size, context);
+        var outputWorkingSurface = TryInitWorkingSurface(size, context, 0);
+        var filterlessWorkingSurface = TryInitWorkingSurface(size, context, 1);
+        
+        if (Background.Value != null)
+        {
+            DrawBackground(filterlessWorkingSurface, context);
+            blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
+        }
+
+        if (Content.Value != null)
+        {
+            blendPaint.Color = blendPaint.Color.WithAlpha((byte)Math.Round(Opacity.Value * 255)); 
+            DrawSurface(filterlessWorkingSurface, Content.Value, context, null);
+        }
+
+        FilterlessOutput.Value = filterlessWorkingSurface;
 
         if (!HasOperations())
         {
             if (Background.Value != null)
             {
-                DrawBackground(workingSurface, context);
+                blendPaint.Color = new Color(255, 255, 255, 255);
+                blendPaint.BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src;
+                DrawBackground(outputWorkingSurface, context);
                 blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
             }
             
             if (Content.Value != null)
             {
                 blendPaint.Color = blendPaint.Color.WithAlpha((byte)Math.Round(Opacity.Value * 255)); 
-                DrawSurface(workingSurface, Content.Value, context, Filters.Value);
+                DrawSurface(outputWorkingSurface, Content.Value, context, Filters.Value);
             }
             
-            Output.Value = workingSurface;
+            Output.Value = outputWorkingSurface;
             return Output.Value;
         }
         
         if (Content.Value != null)
         {
-            DrawSurface(workingSurface, Content.Value, context, Filters.Value);
+            DrawSurface(outputWorkingSurface, Content.Value, context, Filters.Value);
+            
+            ApplyMaskIfPresent(outputWorkingSurface, context);
+            ApplyRasterClip(outputWorkingSurface, context);
             
-            ApplyMaskIfPresent(workingSurface, context);
-            ApplyRasterClip(workingSurface, context);
         }
         
         if (Background.Value != null)
         {
-            Surface tempSurface = new Surface(workingSurface.Size);
+            Surface tempSurface = new Surface(outputWorkingSurface.Size);
             DrawBackground(tempSurface, context);
             
             blendPaint.Color = blendPaint.Color.WithAlpha((byte)Math.Round(Opacity.Value * 255));
             blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
-            tempSurface.DrawingSurface.Canvas.DrawSurface(workingSurface.DrawingSurface, 0, 0, blendPaint);
+            tempSurface.DrawingSurface.Canvas.DrawSurface(outputWorkingSurface.DrawingSurface, 0, 0, blendPaint);
 
             Output.Value = tempSurface;
             return tempSurface;
         }
 
-        Output.Value = workingSurface;
+        Output.Value = outputWorkingSurface;
         return Output.Value;
     }
 

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

@@ -73,49 +73,64 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
 
     private Surface RenderImage(ChunkyImage frameImage, RenderingContext context)
     {
-        var workingSurface = TryInitWorkingSurface(frameImage.LatestSize, context);
+        var outputWorkingSurface = TryInitWorkingSurface(frameImage.LatestSize, context, 0);
+        var filterlessWorkingSurface = TryInitWorkingSurface(frameImage.LatestSize, context, 1);
 
+        bool canClear = Background.Value == null;
+        if (Background.Value != null)
+        {
+            DrawBackground(filterlessWorkingSurface, context);
+            blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
+        }
+
+        DrawLayer(frameImage, context, filterlessWorkingSurface, canClear, useFilters: false);
+        blendPaint.BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src;
+        
+        FilterlessOutput.Value = filterlessWorkingSurface;
+        
         if (!HasOperations())
         {
-            bool canClear = Background.Value == null;
             if (Background.Value != null)
             {
-                DrawBackground(workingSurface, context);
+                DrawBackground(outputWorkingSurface, context);
                 blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
             }
 
-            DrawLayer(frameImage, context, workingSurface, canClear);
-            Output.Value = workingSurface;
-            return workingSurface;
+            DrawLayer(frameImage, context, outputWorkingSurface, canClear);
+            
+            Output.Value = outputWorkingSurface;
+            
+            return outputWorkingSurface;
         }
 
-        DrawLayer(frameImage, context, workingSurface, true);
+        DrawLayer(frameImage, context, outputWorkingSurface, true);
 
         // shit gets downhill with mask on big canvases, TODO: optimize
-        ApplyMaskIfPresent(workingSurface, context);
-        ApplyRasterClip(workingSurface, context);
-
+        ApplyMaskIfPresent(outputWorkingSurface, context);
+        ApplyRasterClip(outputWorkingSurface, context);
+        
         if (Background.Value != null)
         {
-            Surface tempSurface = new Surface(workingSurface.Size);
+            Surface tempSurface = new Surface(outputWorkingSurface.Size);
             DrawBackground(tempSurface, context);
             blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
-            tempSurface.DrawingSurface.Canvas.DrawSurface(workingSurface.DrawingSurface, 0, 0, blendPaint);
+            tempSurface.DrawingSurface.Canvas.DrawSurface(outputWorkingSurface.DrawingSurface, 0, 0, blendPaint);
 
             Output.Value = tempSurface;
             return tempSurface;
         }
 
-        Output.Value = workingSurface;
-        return workingSurface;
+        Output.Value = outputWorkingSurface;
+        
+        return outputWorkingSurface;
     }
 
-    private void DrawLayer(ChunkyImage frameImage, RenderingContext context, Surface workingSurface, bool shouldClear)
+    private void DrawLayer(ChunkyImage frameImage, RenderingContext context, Surface workingSurface, bool shouldClear, bool useFilters = true)
     {
-        blendPaint.Color = blendPaint.Color.WithAlpha((byte)Math.Round(Opacity.Value * 255)); 
-        
-        blendPaint.SetFilters(Filters.Value);
-        
+        blendPaint.Color = blendPaint.Color.WithAlpha((byte)Math.Round(Opacity.Value * 255));
+
+        blendPaint.SetFilters(useFilters ? Filters.Value : null);
+
         if (!frameImage.DrawMostUpToDateChunkOn(
                 context.ChunkToUpdate,
                 context.ChunkResolution,
@@ -124,6 +139,7 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
                 blendPaint) && shouldClear)
         {
             workingSurface.DrawingSurface.Canvas.DrawRect(CalculateDestinationRect(context), clearPaint);
+            workingSurface.DrawingSurface.Canvas.Flush();
         }
     }
 

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

@@ -23,6 +23,8 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
 
     public OutputProperty<Surface?> Output { get; }
 
+    public OutputProperty<Surface?> FilterlessOutput { get; }
+
     public string MemberName { get; set; } = "New Element"; // would be good to add localization here, it is set if node is created via node graph
     
     public override string DisplayName
@@ -31,7 +33,7 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
         set => MemberName = value;
     }
 
-    protected Dictionary<ChunkResolution, Surface> workingSurfaces = new Dictionary<ChunkResolution, Surface>();
+    protected Dictionary<(ChunkResolution, int), Surface> workingSurfaces = new Dictionary<(ChunkResolution, int), Surface>();
     private Paint maskPaint = new Paint() { BlendMode = DrawingApi.Core.Surfaces.BlendMode.DstIn };
     protected Paint blendPaint = new Paint();
 
@@ -47,20 +49,21 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
         Filters = CreateInput<Filter>(nameof(Filters), "FILTERS", null);
 
         Output = CreateOutput<Surface?>("Output", "OUTPUT", null);
+        FilterlessOutput = CreateOutput<Surface?>(nameof(FilterlessOutput), "WITHOUT_FILTERS", null);
     }
 
     protected abstract override Surface? OnExecute(RenderingContext context);
 
-    protected Surface TryInitWorkingSurface(VecI imageSize, RenderingContext context)
+    protected Surface TryInitWorkingSurface(VecI imageSize, RenderingContext context, int id)
     {
         ChunkResolution targetResolution = context.ChunkResolution;
-        bool hasSurface = workingSurfaces.TryGetValue(targetResolution, out Surface workingSurface);
+        bool hasSurface = workingSurfaces.TryGetValue((targetResolution, id), out Surface workingSurface);
         VecI targetSize = (VecI)(imageSize * targetResolution.Multiplier());
 
         if (!hasSurface || workingSurface.Size != targetSize || workingSurface.IsDisposed)
         {
-            workingSurfaces[targetResolution] = new Surface(targetSize);
-            workingSurface = workingSurfaces[targetResolution];
+            workingSurfaces[(targetResolution, id)] = new Surface(targetSize);
+            workingSurface = workingSurfaces[(targetResolution, id)];
         }
 
         return workingSurface;