|
@@ -1,20 +1,23 @@
|
|
-using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
|
|
|
|
|
|
+using PixiEditor.ChangeableDocument.Changeables.Graph;
|
|
|
|
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
|
|
|
|
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
|
|
using PixiEditor.ChangeableDocument.Changeables.Interfaces;
|
|
using PixiEditor.ChangeableDocument.Changeables.Interfaces;
|
|
using PixiEditor.DrawingApi.Core.Surface.ImageData;
|
|
using PixiEditor.DrawingApi.Core.Surface.ImageData;
|
|
using PixiEditor.Numerics;
|
|
using PixiEditor.Numerics;
|
|
|
|
|
|
namespace PixiEditor.ChangeableDocument.Rendering;
|
|
namespace PixiEditor.ChangeableDocument.Rendering;
|
|
|
|
|
|
-public class DocumentEvaluator
|
|
|
|
|
|
+public class DocumentRenderer
|
|
{
|
|
{
|
|
- public DocumentEvaluator(IReadOnlyDocument document)
|
|
|
|
|
|
+ public DocumentRenderer(IReadOnlyDocument document)
|
|
{
|
|
{
|
|
Document = document;
|
|
Document = document;
|
|
}
|
|
}
|
|
|
|
|
|
private IReadOnlyDocument Document { get; }
|
|
private IReadOnlyDocument Document { get; }
|
|
-
|
|
|
|
- public OneOf<Chunk, EmptyChunk> RenderChunk(VecI chunkPos, ChunkResolution resolution, int frame, RectI? globalClippingRect = null)
|
|
|
|
|
|
+
|
|
|
|
+ public OneOf<Chunk, EmptyChunk> RenderChunk(VecI chunkPos, ChunkResolution resolution, int frame,
|
|
|
|
+ RectI? globalClippingRect = null)
|
|
{
|
|
{
|
|
using RenderingContext context = new(frame, chunkPos, resolution, Document.Size);
|
|
using RenderingContext context = new(frame, chunkPos, resolution, Document.Size);
|
|
try
|
|
try
|
|
@@ -36,17 +39,17 @@ public class DocumentEvaluator
|
|
{
|
|
{
|
|
chunk.Surface.DrawingSurface.Canvas.ClipRect((RectD)transformedClippingRect);
|
|
chunk.Surface.DrawingSurface.Canvas.ClipRect((RectD)transformedClippingRect);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
VecD pos = chunkPos;
|
|
VecD pos = chunkPos;
|
|
int x = (int)(pos.X * ChunkyImage.FullChunkSize * resolution.Multiplier());
|
|
int x = (int)(pos.X * ChunkyImage.FullChunkSize * resolution.Multiplier());
|
|
int y = (int)(pos.Y * ChunkyImage.FullChunkSize * resolution.Multiplier());
|
|
int y = (int)(pos.Y * ChunkyImage.FullChunkSize * resolution.Multiplier());
|
|
int width = (int)(ChunkyImage.FullChunkSize * resolution.Multiplier());
|
|
int width = (int)(ChunkyImage.FullChunkSize * resolution.Multiplier());
|
|
int height = (int)(ChunkyImage.FullChunkSize * resolution.Multiplier());
|
|
int height = (int)(ChunkyImage.FullChunkSize * resolution.Multiplier());
|
|
-
|
|
|
|
|
|
+
|
|
RectD sourceRect = new(x, y, width, height);
|
|
RectD sourceRect = new(x, y, width, height);
|
|
|
|
|
|
using var chunkSnapshot = evaluated.DrawingSurface.Snapshot((RectI)sourceRect);
|
|
using var chunkSnapshot = evaluated.DrawingSurface.Snapshot((RectI)sourceRect);
|
|
-
|
|
|
|
|
|
+
|
|
chunk.Surface.DrawingSurface.Canvas.DrawImage(chunkSnapshot, 0, 0, context.ReplacingPaintWithOpacity);
|
|
chunk.Surface.DrawingSurface.Canvas.DrawImage(chunkSnapshot, 0, 0, context.ReplacingPaintWithOpacity);
|
|
|
|
|
|
chunk.Surface.DrawingSurface.Canvas.Restore();
|
|
chunk.Surface.DrawingSurface.Canvas.Restore();
|
|
@@ -73,26 +76,7 @@ public class DocumentEvaluator
|
|
return new EmptyChunk();
|
|
return new EmptyChunk();
|
|
}
|
|
}
|
|
|
|
|
|
- Chunk chunk = Chunk.Create(resolution);
|
|
|
|
-
|
|
|
|
- chunk.Surface.DrawingSurface.Canvas.Save();
|
|
|
|
- chunk.Surface.DrawingSurface.Canvas.Clear();
|
|
|
|
-
|
|
|
|
- int x = 0;
|
|
|
|
- int y = 0;
|
|
|
|
-
|
|
|
|
- if (transformedClippingRect is not null)
|
|
|
|
- {
|
|
|
|
- chunk.Surface.DrawingSurface.Canvas.ClipRect((RectD)transformedClippingRect);
|
|
|
|
- x = transformedClippingRect.Value.X;
|
|
|
|
- y = transformedClippingRect.Value.Y;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- chunk.Surface.DrawingSurface.Canvas.DrawSurface(evaluated.DrawingSurface, x, y, context.ReplacingPaintWithOpacity);
|
|
|
|
-
|
|
|
|
- chunk.Surface.DrawingSurface.Canvas.Restore();
|
|
|
|
-
|
|
|
|
- return chunk;
|
|
|
|
|
|
+ return ChunkFromResult(resolution, transformedClippingRect, evaluated, context);
|
|
}
|
|
}
|
|
catch (ObjectDisposedException)
|
|
catch (ObjectDisposedException)
|
|
{
|
|
{
|
|
@@ -109,4 +93,87 @@ public class DocumentEvaluator
|
|
VecI pixelChunkPos = chunkPos * (int)(ChunkyImage.FullChunkSize * multiplier);
|
|
VecI pixelChunkPos = chunkPos * (int)(ChunkyImage.FullChunkSize * multiplier);
|
|
return (RectI?)rect.Scale(multiplier).Translate(-pixelChunkPos).RoundOutwards();
|
|
return (RectI?)rect.Scale(multiplier).Translate(-pixelChunkPos).RoundOutwards();
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ public OneOf<Chunk, EmptyChunk> RenderLayersChunk(VecI chunkPos, ChunkResolution resolution, int frame,
|
|
|
|
+ HashSet<Guid> layersToCombine)
|
|
|
|
+ {
|
|
|
|
+ using RenderingContext context = new(frame, chunkPos, resolution, Document.Size);
|
|
|
|
+ NodeGraph membersOnlyGraph = ConstructMembersOnlyGraph(layersToCombine, Document.NodeGraph);
|
|
|
|
+ try
|
|
|
|
+ {
|
|
|
|
+ Surface? evaluated = membersOnlyGraph.Execute(context);
|
|
|
|
+ if (evaluated is null)
|
|
|
|
+ {
|
|
|
|
+ return new EmptyChunk();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var result = ChunkFromResult(resolution, null, evaluated, context);
|
|
|
|
+
|
|
|
|
+ membersOnlyGraph.Dispose();
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+ catch (ObjectDisposedException)
|
|
|
|
+ {
|
|
|
|
+ return new EmptyChunk();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private NodeGraph ConstructMembersOnlyGraph(HashSet<Guid> layersToCombine, IReadOnlyNodeGraph fullGraph)
|
|
|
|
+ {
|
|
|
|
+ NodeGraph membersOnlyGraph = new();
|
|
|
|
+
|
|
|
|
+ OutputNode outputNode = new();
|
|
|
|
+
|
|
|
|
+ membersOnlyGraph.AddNode(outputNode);
|
|
|
|
+
|
|
|
|
+ List<LayerNode> layersInOrder = new();
|
|
|
|
+
|
|
|
|
+ fullGraph.TryTraverse(node =>
|
|
|
|
+ {
|
|
|
|
+ if (node is LayerNode layer && layersToCombine.Contains(layer.Id))
|
|
|
|
+ {
|
|
|
|
+ layersInOrder.Insert(0, layer);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ IInputProperty<Surface> lastInput = outputNode.Input;
|
|
|
|
+
|
|
|
|
+ foreach (var layer in layersInOrder)
|
|
|
|
+ {
|
|
|
|
+ var clone = (LayerNode)layer.Clone();
|
|
|
|
+ membersOnlyGraph.AddNode(clone);
|
|
|
|
+
|
|
|
|
+ clone.Output.ConnectTo(lastInput);
|
|
|
|
+ lastInput = clone.Background;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return membersOnlyGraph;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static OneOf<Chunk, EmptyChunk> ChunkFromResult(ChunkResolution resolution,
|
|
|
|
+ RectI? transformedClippingRect, Surface evaluated,
|
|
|
|
+ RenderingContext context)
|
|
|
|
+ {
|
|
|
|
+ Chunk chunk = Chunk.Create(resolution);
|
|
|
|
+
|
|
|
|
+ chunk.Surface.DrawingSurface.Canvas.Save();
|
|
|
|
+ chunk.Surface.DrawingSurface.Canvas.Clear();
|
|
|
|
+
|
|
|
|
+ int x = 0;
|
|
|
|
+ int y = 0;
|
|
|
|
+
|
|
|
|
+ if (transformedClippingRect is not null)
|
|
|
|
+ {
|
|
|
|
+ chunk.Surface.DrawingSurface.Canvas.ClipRect((RectD)transformedClippingRect);
|
|
|
|
+ x = transformedClippingRect.Value.X;
|
|
|
|
+ y = transformedClippingRect.Value.Y;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ chunk.Surface.DrawingSurface.Canvas.DrawSurface(evaluated.DrawingSurface, x, y,
|
|
|
|
+ context.ReplacingPaintWithOpacity);
|
|
|
|
+
|
|
|
|
+ chunk.Surface.DrawingSurface.Canvas.Restore();
|
|
|
|
+
|
|
|
|
+ return chunk;
|
|
|
|
+ }
|
|
}
|
|
}
|