Browse Source

Vector layer preview

flabbet 11 months ago
parent
commit
d9a98d912e

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

@@ -0,0 +1,9 @@
+using PixiEditor.DrawingApi.Core;
+using PixiEditor.Numerics;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
+
+public interface IPreviewRenderable
+{
+    public bool RenderPreview(Texture renderOn, VecI chunk, ChunkResolution resolution, int frame);
+}

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

@@ -1,5 +1,5 @@
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 
-public interface IReadOnlyLayerNode : IReadOnlyStructureNode
+public interface IReadOnlyLayerNode : IReadOnlyStructureNode, IPreviewRenderable
 {
 }

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

@@ -51,6 +51,7 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
         this.size = size;
     }
 
+
     public override RectD? GetTightBounds(KeyFrameTime frameTime)
     {
         return (RectD?)GetLayerImageAtFrame(frameTime.Frame).FindTightCommittedBounds();
@@ -189,6 +190,26 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
         workingSurface.DrawingSurface.Canvas.DrawSurface(tempSurface.DrawingSurface, VecI.Zero, paint);
     }
 
+    public override bool RenderPreview(Texture renderOn, VecI chunk, ChunkResolution resolution, int frame)
+    {
+        var img = GetLayerImageAtFrame(frame);
+        
+        if (img is null)
+        {
+            return false;
+        }
+        
+        img.DrawMostUpToDateChunkOn(
+            chunk,
+            resolution,
+            renderOn.DrawingSurface,
+            chunk * resolution.PixelSize(),
+            blendPaint);
+        
+        return true;
+    }
+
+
     private void DrawChunk(ChunkyImage frameImage, RenderingContext context, Texture tempSurface, VecI vecI,
         Paint paint)
     {

+ 2 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/LayerNode.cs

@@ -131,4 +131,6 @@ public abstract class LayerNode : StructureNode, IReadOnlyLayerNode
 
         return workingSurface;
     }
+
+    public abstract bool RenderPreview(Texture renderOn, VecI chunk, ChunkResolution resolution, int frame);
 }

+ 22 - 5
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/EllipseVectorData.cs

@@ -24,7 +24,17 @@ public class EllipseVectorData : ShapeVectorData, IReadOnlyEllipseData
         Radius = radius;
     }
 
-    public override void Rasterize(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint)
+    public override void RasterizeGeometry(DrawingSurface drawingSurface, ChunkResolution resolution, Paint? paint)
+    {
+        Rasterize(drawingSurface, resolution, paint, false);
+    }
+
+    public override void RasterizeTransformed(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint)
+    {
+        Rasterize(drawingSurface, resolution, paint, true);
+    }
+
+    private void Rasterize(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint, bool applyTransform)
     {
         var imageSize = (VecI)(Radius * 2);
         
@@ -42,12 +52,19 @@ public class EllipseVectorData : ShapeVectorData, IReadOnlyEllipseData
         
         RectI region = new(VecI.Zero, (VecI)GeometryAABB.Size);
 
-        int num = drawingSurface.Canvas.Save();
-        drawingSurface.Canvas.SetMatrix(TransformationMatrix);
+        int num = 0;
+        if (applyTransform)
+        {
+            num = drawingSurface.Canvas.Save();
+            drawingSurface.Canvas.SetMatrix(TransformationMatrix);
+        }
 
         img.DrawMostUpToDateRegionOn(region, resolution, drawingSurface, topLeft, paint);
-        
-        drawingSurface.Canvas.RestoreToCount(num);
+
+        if (applyTransform)
+        {
+            drawingSurface.Canvas.RestoreToCount(num);
+        }
     }
 
     public override bool IsValid()

+ 23 - 5
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/LineVectorData.cs

@@ -31,7 +31,17 @@ public class LineVectorData(VecD startPos, VecD pos) : ShapeVectorData, IReadOnl
     public override ShapeCorners TransformationCorners => new ShapeCorners(GeometryAABB)
         .WithMatrix(TransformationMatrix);
 
-    public override void Rasterize(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint)
+    public override void RasterizeGeometry(DrawingSurface drawingSurface, ChunkResolution resolution, Paint? paint)
+    {
+        Rasterize(drawingSurface, resolution, paint, false);
+    }
+
+    public override void RasterizeTransformed(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint)
+    {
+        Rasterize(drawingSurface, resolution, paint, true);
+    }
+
+    private void Rasterize(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint, bool applyTransform)
     {
         RectD adjustedAABB = GeometryAABB.RoundOutwards().Inflate(1);
         var imageSize = (VecI)adjustedAABB.Size;
@@ -57,12 +67,20 @@ public class LineVectorData(VecD startPos, VecD pos) : ShapeVectorData, IReadOnl
         
         RectI region = new(VecI.Zero, imageSize);
         
-        int num = drawingSurface.Canvas.Save();
-        drawingSurface.Canvas.SetMatrix(TransformationMatrix);
-        
+        int num = 0;
+
+        if (applyTransform)
+        {
+            num = drawingSurface.Canvas.Save();
+            drawingSurface.Canvas.SetMatrix(TransformationMatrix);
+        }
+
         img.DrawMostUpToDateRegionOn(region, resolution, drawingSurface, topLeft, paint);
         
-        drawingSurface.Canvas.RestoreToCount(num);
+        if (applyTransform)
+        {
+            drawingSurface.Canvas.RestoreToCount(num);
+        }
     }
 
     public override bool IsValid()

+ 24 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/PointsVectorData.cs

@@ -16,14 +16,36 @@ public class PointsVectorData : ShapeVectorData
     public override RectD GeometryAABB => new RectD(Points.Min(p => p.X), Points.Min(p => p.Y), Points.Max(p => p.X),
         Points.Max(p => p.Y));
     public override ShapeCorners TransformationCorners => new ShapeCorners(
-        GeometryAABB).WithMatrix(TransformationMatrix); 
+        GeometryAABB).WithMatrix(TransformationMatrix);
 
-    public override void Rasterize(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint)
+    public override void RasterizeGeometry(DrawingSurface drawingSurface, ChunkResolution resolution, Paint? paint)
+    {
+        Rasterize(drawingSurface, paint, false);
+    }
+
+    public override void RasterizeTransformed(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint)
+    {
+        Rasterize(drawingSurface, paint, true);
+    }
+
+    private void Rasterize(DrawingSurface drawingSurface, Paint paint, bool applyTransform)
     {
         paint.Color = FillColor;
         paint.StrokeWidth = StrokeWidth;
         
+        int num = 0;
+        if (applyTransform)
+        {
+            num = drawingSurface.Canvas.Save();
+            drawingSurface.Canvas.SetMatrix(TransformationMatrix);
+        }
+        
         drawingSurface.Canvas.DrawPoints(PointMode.Points, Points.Select(p => new Point((int)p.X, (int)p.Y)).ToArray(), paint);
+        
+        if (applyTransform)
+        {
+            drawingSurface.Canvas.RestoreToCount(num);
+        }
     }
 
     public override bool IsValid()

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

@@ -22,8 +22,18 @@ public class RectangleVectorData : ShapeVectorData, IReadOnlyRectangleData
         Center = center;
         Size = size;
     }
-    
-    public override void Rasterize(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint)
+
+    public override void RasterizeGeometry(DrawingSurface drawingSurface, ChunkResolution resolution, Paint? paint)
+    {
+        Rasterize(drawingSurface, resolution, paint, false);
+    }
+
+    public override void RasterizeTransformed(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint)
+    {
+        Rasterize(drawingSurface, resolution, paint, true);
+    }
+
+    private void Rasterize(DrawingSurface drawingSurface, ChunkResolution resolution, Paint paint, bool applyTransform)
     {
         var imageSize = (VecI)Size; 
 
@@ -39,12 +49,19 @@ public class RectangleVectorData : ShapeVectorData, IReadOnlyRectangleData
 
         RectI region = new(VecI.Zero, (VecI)GeometryAABB.Size);
 
-        int num = drawingSurface.Canvas.Save();
-        drawingSurface.Canvas.SetMatrix(TransformationMatrix);
+        int num = 0;
+        if (applyTransform)
+        {
+            num = drawingSurface.Canvas.Save();
+            drawingSurface.Canvas.SetMatrix(TransformationMatrix);
+        }
 
         img.DrawMostUpToDateRegionOn(region, resolution, drawingSurface, topLeft, paint);
-
-        drawingSurface.Canvas.RestoreToCount(num);
+        
+        if (applyTransform)
+        {
+            drawingSurface.Canvas.RestoreToCount(num);
+        }
     }
 
     public override bool IsValid()

+ 2 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/ShapeVectorData.cs

@@ -19,7 +19,8 @@ public abstract class ShapeVectorData : ICacheable, ICloneable, IReadOnlyShapeVe
     public RectD TransformedAABB => new ShapeCorners(GeometryAABB).WithMatrix(TransformationMatrix).AABBBounds;
     public abstract ShapeCorners TransformationCorners { get; } 
 
-    public abstract void Rasterize(DrawingSurface drawingSurface, ChunkResolution resolution, Paint? paint);
+    public abstract void RasterizeGeometry(DrawingSurface drawingSurface, ChunkResolution resolution, Paint? paint);
+    public abstract void RasterizeTransformed(DrawingSurface drawingSurface, ChunkResolution resolution, Paint? paint);
     public abstract bool IsValid();
     public abstract int GetCacheHash();
     public abstract int CalculateHash();

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/RasterizeShapeNode.cs

@@ -35,7 +35,7 @@ public class RasterizeShapeNode : Node
         var size = context.DocumentSize;
         var image = RequestTexture(0, size);
         
-        shape.Rasterize(image.DrawingSurface, context.ChunkResolution, null);
+        shape.RasterizeTransformed(image.DrawingSurface, context.ChunkResolution, null);
 
         Image.Value = image;
         

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/ShapeNode.cs

@@ -33,7 +33,7 @@ public abstract class ShapeNode<T> : Node where T : ShapeVectorData
     {
         Texture texture = RequestTexture(0, size);
         
-        vectorData.Rasterize(texture.DrawingSurface, ChunkResolution.Full, null);
+        vectorData.RasterizeTransformed(texture.DrawingSurface, ChunkResolution.Full, null);
         
         return texture;
     }

+ 30 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/VectorLayerNode.cs

@@ -82,6 +82,34 @@ public class VectorLayerNode : LayerNode, ITransformableObject, IReadOnlyVectorN
         Rasterize(workingSurface.DrawingSurface, ctx.ChunkResolution, paint);
     }
 
+    public override bool RenderPreview(Texture renderOn, VecI chunk, ChunkResolution resolution, int frame)
+    {
+        if (ShapeData == null)
+        {
+            return false;
+        }
+
+        using var paint = new Paint();
+
+        VecI tightBoundsSize = (VecI)ShapeData.TransformedAABB.Size;
+
+        VecI translation = new VecI(
+            (int)Math.Max(ShapeData.TransformedAABB.TopLeft.X, 0),
+            (int)Math.Max(ShapeData.TransformedAABB.TopLeft.Y, 0));
+
+        using Texture toRasterizeOn = new(tightBoundsSize + translation);
+
+        int save = toRasterizeOn.DrawingSurface.Canvas.Save();
+
+        Matrix3X3 matrix = ShapeData.TransformationMatrix;
+        Rasterize(toRasterizeOn.DrawingSurface, resolution, paint);
+
+        renderOn.DrawingSurface.Canvas.DrawSurface(toRasterizeOn.DrawingSurface, 0, 0, paint);
+
+        toRasterizeOn.DrawingSurface.Canvas.RestoreToCount(save);
+        return true;
+    }
+
     public override void SerializeAdditionalData(Dictionary<string, object> additionalData)
     {
         base.SerializeAdditionalData(additionalData);
@@ -95,7 +123,7 @@ public class VectorLayerNode : LayerNode, ITransformableObject, IReadOnlyVectorN
         ShapeData = (ShapeVectorData)data["ShapeData"];
         var affected = new AffectedArea(OperationHelper.FindChunksTouchingRectangle(
             (RectI)ShapeData.TransformedAABB, ChunkyImage.FullChunkSize));
-        
+
         return new VectorShape_ChangeInfo(Id, affected);
     }
 
@@ -122,7 +150,7 @@ public class VectorLayerNode : LayerNode, ITransformableObject, IReadOnlyVectorN
 
     public void Rasterize(DrawingSurface surface, ChunkResolution resolution, Paint paint)
     {
-        ShapeData?.Rasterize(surface, resolution, paint);
+        ShapeData?.RasterizeTransformed(surface, resolution, paint);
     }
 
     public override Node CreateCopy()

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

@@ -42,5 +42,6 @@ namespace PixiEditor.DrawingApi.Core.Bridge.Operations
         public object GetNativeCanvas(IntPtr objectPointer);
         public void DrawPaint(IntPtr objectPointer, Paint paint);
         public void DrawImage(IntPtr objectPointer, Image image, int x, int y, Paint paint);
+        public Matrix3X3 GetActiveMatrix(IntPtr objectPointer);
     }
 }

+ 2 - 0
src/PixiEditor.DrawingApi.Core/Surfaces/Canvas.cs

@@ -14,6 +14,8 @@ namespace PixiEditor.DrawingApi.Core.Surfaces
     public class Canvas : NativeObject
     {
         public override object Native => DrawingBackendApi.Current.CanvasImplementation.GetNativeCanvas(ObjectPointer);
+        public Matrix3X3 ActiveMatrix => DrawingBackendApi.Current.CanvasImplementation.GetActiveMatrix(ObjectPointer);
+
         public event SurfaceChangedEventHandler? Changed;
 
         public Canvas(IntPtr objPtr) : base(objPtr)

+ 5 - 0
src/PixiEditor.DrawingApi.Skia/Implementations/SkiaCanvasImplementation.cs

@@ -75,6 +75,11 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
             canvas.DrawImage(img, x, y, skPaint);
         }
 
+        public Matrix3X3 GetActiveMatrix(IntPtr objectPointer)
+        {
+            return ManagedInstances[objectPointer].TotalMatrix.ToMatrix3X3();
+        }
+
         public int Save(IntPtr objPtr)
         {
             return ManagedInstances[objPtr].Save();

+ 6 - 9
src/PixiEditor/Models/Rendering/MemberPreviewUpdater.cs

@@ -623,16 +623,13 @@ internal class MemberPreviewUpdater
             foreach (var chunk in area.Chunks)
             {
                 var pos = chunk * ChunkResolution.Full.PixelSize();
-                if (layer is not IReadOnlyImageNode raster) return;
-                IReadOnlyChunkyImage? result = raster.GetLayerImageAtFrame(frame);
-
-                if (!result.DrawCommittedChunkOn(
-                        chunk,
-                        ChunkResolution.Full, surface.DrawingSurface, pos,
-                        scaling < smoothingThreshold ? SmoothReplacingPaint : ReplacingPaint))
+                if (layer is IPreviewRenderable renderable)
                 {
-                    surface.DrawingSurface.Canvas.DrawRect(pos.X, pos.Y, ChunkyImage.FullChunkSize,
-                        ChunkyImage.FullChunkSize, ClearPaint);
+                    if (!renderable.RenderPreview(surface, chunk, ChunkResolution.Full, frame))
+                    {
+                        surface.DrawingSurface.Canvas.DrawRect(pos.X, pos.Y, ChunkResolution.Full.PixelSize(),
+                            ChunkResolution.Full.PixelSize(), ClearPaint);
+                    }
                 }
             }