Преглед изворни кода

Fixed merge structure members and clip to member below

flabbet пре 1 година
родитељ
комит
5ecac2b785

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

@@ -81,15 +81,15 @@ public class FolderNode : StructureNode, IReadOnlyFolderNode
             DrawSurface(outputWorkingSurface, Content.Value, context, Filters.Value);
             
             ApplyMaskIfPresent(outputWorkingSurface, context);
-            ApplyRasterClip(outputWorkingSurface, context);
-            
         }
         
         if (Background.Value != null)
         {
-            Texture tempSurface = new Texture(outputWorkingSurface.Size);
+            Texture tempSurface = RequestTexture(2, outputWorkingSurface.Size);
             DrawBackground(tempSurface, context);
             
+            ApplyRasterClip(outputWorkingSurface, tempSurface);
+            
             blendPaint.Color = blendPaint.Color.WithAlpha((byte)Math.Round(Opacity.Value * 255));
             blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
             tempSurface.DrawingSurface.Canvas.DrawSurface(outputWorkingSurface.DrawingSurface, 0, 0, blendPaint);

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

@@ -119,15 +119,14 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
 
         // shit gets downhill with mask on big canvases, TODO: optimize
         ApplyMaskIfPresent(outputWorkingSurface, context);
-        ApplyRasterClip(outputWorkingSurface, context);
 
         if (Background.Value != null)
         {
             Texture tempSurface = RequestTexture(4, outputWorkingSurface.Size, true);
             DrawBackground(tempSurface, context);
+            ApplyRasterClip(outputWorkingSurface, tempSurface);
             blendPaint.BlendMode = RenderingContext.GetDrawingBlendMode(BlendMode.Value);
             tempSurface.DrawingSurface.Canvas.DrawSurface(outputWorkingSurface.DrawingSurface, 0, 0, blendPaint);
-
             Output.Value = tempSurface;
             return tempSurface;
         }
@@ -171,33 +170,34 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
         bool requiresTopLeft = context.ChunkToUpdate.X > 0 || context.ChunkToUpdate.Y > 0;
         bool requiresTop = context.ChunkToUpdate.Y > 0;
         bool requiresLeft = context.ChunkToUpdate.X > 0;
-        bool requiresTopRight = context.ChunkToUpdate.X < imageChunksSize.X - 1 && context.ChunkToUpdate.Y > 0; 
+        bool requiresTopRight = context.ChunkToUpdate.X < imageChunksSize.X - 1 && context.ChunkToUpdate.Y > 0;
         bool requiresRight = context.ChunkToUpdate.X < imageChunksSize.X - 1;
-        bool requiresBottomRight = context.ChunkToUpdate.X < imageChunksSize.X - 1 && context.ChunkToUpdate.Y < imageChunksSize.Y - 1; 
+        bool requiresBottomRight = context.ChunkToUpdate.X < imageChunksSize.X - 1 &&
+                                   context.ChunkToUpdate.Y < imageChunksSize.Y - 1;
         bool requiresBottom = context.ChunkToUpdate.Y < imageChunksSize.Y - 1;
         bool requiresBottomLeft = context.ChunkToUpdate.X > 0 && context.ChunkToUpdate.Y < imageChunksSize.Y - 1;
 
         VecI tempSizeInChunks = new VecI(1, 1);
-        if(requiresLeft)
+        if (requiresLeft)
         {
             tempSizeInChunks.X++;
         }
-        
-        if(requiresRight)
+
+        if (requiresRight)
         {
             tempSizeInChunks.X++;
         }
-        
-        if(requiresTop)
+
+        if (requiresTop)
         {
             tempSizeInChunks.Y++;
         }
-        
-        if(requiresBottom)
+
+        if (requiresBottom)
         {
             tempSizeInChunks.Y++;
         }
-        
+
         VecI tempSize = tempSizeInChunks * context.ChunkResolution.PixelSize();
         tempSize = new VecI(Math.Min(tempSize.X, workingSurface.Size.X), Math.Min(tempSize.Y, workingSurface.Size.Y));
 
@@ -206,54 +206,54 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
             workingSurface.DrawingSurface.Canvas.DrawRect(
                 new RectI(
                     VecI.Zero,
-                    tempSize), 
+                    tempSize),
                 clearPaint);
         }
-        
+
         using Texture tempSurface = new Texture(tempSize);
 
         if (requiresTopLeft)
         {
             DrawChunk(frameImage, context, tempSurface, new VecI(-1, -1));
         }
-        
+
         if (requiresTop)
         {
             DrawChunk(frameImage, context, tempSurface, new VecI(0, -1));
         }
-        
+
         if (requiresLeft)
         {
             DrawChunk(frameImage, context, tempSurface, new VecI(-1, 0));
         }
-        
+
         if (requiresTopRight)
         {
             DrawChunk(frameImage, context, tempSurface, new VecI(1, -1));
         }
-        
+
         if (requiresRight)
         {
             DrawChunk(frameImage, context, tempSurface, new VecI(1, 0));
         }
-        
+
         if (requiresBottomRight)
         {
             DrawChunk(frameImage, context, tempSurface, new VecI(1, 1));
         }
-        
+
         if (requiresBottom)
         {
             DrawChunk(frameImage, context, tempSurface, new VecI(0, 1));
         }
-        
+
         if (requiresBottomLeft)
         {
             DrawChunk(frameImage, context, tempSurface, new VecI(-1, 1));
         }
-        
+
         DrawChunk(frameImage, context, tempSurface, new VecI(0, 0));
-        
+
         blendPaint.SetFilters(Filters.Value);
         workingSurface.DrawingSurface.Canvas.DrawSurface(tempSurface.DrawingSurface, VecI.Zero, blendPaint);
     }

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

@@ -79,17 +79,11 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
         }
     }
 
-    protected void ApplyRasterClip(Texture surface, RenderingContext context)
+    protected void ApplyRasterClip(Texture toClip, Texture clipSource)
     {
         if (ClipToPreviousMember.Value && Background.Value != null)
         {
-            RectI? clippingRect = null;
-            VecI chunkStart = context.ChunkToUpdate * context.ChunkResolution.PixelSize();
-            VecI targetSize = new VecI(context.ChunkResolution.PixelSize());
-            clippingRect = new RectI(chunkStart, targetSize);
-
-            //TODO: Fix
-            //OperationHelper.ClampAlpha(surface.DrawingSurface, Background.Value, clippingRect);
+             toClip.DrawingSurface.Canvas.DrawSurface(clipSource.DrawingSurface, 0, 0, maskPaint);
         }
     }
 

+ 26 - 14
src/PixiEditor.ChangeableDocument/Changes/Drawing/CombineStructureMembersOnto_Change.cs

@@ -1,5 +1,6 @@
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.Rendering;
+using PixiEditor.DrawingApi.Core.Bridge;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Numerics;
 
@@ -31,7 +32,7 @@ internal class CombineStructureMembersOnto_Change : Change
         {
             if (!target.TryFindMember(guid, out var member))
                 return false;
-            
+
             if (member is LayerNode layer)
                 layersToCombine.Add(layer.Id);
             else if (member is FolderNode innerFolder)
@@ -58,7 +59,8 @@ internal class CombineStructureMembersOnto_Change : Change
         }
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply,
+        out bool ignoreInUndo)
     {
         //TODO: Add support for different Layer types
         var toDrawOn = target.FindMemberOrThrow<ImageLayerNode>(targetLayer);
@@ -73,21 +75,29 @@ internal class CombineStructureMembersOnto_Change : Change
 
         var toDrawOnImage = toDrawOn.GetLayerImageAtFrame(frame);
         toDrawOnImage.EnqueueClear();
-        
+
         DocumentRenderer renderer = new(target);
-        
-        foreach (var chunk in chunksToCombine)
+
+        AffectedArea affArea = new();
+        DrawingBackendApi.Current.RenderDispatch(() =>
         {
-            OneOf<Chunk, EmptyChunk> combined = renderer.RenderLayersChunk(chunk, ChunkResolution.Full, frame, layersToCombine);
-            if (combined.IsT0)
+            RectI? globalClippingRect = new RectI(0, 0, target.Size.X, target.Size.Y);
+            foreach (var chunk in chunksToCombine)
             {
-                toDrawOnImage.EnqueueDrawImage(chunk * ChunkyImage.FullChunkSize, combined.AsT0.Surface);
-                combined.AsT0.Dispose();
+                OneOf<Chunk, EmptyChunk> combined =
+                    renderer.RenderLayersChunk(chunk, ChunkResolution.Full, frame, layersToCombine, globalClippingRect);
+                if (combined.IsT0)
+                {
+                    toDrawOnImage.EnqueueDrawImage(chunk * ChunkyImage.FullChunkSize, combined.AsT0.Surface);
+                    combined.AsT0.Dispose();
+                }
             }
-        }
-        var affArea = toDrawOnImage.FindAffectedArea();
-        originalChunks = new CommittedChunkStorage(toDrawOnImage, affArea.Chunks);
-        toDrawOnImage.CommitChanges();
+
+            affArea = toDrawOnImage.FindAffectedArea();
+            originalChunks = new CommittedChunkStorage(toDrawOnImage, affArea.Chunks);
+            toDrawOnImage.CommitChanges();
+        });
+
 
         ignoreInUndo = false;
         return new LayerImageArea_ChangeInfo(targetLayer, affArea);
@@ -96,7 +106,9 @@ internal class CombineStructureMembersOnto_Change : Change
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
     {
         var toDrawOn = target.FindMemberOrThrow<ImageLayerNode>(targetLayer);
-        var affectedArea = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(toDrawOn.GetLayerImageAtFrame(frame), ref originalChunks);
+        var affectedArea =
+            DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(toDrawOn.GetLayerImageAtFrame(frame),
+                ref originalChunks);
         return new LayerImageArea_ChangeInfo(targetLayer, affectedArea);
     }
 

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Drawing/FloodFill/FloodFillChunkCache.cs

@@ -49,7 +49,7 @@ internal class FloodFillChunkCache : IDisposable
         {
             if (document is null || membersToRender is null)
                 throw new InvalidOperationException();
-            var chunk = document.Renderer.RenderLayersChunk(pos, ChunkResolution.Full, frame, membersToRender);
+            var chunk = document.Renderer.RenderLayersChunk(pos, ChunkResolution.Full, frame, membersToRender, null);
             acquiredChunks[pos] = chunk;
             return chunk;
         }

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

@@ -47,7 +47,8 @@ internal class CreateStructureMember_Change : Change
         List<IChangeInfo> changes = new() { CreateChangeInfo(member) };
         
         InputProperty<Texture> targetInput = parentNode.InputProperties.FirstOrDefault(x => 
-            x.ValueType == typeof(Texture) && 
+            x.ValueType == typeof(Texture) &&
+            x.Connection != null &&
             x.Connection.Node is StructureNode) as InputProperty<Texture>;
         
         

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

@@ -4,6 +4,7 @@ using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using PixiEditor.DrawingApi.Core;
+using PixiEditor.DrawingApi.Core.Surfaces.ImageData;
 using PixiEditor.Numerics;
 
 namespace PixiEditor.ChangeableDocument.Rendering;
@@ -93,7 +94,10 @@ public class DocumentRenderer
                 return new EmptyChunk();
             }
 
-            return ChunkFromResult(resolution, transformedClippingRect, evaluated, context);
+            var result = ChunkFromResult(resolution, transformedClippingRect, evaluated.DrawingSurface.Snapshot(), context);
+            evaluated.Dispose();
+            
+            return result;
         }
         catch (ObjectDisposedException)
         {
@@ -112,19 +116,20 @@ public class DocumentRenderer
     }
 
     public OneOf<Chunk, EmptyChunk> RenderLayersChunk(VecI chunkPos, ChunkResolution resolution, int frame,
-        HashSet<Guid> layersToCombine)
+        HashSet<Guid> layersToCombine, RectI? globalClippingRect)
     {
         using RenderingContext context = new(frame, chunkPos, resolution, Document.Size);
         NodeGraph membersOnlyGraph = ConstructMembersOnlyGraph(layersToCombine, Document.NodeGraph);
         try
         {
+            RectI? transformedClippingRect = TransformClipRect(globalClippingRect, resolution, chunkPos);
             Texture? evaluated = membersOnlyGraph.Execute(context);
             if (evaluated is null)
             {
                 return new EmptyChunk();
             }
 
-            var result = ChunkFromResult(resolution, null, evaluated, context);
+            var result = ChunkFromResult(resolution, transformedClippingRect, evaluated.DrawingSurface.Snapshot(), context);
             
             membersOnlyGraph.Dispose();
             return result;
@@ -167,8 +172,9 @@ public class DocumentRenderer
         return membersOnlyGraph;
     }
 
-    private static OneOf<Chunk, EmptyChunk> ChunkFromResult(ChunkResolution resolution,
-        RectI? transformedClippingRect, Texture evaluated,
+    private static OneOf<Chunk, EmptyChunk> ChunkFromResult(
+        ChunkResolution resolution,
+        RectI? transformedClippingRect, Image evaluated,
         RenderingContext context)
     {
         Chunk chunk = Chunk.Create(resolution);
@@ -186,7 +192,7 @@ public class DocumentRenderer
             y = transformedClippingRect.Value.Y;
         }
 
-        chunk.Surface.DrawingSurface.Canvas.DrawSurface(evaluated.DrawingSurface, x, y,
+        chunk.Surface.DrawingSurface.Canvas.DrawImage(evaluated, x, y,
             context.ReplacingPaintWithOpacity);
 
         chunk.Surface.DrawingSurface.Canvas.Restore();

+ 2 - 1
src/PixiEditor.DrawingApi.Core/Bridge/DrawingBackendApi.cs

@@ -20,7 +20,7 @@ namespace PixiEditor.DrawingApi.Core.Bridge
         
         public static bool HasBackend => _current != null;
         
-        public static void SetupBackend(IDrawingBackend backend)
+        public static void SetupBackend(IDrawingBackend backend, Action<Action> dispatcher)
         {
             if (_current != null)
             {
@@ -28,6 +28,7 @@ namespace PixiEditor.DrawingApi.Core.Bridge
             }
             
             _current = backend;
+            _current.RenderDispatch = dispatcher;
             backend.Setup();
         }
     }

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

@@ -22,5 +22,6 @@ namespace PixiEditor.DrawingApi.Core.Bridge
         public IImageFilterImplementation ImageFilterImplementation { get; }
         public IShaderImplementation ShaderImplementation { get; set; }
         public bool IsHardwareAccelerated { get; }
+        public Action<Action> RenderDispatch { get; set; }
     }
 }

+ 4 - 2
src/PixiEditor.DrawingApi.Skia/SkiaDrawingBackend.cs

@@ -1,4 +1,5 @@
-using PixiEditor.DrawingApi.Core.Bridge;
+using System;
+using PixiEditor.DrawingApi.Core.Bridge;
 using PixiEditor.DrawingApi.Core.Bridge.NativeObjectsImpl;
 using PixiEditor.DrawingApi.Core.Bridge.Operations;
 using PixiEditor.DrawingApi.Skia.Exceptions;
@@ -24,7 +25,8 @@ namespace PixiEditor.DrawingApi.Skia
         }
         
         public bool IsHardwareAccelerated => GraphicsContext != null;
-        
+        public Action<Action> RenderDispatch { get; set; }
+
         public IColorImplementation ColorImplementation { get; }
         public IImageImplementation ImageImplementation { get; }
         public IImgDataImplementation ImgDataImplementation { get; }

+ 1 - 1
src/PixiEditor/Views/MainWindow.axaml.cs

@@ -71,7 +71,7 @@ internal partial class MainWindow : Window
 
         SkiaDrawingBackend skiaDrawingBackend = new SkiaDrawingBackend();
         skiaDrawingBackend.GraphicsContext = GetOpenGlGrContext();
-        DrawingBackendApi.SetupBackend(skiaDrawingBackend);
+        DrawingBackendApi.SetupBackend(skiaDrawingBackend, (a) => Dispatcher.UIThread.Invoke(a));
 
         preferences = services.GetRequiredService<IPreferences>();
         platform = services.GetRequiredService<IPlatform>();