|
@@ -1,4 +1,5 @@
|
|
|
-using PixiEditor.ChangeableDocument.Changeables.Animations;
|
|
|
+using System.Collections.Concurrent;
|
|
|
+using PixiEditor.ChangeableDocument.Changeables.Animations;
|
|
|
using PixiEditor.ChangeableDocument.Changeables.Graph;
|
|
|
using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
|
|
|
using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
|
|
@@ -18,6 +19,8 @@ public class DocumentRenderer : IPreviewRenderable
|
|
|
BlendMode = BlendMode.Src, Color = Drawie.Backend.Core.ColorsImpl.Colors.Transparent
|
|
|
};
|
|
|
|
|
|
+ private Texture renderTexture;
|
|
|
+
|
|
|
public DocumentRenderer(IReadOnlyDocument document)
|
|
|
{
|
|
|
Document = document;
|
|
@@ -72,22 +75,37 @@ public class DocumentRenderer : IPreviewRenderable
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
IsBusy = true;
|
|
|
|
|
|
RenderContext context = new(renderOn, frameTime, resolution, Document.Size, Document.ProcessingColorSpace);
|
|
|
context.FullRerender = true;
|
|
|
-
|
|
|
+
|
|
|
node.RenderForOutput(context, renderOn, null);
|
|
|
IsBusy = false;
|
|
|
}
|
|
|
+
|
|
|
+ public void RenderNodePreview(IPreviewRenderable previewRenderable, DrawingSurface renderOn, RenderContext context, string elementToRenderName)
|
|
|
+ {
|
|
|
+ if (IsBusy)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ IsBusy = true;
|
|
|
+
|
|
|
+ previewRenderable.RenderPreview(renderOn, context, elementToRenderName);
|
|
|
+
|
|
|
+ IsBusy = false;
|
|
|
+ }
|
|
|
|
|
|
public static IReadOnlyNodeGraph ConstructMembersOnlyGraph(IReadOnlyNodeGraph fullGraph)
|
|
|
{
|
|
|
return ConstructMembersOnlyGraph(null, fullGraph);
|
|
|
}
|
|
|
|
|
|
- public static IReadOnlyNodeGraph ConstructMembersOnlyGraph(HashSet<Guid>? layersToCombine,
|
|
|
+ public static IReadOnlyNodeGraph ConstructMembersOnlyGraph(
|
|
|
+ HashSet<Guid>? membersToCombine,
|
|
|
IReadOnlyNodeGraph fullGraph)
|
|
|
{
|
|
|
NodeGraph membersOnlyGraph = new();
|
|
@@ -96,26 +114,40 @@ public class DocumentRenderer : IPreviewRenderable
|
|
|
|
|
|
membersOnlyGraph.AddNode(outputNode);
|
|
|
|
|
|
- List<LayerNode> layersInOrder = new();
|
|
|
+ Dictionary<Guid, Guid> nodeMapping = new();
|
|
|
|
|
|
- fullGraph.TryTraverse(node =>
|
|
|
+ fullGraph.OutputNode.TraverseBackwards((node, input) =>
|
|
|
{
|
|
|
- if (node is LayerNode layer && (layersToCombine == null || layersToCombine.Contains(layer.Id)))
|
|
|
+ if (node is StructureNode structureNode && membersToCombine != null &&
|
|
|
+ !membersToCombine.Contains(structureNode.Id))
|
|
|
{
|
|
|
- layersInOrder.Insert(0, layer);
|
|
|
+ return true;
|
|
|
}
|
|
|
- });
|
|
|
|
|
|
- IInputProperty<Painter> lastInput = outputNode.Input;
|
|
|
+ if (node is LayerNode layer)
|
|
|
+ {
|
|
|
+ LayerNode clone = (LayerNode)layer.Clone();
|
|
|
+ membersOnlyGraph.AddNode(clone);
|
|
|
+
|
|
|
+
|
|
|
+ IInputProperty targetInput = GetTargetInput(input, fullGraph, membersOnlyGraph, nodeMapping);
|
|
|
+
|
|
|
+ clone.Output.ConnectTo(targetInput);
|
|
|
+ nodeMapping[layer.Id] = clone.Id;
|
|
|
+ }
|
|
|
+ else if (node is FolderNode folder)
|
|
|
+ {
|
|
|
+ FolderNode clone = (FolderNode)folder.Clone();
|
|
|
+ membersOnlyGraph.AddNode(clone);
|
|
|
|
|
|
- foreach (var layer in layersInOrder)
|
|
|
- {
|
|
|
- var clone = (LayerNode)layer.Clone();
|
|
|
- membersOnlyGraph.AddNode(clone);
|
|
|
+ var targetInput = GetTargetInput(input, fullGraph, membersOnlyGraph, nodeMapping);
|
|
|
+
|
|
|
+ clone.Output.ConnectTo(targetInput);
|
|
|
+ nodeMapping[folder.Id] = clone.Id;
|
|
|
+ }
|
|
|
|
|
|
- clone.Output.ConnectTo(lastInput);
|
|
|
- lastInput = clone.Background;
|
|
|
- }
|
|
|
+ return true;
|
|
|
+ });
|
|
|
|
|
|
return membersOnlyGraph;
|
|
|
}
|
|
@@ -126,16 +158,76 @@ public class DocumentRenderer : IPreviewRenderable
|
|
|
public bool RenderPreview(DrawingSurface renderOn, RenderContext context,
|
|
|
string elementToRenderName)
|
|
|
{
|
|
|
+ IsBusy = true;
|
|
|
+
|
|
|
+ if (renderTexture == null || renderTexture.Size != Document.Size)
|
|
|
+ {
|
|
|
+ renderTexture?.Dispose();
|
|
|
+ renderTexture = Texture.ForProcessing(Document.Size, Document.ProcessingColorSpace);
|
|
|
+ }
|
|
|
+
|
|
|
+ renderTexture.DrawingSurface.Canvas.Clear();
|
|
|
+ context.RenderSurface = renderTexture.DrawingSurface;
|
|
|
Document.NodeGraph.Execute(context);
|
|
|
|
|
|
+ renderOn.Canvas.DrawSurface(renderTexture.DrawingSurface, 0, 0);
|
|
|
+
|
|
|
+ IsBusy = false;
|
|
|
+
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
public void RenderDocument(DrawingSurface toRenderOn, KeyFrameTime frameTime)
|
|
|
{
|
|
|
IsBusy = true;
|
|
|
- RenderContext context = new(toRenderOn, frameTime, ChunkResolution.Full, Document.Size, Document.ProcessingColorSpace) { FullRerender = true };
|
|
|
+
|
|
|
+ if (renderTexture == null || renderTexture.Size != Document.Size)
|
|
|
+ {
|
|
|
+ renderTexture?.Dispose();
|
|
|
+ renderTexture = Texture.ForProcessing(Document.Size, Document.ProcessingColorSpace);
|
|
|
+ }
|
|
|
+
|
|
|
+ renderTexture.DrawingSurface.Canvas.Clear();
|
|
|
+ RenderContext context =
|
|
|
+ new(renderTexture.DrawingSurface, frameTime, ChunkResolution.Full, Document.Size,
|
|
|
+ Document.ProcessingColorSpace) { FullRerender = true };
|
|
|
Document.NodeGraph.Execute(context);
|
|
|
+
|
|
|
+ toRenderOn.Canvas.DrawSurface(renderTexture.DrawingSurface, 0, 0);
|
|
|
IsBusy = false;
|
|
|
}
|
|
|
+
|
|
|
+ private static IInputProperty GetTargetInput(IInputProperty? input,
|
|
|
+ IReadOnlyNodeGraph sourceGraph,
|
|
|
+ NodeGraph membersOnlyGraph,
|
|
|
+ Dictionary<Guid, Guid> nodeMapping)
|
|
|
+ {
|
|
|
+ if(input == null) return membersOnlyGraph.OutputNode.Input;
|
|
|
+
|
|
|
+ if (nodeMapping.ContainsKey(input.Node?.Id ?? Guid.Empty))
|
|
|
+ {
|
|
|
+ return membersOnlyGraph.Nodes.First(x => x.Id == nodeMapping[input.Node.Id])
|
|
|
+ .GetInputProperty(input.InternalPropertyName);
|
|
|
+ }
|
|
|
+
|
|
|
+ var sourceNode = sourceGraph.AllNodes.First(x => x.Id == input.Node.Id);
|
|
|
+
|
|
|
+ IInputProperty? found = null;
|
|
|
+ sourceNode.TraverseForwards((n, input) =>
|
|
|
+ {
|
|
|
+ if (n is StructureNode structureNode)
|
|
|
+ {
|
|
|
+ if(nodeMapping.TryGetValue(structureNode.Id, out var value))
|
|
|
+ {
|
|
|
+ Node mappedNode = membersOnlyGraph.Nodes.First(x => x.Id == value);
|
|
|
+ found = mappedNode.GetInputProperty(input.InternalPropertyName);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+
|
|
|
+ return found ?? membersOnlyGraph.OutputNode.Input;
|
|
|
+ }
|
|
|
}
|