| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- using PixiEditor.ChangeableDocument.Rendering;
- using Drawie.Backend.Core;
- using Drawie.Backend.Core.Bridge;
- using Drawie.Backend.Core.ColorsImpl;
- using Drawie.Backend.Core.ColorsImpl.Paintables;
- using Drawie.Backend.Core.Numerics;
- using Drawie.Backend.Core.Surfaces;
- using Drawie.Backend.Core.Surfaces.ImageData;
- using Drawie.Backend.Core.Surfaces.PaintImpl;
- using Drawie.Numerics;
- using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
- namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
- [NodeInfo("CreateImage")]
- public class CreateImageNode : Node
- {
- public OutputProperty<Texture> Output { get; }
- public InputProperty<VecI> Size { get; }
- public InputProperty<Paintable> Fill { get; }
- public RenderInputProperty Content { get; }
- public InputProperty<Matrix3X3> ContentMatrix { get; }
- public RenderOutputProperty RenderOutput { get; }
- private TextureCache textureCache = new();
- protected override bool ExecuteOnlyOnCacheChange => true;
- protected override CacheTriggerFlags CacheTrigger => CacheTriggerFlags.Inputs;
- public CreateImageNode()
- {
- Output = CreateOutput<Texture>(nameof(Output), "IMAGE", null);
- Size = CreateInput(nameof(Size), "SIZE", new VecI(32, 32)).WithRules(v => v.Min(VecI.One));
- Fill = CreateInput<Paintable>(nameof(Fill), "FILL", new ColorPaintable(Colors.Transparent));
- Content = CreateRenderInput(nameof(Content), "CONTENT");
- ContentMatrix = CreateInput<Matrix3X3>(nameof(ContentMatrix), "MATRIX", Matrix3X3.Identity);
- RenderOutput = CreateRenderOutput("RenderOutput", "RENDER_OUTPUT", () => new Painter(OnPaint));
- }
- protected override void OnExecute(RenderContext context)
- {
- if (Size.Value.X <= 0 || Size.Value.Y <= 0)
- {
- return;
- }
- var surface = Render(context);
- RenderPreviews(surface, context);
- Output.Value = surface;
- RenderOutput.ChainToPainterValue();
- }
- private Texture? Render(RenderContext context)
- {
- var size = (VecI)(Size.Value * context.ChunkResolution.Multiplier());
- if (size.X <= 0 || size.Y <= 0)
- {
- return null;
- }
- int id = (Size.Value * context.ChunkResolution.Multiplier()).GetHashCode();
- var surface = textureCache.RequestTexture(id, (VecI)(Size.Value * context.ChunkResolution.Multiplier()), context.ProcessingColorSpace, false);
- surface.DrawingSurface.Canvas.SetMatrix(Matrix3X3.Identity);
- if (Fill.Value is ColorPaintable colorPaintable)
- {
- surface.DrawingSurface.Canvas.Clear(colorPaintable.Color);
- }
- else
- {
- using Paint paint = new Paint();
- paint.SetPaintable(Fill.Value);
- paint.BlendMode = BlendMode.Src;
- surface.DrawingSurface.Canvas.DrawRect(0, 0, Size.Value.X, Size.Value.Y, paint);
- }
- int saved = surface.DrawingSurface.Canvas.Save();
- RenderContext ctx = context.Clone();
- ctx.RenderSurface = surface.DrawingSurface.Canvas;
- ctx.RenderOutputSize = surface.Size;
- ctx.VisibleDocumentRegion = null;
- float chunkMultiplier = (float)context.ChunkResolution.Multiplier();
- surface.DrawingSurface.Canvas.SetMatrix(
- surface.DrawingSurface.Canvas.TotalMatrix.Concat(
- Matrix3X3.CreateScale(chunkMultiplier, chunkMultiplier).Concat(ContentMatrix.Value)));
- Content.Value?.Paint(ctx, surface.DrawingSurface.Canvas);
- surface.DrawingSurface.Canvas.RestoreToCount(saved);
- return surface;
- }
- private void OnPaint(RenderContext context, Canvas surface)
- {
- if (Output.Value == null || Output.Value.IsDisposed) return;
- int saved = surface.Save();
- surface.Scale((float)context.ChunkResolution.InvertedMultiplier());
- surface.DrawSurface(Output.Value.DrawingSurface, 0, 0);
- surface.RestoreToCount(saved);
- }
- private void RenderPreviews(Texture surface, RenderContext context)
- {
- var previews = context.GetPreviewTexturesForNode(Id);
- if (previews is null) return;
- foreach (var request in previews)
- {
- var texture = request.Texture;
- if (texture is null) continue;
- int saved = texture.DrawingSurface.Canvas.Save();
- VecD scaling = PreviewUtility.CalculateUniformScaling(surface.Size, texture.Size);
- VecD offset = PreviewUtility.CalculateCenteringOffset(surface.Size, texture.Size, scaling);
- texture.DrawingSurface.Canvas.Translate((float)offset.X, (float)offset.Y);
- texture.DrawingSurface.Canvas.Scale((float)scaling.X, (float)scaling.Y);
- var previewCtx =
- PreviewUtility.CreatePreviewContext(context, scaling, context.RenderOutputSize, texture.Size);
- texture.DrawingSurface.Canvas.Clear();
- texture.DrawingSurface.Canvas.DrawSurface(surface.DrawingSurface, 0, 0);
- texture.DrawingSurface.Canvas.RestoreToCount(saved);
- }
- }
- public override Node CreateCopy() => new CreateImageNode();
- public override void Dispose()
- {
- base.Dispose();
- textureCache.Dispose();
- }
- }
|