Browse Source

Fixed empty chunk rendering and group timeline preview

flabbet 10 months ago
parent
commit
4815456a08

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

@@ -34,7 +34,10 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IRenderInput
     public ChunkyImage? EmbeddedMask { get; set; }
 
     protected Texture renderedMask;
-    protected static readonly Paint replacePaint = new Paint() { BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src };
+    protected static readonly Paint replacePaint = new Paint() 
+        { BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src };
+    protected static readonly Paint clearPaint = new Paint() 
+        { BlendMode = DrawingApi.Core.Surfaces.BlendMode.Src, Color = Colors.Transparent };
 
     public virtual ShapeCorners GetTransformationCorners(KeyFrameTime frameTime)
     {
@@ -160,12 +163,16 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IRenderInput
             renderSurface = new Texture(targetSize);
         }
 
-        img.DrawMostUpToDateChunkOn(
-            chunkPos,
-            ChunkResolution.Full,
-            renderSurface.DrawingSurface,
-            chunkPos * ChunkResolution.Full.PixelSize(),
-            replacePaint);
+        if (!img.DrawMostUpToDateChunkOn(
+                chunkPos,
+                ChunkResolution.Full,
+                renderSurface.DrawingSurface,
+                chunkPos * ChunkResolution.Full.PixelSize(),
+                replacePaint))
+        {
+            var chunkSize = ChunkResolution.Full.PixelSize();
+            renderSurface.DrawingSurface.Canvas.DrawRect(new RectD(chunkPos * chunkSize, new VecD(chunkSize)), clearPaint);
+        }
 
         renderSurface.DrawingSurface.Flush();
     }
@@ -194,61 +201,6 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IRenderInput
         clipSource.DrawOnTexture(context, drawOnto);
     }
 
-    protected void DrawSurface(DrawingSurface workingSurface, DrawingSurface source, RenderContext context,
-        Filter? filter)
-    {
-        // Maybe clip rect will allow to avoid snapshotting? Idk if it will be faster
-        /*
-        RectI sourceRect = CalculateSourceRect(workingSurface.Size, source.Size, context);
-        RectI targetRect = CalculateDestinationRect(context);
-        using var snapshot = source.DrawingSurface.Snapshot(sourceRect);
-        */
-
-        blendPaint.SetFilters(filter);
-
-        workingSurface.Canvas.DrawSurface(source, source.DeviceClipBounds.X, source.DeviceClipBounds.Y, blendPaint);
-    }
-
-    protected RectI CalculateSourceRect(VecI targetSize, VecI sourceSize, RenderContext context)
-    {
-        /*float divider = 1;
-
-        if (sourceSize.X < targetSize.X || sourceSize.Y < targetSize.Y)
-        {
-            divider = Math.Min((float)targetSize.X / sourceSize.X, (float)targetSize.Y / sourceSize.Y);
-        }
-
-        int chunkSize = (int)Math.Round(context.ChunkResolution.PixelSize() / divider);
-        VecI chunkPos = context.ChunkToUpdate.Value;
-
-        int x = (int)(chunkPos.X * chunkSize);
-        int y = (int)(chunkPos.Y * chunkSize);
-        int width = (int)(chunkSize);
-        int height = (int)(chunkSize);
-
-        x = Math.Clamp(x, 0, Math.Max(sourceSize.X - width, 0));
-        y = Math.Clamp(y, 0, Math.Max(sourceSize.Y - height, 0));
-
-        return new RectI(x, y, width, height);*/
-
-        return new RectI(0, 0, sourceSize.X, sourceSize.Y);
-    }
-
-    protected RectI CalculateDestinationRect(RenderContext context)
-    {
-        /*int chunkSize = context.ChunkResolution.PixelSize();
-        VecI chunkPos = context.ChunkToUpdate.Value;
-
-        int x = chunkPos.X * chunkSize;
-        int y = chunkPos.Y * chunkSize;
-        int width = chunkSize;
-        int height = chunkSize;
-
-        return new RectI(x, y, width, height);*/
-
-        return new RectI(0, 0, context.DocumentSize.X, context.DocumentSize.Y);
-    }
-
     public abstract RectD? GetTightBounds(KeyFrameTime frameTime);
 
     public override void SerializeAdditionalData(Dictionary<string, object> additionalData)
@@ -278,14 +230,6 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IRenderInput
         return new None();
     }
 
-    public override void Dispose()
-    {
-        Output.Value = null;
-        base.Dispose();
-        maskPaint.Dispose();
-        blendPaint.Dispose();
-    }
-
     public virtual RectD? GetPreviewBounds(int frame, string elementFor = "")
     {
         if (elementFor == nameof(EmbeddedMask) && EmbeddedMask != null)
@@ -315,4 +259,12 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IRenderInput
 
         return true;
     }
+
+    public override void Dispose()
+    {
+        Output.Value = null;
+        base.Dispose();
+        maskPaint.Dispose();
+        blendPaint.Dispose();
+    }
 }

+ 16 - 96
src/PixiEditor/Models/Rendering/MemberPreviewUpdater.cs

@@ -14,6 +14,7 @@ using PixiEditor.Helpers;
 using PixiEditor.Models.DocumentModels;
 using PixiEditor.Models.Handlers;
 using PixiEditor.Numerics;
+using PixiEditor.Parser;
 
 namespace PixiEditor.Models.Rendering;
 
@@ -113,7 +114,7 @@ internal class MemberPreviewUpdater
             {
                 foreach (var childFrame in groupHandler.Children)
                 {
-                    if (!memberGuids.Contains(childFrame.LayerGuid))
+                    if (!memberGuids.Contains(childFrame.LayerGuid) || !IsInFrame(childFrame))
                         continue;
 
                     RenderFramePreview(childFrame);
@@ -122,10 +123,16 @@ internal class MemberPreviewUpdater
                 if (!memberGuids.Contains(groupHandler.LayerGuid))
                     continue;
 
-                //RenderGroupPreview(groupHandler);
+                RenderGroupPreview(groupHandler);
             }
         }
     }
+    
+    private bool IsInFrame(IKeyFrameHandler keyFrame)
+    {
+        return keyFrame.StartFrameBindable <= doc.AnimationHandler.ActiveFrameBindable &&
+               keyFrame.StartFrameBindable + keyFrame.DurationBindable >= doc.AnimationHandler.ActiveFrameBindable;
+    }
 
     private void RenderFramePreview(IKeyFrameHandler keyFrame)
     {
@@ -135,104 +142,17 @@ internal class MemberPreviewUpdater
             keyFrame.PreviewPainter.Repaint();
         }
     }
-
-    private void RenderGroupPreview(IKeyFrameHandler keyFrame, IStructureMemberHandler memberVM,
-        IReadOnlyStructureNode member, [DisallowNull] AffectedArea? affArea, VecI position, float scaling)
+    
+    private void RenderGroupPreview(IKeyFrameGroupHandler groupHandler)
     {
-        /*bool isEditingRootImage = !member.KeyFrames.Any(x => x.IsInFrame(doc.AnimationHandler.ActiveFrameBindable));
-        if (!isEditingRootImage && keyFrame.PreviewSurface is not null)
-            return;
-
-        if (keyFrame.PreviewSurface == null ||
-            keyFrame.PreviewSurface.Size != memberVM.PreviewPainter.Size)
+        var group = internals.Tracker.Document.AnimationData.KeyFrames.FirstOrDefault(x => x.Id == groupHandler.Id);
+        if (group != null)
         {
-            keyFrame.PreviewSurface?.Dispose();
-            keyFrame.PreviewSurface = new Texture(memberVM.PreviewPainter.Size);
+            groupHandler.PreviewPainter ??= new PreviewPainter(AnimationKeyFramePreviewRenderer, groupHandler.Id.ToString());
+            groupHandler.PreviewPainter.Repaint();
         }
-
-        RenderLayerMainPreview((IReadOnlyLayerNode)member, keyFrame.PreviewSurface, affArea.Value,
-            position, scaling, 0);*/
     }
-
-    /// <summary>
-    /// Re-render the <paramref name="area"/> of the main preview of the <paramref name="memberVM"/> folder
-    /// </summary>
-    private void RenderFolderMainPreview(IReadOnlyFolderNode folder, IStructureMemberHandler memberVM,
-        AffectedArea area,
-        VecI position, float scaling)
-    {
-        /*QueueRender(() =>
-        {
-            memberVM.PreviewSurface.DrawingSurface.Canvas.Save();
-            memberVM.PreviewSurface.DrawingSurface.Canvas.Scale(scaling);
-            memberVM.PreviewSurface.DrawingSurface.Canvas.Translate(-position);
-            memberVM.PreviewSurface.DrawingSurface.Canvas.ClipRect((RectD)area.GlobalArea);
-            foreach (var chunk in area.Chunks)
-            {
-                var pos = chunk * ChunkResolution.Full.PixelSize();
-                // drawing in full res here is kinda slow
-                // we could switch to a lower resolution based on (canvas size / preview size) to make it run faster
-                HashSet<Guid> layers = folder.GetLayerNodeGuids();
-
-                OneOf<Chunk, EmptyChunk> rendered;
-
-                if (layers.Count == 0)
-                {
-                    rendered = new EmptyChunk();
-                }
-                else
-                {
-                    rendered = doc.Renderer.RenderLayersChunk(chunk, ChunkResolution.Full,
-                        doc.AnimationHandler.ActiveFrameTime, layers,
-                        null);
-                }
-
-                if (rendered.IsT0)
-                {
-                    memberVM.PreviewSurface.DrawingSurface.Canvas.DrawSurface(rendered.AsT0.Surface.DrawingSurface, pos,
-                        scaling < smoothingThreshold ? SmoothReplacingPaint : ReplacingPaint);
-                    rendered.AsT0.Dispose();
-                }
-                else
-                {
-                    memberVM.PreviewSurface.DrawingSurface.Canvas.DrawRect(pos.X, pos.Y,
-                        ChunkResolution.Full.PixelSize(),
-                        ChunkResolution.Full.PixelSize(), ClearPaint);
-                }
-            }
-
-            memberVM.PreviewSurface.DrawingSurface.Canvas.Restore();
-        });*/
-    }
-
-    private void RenderAnimationFramePreview(IReadOnlyImageNode node, IKeyFrameHandler keyFrameVM, AffectedArea area)
-    {
-        /*if (keyFrameVM.PreviewPainter is null)
-        {
-            keyFrameVM.PreviewPainter =
-                new Texture(StructureHelpers.CalculatePreviewSize(internals.Tracker.Document.Size));
-        }*/
-
-        /*QueueRender(() =>
-        {
-            keyFrameVM.PreviewSurface!.DrawingSurface.Canvas.Save();
-            float scaling = (float)keyFrameVM.PreviewSurface.Size.X / internals.Tracker.Document.Size.X;
-            keyFrameVM.PreviewSurface.DrawingSurface.Canvas.Scale(scaling);
-            foreach (var chunk in area.Chunks)
-            {
-                var pos = chunk * ChunkResolution.Full.PixelSize();
-                if (!node.GetLayerImageByKeyFrameGuid(keyFrameVM.Id).DrawCommittedChunkOn(chunk, ChunkResolution.Full,
-                        keyFrameVM.PreviewSurface!.DrawingSurface, pos, ReplacingPaint))
-                {
-                    keyFrameVM.PreviewSurface!.DrawingSurface.Canvas.DrawRect(pos.X, pos.Y, ChunkyImage.FullChunkSize,
-                        ChunkyImage.FullChunkSize, ClearPaint);
-                }
-            }
-
-            keyFrameVM.PreviewSurface!.DrawingSurface.Canvas.Restore();
-        });*/
-    }
-
+    
     private void RenderMaskPreviews(Guid[] members)
     {
         foreach (var node in doc.NodeGraphHandler.AllNodes)

+ 3 - 11
src/PixiEditor/Styles/Templates/TimelineGroupHeader.axaml

@@ -24,17 +24,9 @@
                                     </ImageBrush.Transform>
                                 </ImageBrush>
                             </Border.Background>
-                            <visuals:TextureControl
-                                Texture="{Binding Item.PreviewSurface, RelativeSource={RelativeSource TemplatedParent}}"
-                                Stretch="Uniform" Width="60" Height="60">
-                                <ui:RenderOptionsBindable.BitmapInterpolationMode>
-                                    <MultiBinding Converter="{converters:WidthToBitmapScalingModeConverter}">
-                                        <Binding Path="Item.PreviewSurface.Size.X"
-                                                 RelativeSource="{RelativeSource TemplatedParent}" />
-                                        <Binding RelativeSource="{RelativeSource Mode=Self}" Path="Bounds.Width" />
-                                    </MultiBinding>
-                                </ui:RenderOptionsBindable.BitmapInterpolationMode>
-                            </visuals:TextureControl>
+                            <visuals:PreviewPainterControl
+                                PreviewPainter="{Binding Item.PreviewPainter, RelativeSource={RelativeSource TemplatedParent}}"
+                                Width="60" Height="60" RenderOptions.BitmapInterpolationMode="None"/>
                         </Border>
                         <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="{Binding Item.LayerName, RelativeSource={RelativeSource TemplatedParent}}" />
                         <ToggleButton Name="PART_CollapseButton" Margin="0 0 5 0" DockPanel.Dock="Right" Classes="ExpandCollapseToggleStyle" HorizontalAlignment="Right" VerticalAlignment="Center" />