Browse Source

Implemented embedded masks

flabbet 10 months ago
parent
commit
a4f6b8a507

+ 9 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/IChunkRenderable.cs

@@ -0,0 +1,9 @@
+using PixiEditor.ChangeableDocument.Changeables.Animations;
+using PixiEditor.Numerics;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
+
+public interface IChunkRenderable
+{
+    public void RenderChunk(VecI chunkPos, ChunkResolution resolution, KeyFrameTime frameTime);
+}

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

@@ -14,5 +14,4 @@ public interface IReadOnlyImageNode : IReadOnlyLayerNode, ITransparencyLockable
     public IReadOnlyChunkyImage GetLayerImageByKeyFrameGuid(Guid keyFrameGuid);
     void SetLayerImageAtFrame(int frame, IReadOnlyChunkyImage image);
     public void ForEveryFrame(Action<IReadOnlyChunkyImage> action);
-    public void RenderChunk(VecI chunkPos, ChunkResolution resolution, KeyFrameTime frameTime);
 }

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

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

+ 7 - 37
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ImageLayerNode.cs

@@ -25,7 +25,6 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
 
     private VecI startSize;
     private ChunkyImage layerImage => keyFrames[0]?.Data as ChunkyImage;
-    protected Paint replacePaint = new Paint() { BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src };
 
     private static readonly Paint clearPaint = new()
     {
@@ -52,21 +51,9 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
 
         this.startSize = size;
 
-        CreateRenderCanvases(size);
+        CreateRenderCanvases(size, renderedSurfaces);
     }
-
-    private void CreateRenderCanvases(VecI newSize)
-    {
-        renderedSurfaces[ChunkResolution.Full] = new Texture(newSize);
-        renderedSurfaces[ChunkResolution.Half] =
-            new Texture(new VecI(Math.Max(newSize.X / 2, 1), Math.Max(newSize.Y / 2, 1)));
-        renderedSurfaces[ChunkResolution.Quarter] =
-            new Texture(new VecI(Math.Max(newSize.X / 4, 1), Math.Max(newSize.Y / 4, 1)));
-        renderedSurfaces[ChunkResolution.Eighth] =
-            new Texture(new VecI(Math.Max(newSize.X / 8, 1), Math.Max(newSize.Y / 8, 1)));
-    }
-
-
+    
     public override RectD? GetTightBounds(KeyFrameTime frameTime)
     {
         return (RectD?)GetLayerImageAtFrame(frameTime.Frame).FindTightCommittedBounds();
@@ -306,32 +293,15 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
 
     void IReadOnlyImageNode.ForEveryFrame(Action<IReadOnlyChunkyImage> action) => ForEveryFrame(action);
 
-    public void RenderChunk(VecI chunkPos, ChunkResolution resolution, KeyFrameTime frameTime)
+    public override void RenderChunk(VecI chunkPos, ChunkResolution resolution, KeyFrameTime frameTime)
     {
+        base.RenderChunk(chunkPos, resolution, frameTime);
+        
         var img = GetLayerImageAtFrame(frameTime.Frame);
 
-        if (img is null)
-        {
-            return;
-        }
-
-        VecD targetSize = img.LatestSize * resolution.Multiplier();
-        if ((renderedSurfaces[resolution].Size * resolution.InvertedMultiplier()) != targetSize)
-        {
-            renderedSurfaces[resolution].Dispose();
-            renderedSurfaces[resolution] = new Texture((VecI)targetSize);
-        }
-
-        img.DrawMostUpToDateChunkOn(
-            chunkPos,
-            resolution,
-            renderedSurfaces[resolution].DrawingSurface,
-            chunkPos * resolution.PixelSize(),
-            replacePaint);
-
-        renderedSurfaces[resolution].DrawingSurface.Flush();
+        RenderChunkyImageChunk(chunkPos, resolution, img, renderedSurfaces);
     }
-
+    
     public void ForEveryFrame(Action<ChunkyImage> action)
     {
         foreach (var frame in keyFrames)

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

@@ -27,15 +27,15 @@ public class RectangleVectorData : ShapeVectorData, IReadOnlyRectangleData
 
     public override void RasterizeGeometry(DrawingSurface drawingSurface, ChunkResolution resolution, Paint? paint)
     {
-        Rasterize(drawingSurface, resolution, paint, false);
+        Rasterize(drawingSurface, paint, false);
     }
 
     public override void RasterizeTransformed(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint)
     {
-        Rasterize(drawingSurface, resolution, paint, true);
+        Rasterize(drawingSurface, paint, true);
     }
 
-    private void Rasterize(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint, bool applyTransform)
+    private void Rasterize(DrawingSurface drawingSurface, Paint paint, bool applyTransform)
     {
         int saved = 0;
         if (applyTransform)

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

@@ -33,6 +33,9 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
 
     public ChunkyImage? EmbeddedMask { get; set; }
 
+    private Dictionary<ChunkResolution, Texture> renderedMasks = new();
+    protected static readonly Paint replacePaint = new Paint() { BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src };
+
     public virtual ShapeCorners GetTransformationCorners(KeyFrameTime frameTime)
     {
         return new ShapeCorners(GetTightBounds(frameTime).GetValueOrDefault());
@@ -99,16 +102,22 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
             }
             else if (EmbeddedMask != null)
             {
-                /*EmbeddedMask.DrawMostUpToDateChunkOn(
-                    context.ChunkToUpdate.Value,
-                    context.ChunkResolution,
-                    surface,
-                    context.ChunkToUpdate.Value * context.ChunkResolution.PixelSize(),
-                    maskPaint);*/
+                surface.Canvas.DrawSurface(renderedMasks[context.ChunkResolution].DrawingSurface, 0, 0, maskPaint); 
             }
         }
     }
 
+    protected static void CreateRenderCanvases(VecI newSize, Dictionary<ChunkResolution, Texture> target)
+    {
+        target[ChunkResolution.Full] = new Texture(newSize);
+        target[ChunkResolution.Half] =
+            new Texture(new VecI(Math.Max(newSize.X / 2, 1), Math.Max(newSize.Y / 2, 1)));
+        target[ChunkResolution.Quarter] =
+            new Texture(new VecI(Math.Max(newSize.X / 4, 1), Math.Max(newSize.Y / 4, 1)));
+        target[ChunkResolution.Eighth] =
+            new Texture(new VecI(Math.Max(newSize.X / 8, 1), Math.Max(newSize.Y / 8, 1)));
+    }
+
     protected override bool CacheChanged(RenderContext context)
     {
         int cacheHash = EmbeddedMask?.GetCacheHash() ?? 0;
@@ -121,6 +130,41 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
         maskCacheHash = EmbeddedMask?.GetCacheHash() ?? 0;
     }
 
+    public virtual void RenderChunk(VecI chunkPos, ChunkResolution resolution, KeyFrameTime frameTime)
+    {
+        RenderChunkyImageChunk(chunkPos, resolution, EmbeddedMask, renderedMasks);
+    }
+
+    protected void RenderChunkyImageChunk(VecI chunkPos, ChunkResolution resolution, ChunkyImage img,
+        Dictionary<ChunkResolution, Texture> cache)
+    {
+        if (img is null)
+        {
+            return;
+        }
+
+        VecI targetSize = (VecI)(img.LatestSize * resolution.Multiplier());
+        if (!cache.ContainsKey(resolution))
+        {
+            cache[resolution] = new Texture(targetSize);
+        }
+        
+        if ((cache[resolution].Size * resolution.InvertedMultiplier()) != targetSize)
+        {
+            cache[resolution].Dispose();
+            cache[resolution] = new Texture(targetSize);
+        }
+
+        img.DrawMostUpToDateChunkOn(
+            chunkPos,
+            resolution,
+            cache[resolution].DrawingSurface,
+            chunkPos * resolution.PixelSize(),
+            replacePaint);
+
+        cache[resolution].DrawingSurface.Flush();
+    }
+
     protected void ApplyRasterClip(DrawingSurface toClip, DrawingSurface clipSource)
     {
         if (ClipToPreviousMember && Background.Value != null)

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

@@ -74,7 +74,7 @@ public class DocumentRenderer
         {
             Document.NodeGraph.TryTraverse((node =>
             {
-                if (node is IReadOnlyImageNode imageNode)
+                if (node is IChunkRenderable imageNode)
                 {
                     imageNode.RenderChunk(chunkPos, resolution, frameTime);
                 }