123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- using PixiEditor.ChangeableDocument.Changeables.Animations;
- using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
- using PixiEditor.ChangeableDocument.Changeables.Interfaces;
- using PixiEditor.ChangeableDocument.ChangeInfos.Properties;
- using PixiEditor.ChangeableDocument.Helpers;
- using PixiEditor.ChangeableDocument.Rendering;
- using Drawie.Backend.Core;
- using Drawie.Backend.Core.ColorsImpl;
- 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 BlendMode = PixiEditor.ChangeableDocument.Enums.BlendMode;
- namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
- public abstract class StructureNode : RenderNode, IReadOnlyStructureNode, IRenderInput
- {
- public const string DefaultMemberName = "DEFAULT_MEMBER_NAME";
- public const string IsVisiblePropertyName = "IsVisible";
- public const string OpacityPropertyName = "Opacity";
- public const string BlendModePropertyName = "BlendMode";
- public const string ClipToPreviousMemberPropertyName = "ClipToPreviousMember";
- public const string MaskIsVisiblePropertyName = "MaskIsVisible";
- public const string MaskPropertyName = "Mask";
- public const string FiltersPropertyName = "Filters";
- public const string FilterlessOutputPropertyName = "FilterlessOutput";
- public const string RawOutputPropertyName = "RawOutput";
- public InputProperty<float> Opacity { get; }
- public InputProperty<bool> IsVisible { get; }
- public bool ClipToPreviousMember { get; set; }
- public InputProperty<BlendMode> BlendMode { get; }
- public RenderInputProperty CustomMask { get; }
- public InputProperty<bool> MaskIsVisible { get; }
- public InputProperty<Filter> Filters { get; }
- public RenderInputProperty Background { get; }
- public RenderOutputProperty FilterlessOutput { get; }
- public RenderOutputProperty RawOutput { get; }
- public OutputProperty<VecD> TightSize { get; }
- public OutputProperty<VecD> CanvasPosition { get; }
- public OutputProperty<VecD> CenterPosition { get; }
- public ChunkyImage? EmbeddedMask { get; set; }
- protected Texture renderedMask;
- protected static readonly Paint replacePaint = new Paint() { BlendMode = Drawie.Backend.Core.Surfaces.BlendMode.Src };
- protected static readonly Paint clearPaint = new Paint()
- {
- BlendMode = Drawie.Backend.Core.Surfaces.BlendMode.Src, Color = Colors.Transparent
- };
-
- protected static readonly Paint clipPaint = new Paint()
- {
- BlendMode = Drawie.Backend.Core.Surfaces.BlendMode.DstIn
- };
- public virtual ShapeCorners GetTransformationCorners(KeyFrameTime frameTime)
- {
- return new ShapeCorners(GetTightBounds(frameTime).GetValueOrDefault());
- }
- public string MemberName
- {
- get => DisplayName;
- set => DisplayName = value;
- }
- protected Paint maskPaint = new Paint() { BlendMode = Drawie.Backend.Core.Surfaces.BlendMode.DstIn, ColorFilter = Nodes.Filters.MaskFilter };
- protected Paint blendPaint = new Paint() { BlendMode = Drawie.Backend.Core.Surfaces.BlendMode.SrcOver };
- protected Paint maskPreviewPaint = new Paint()
- {
- BlendMode = Drawie.Backend.Core.Surfaces.BlendMode.SrcOver,
- ColorFilter = ColorFilter.CreateCompose(Nodes.Filters.AlphaGrayscaleFilter, Nodes.Filters.MaskFilter)
- };
- private int maskCacheHash = 0;
- protected StructureNode()
- {
- Painter filterlessPainter = new Painter(OnFilterlessPaint);
- Painter rawPainter = new Painter(OnRawPaint);
- Background = CreateRenderInput("Background", "BACKGROUND");
- Opacity = CreateInput<float>(OpacityPropertyName, "OPACITY", 1);
- IsVisible = CreateInput<bool>(IsVisiblePropertyName, "IS_VISIBLE", true);
- BlendMode = CreateInput(BlendModePropertyName, "BLEND_MODE", Enums.BlendMode.Normal);
- CustomMask = CreateRenderInput(MaskPropertyName, "MASK");
- MaskIsVisible = CreateInput<bool>(MaskIsVisiblePropertyName, "MASK_IS_VISIBLE", true);
- Filters = CreateInput<Filter>(FiltersPropertyName, "FILTERS", null);
- FilterlessOutput = CreateRenderOutput(FilterlessOutputPropertyName, "WITHOUT_FILTERS",
- () => filterlessPainter, () => Background.Value);
- RawOutput = CreateRenderOutput(RawOutputPropertyName, "RAW_LAYER_OUTPUT", () => rawPainter);
- CanvasPosition = CreateOutput<VecD>("CanvasPosition", "CANVAS_POSITION", VecD.Zero);
- CenterPosition = CreateOutput<VecD>("CenterPosition", "CENTER_POSITION", VecD.Zero);
- TightSize = CreateOutput<VecD>("Size", "SIZE", VecD.Zero);
- MemberName = DefaultMemberName;
- }
- protected override void OnExecute(RenderContext context)
- {
- base.OnExecute(context);
- if (TightSize.Connections.Count > 0)
- {
- TightSize.Value = GetTightBounds(context.FrameTime)?.Size ?? VecD.Zero;
- }
- if (CanvasPosition.Connections.Count > 0)
- {
- CanvasPosition.Value = GetTightBounds(context.FrameTime)?.TopLeft ?? VecD.Zero;
- }
- if (CenterPosition.Connections.Count > 0)
- {
- CenterPosition.Value = GetTightBounds(context.FrameTime)?.Center ?? VecD.Zero;
- }
- }
- protected override void OnPaint(RenderContext context, DrawingSurface renderTarget)
- {
- if (Output.Connections.Count > 0)
- {
- RenderForOutput(context, renderTarget, Output);
- }
- }
- private void OnFilterlessPaint(RenderContext context, DrawingSurface renderTarget)
- {
- RenderForOutput(context, renderTarget, FilterlessOutput);
- }
-
- private void OnRawPaint(RenderContext context, DrawingSurface renderTarget)
- {
- RenderForOutput(context, renderTarget, RawOutput);
- }
-
- public abstract VecD GetScenePosition(KeyFrameTime frameTime);
- public abstract VecD GetSceneSize(KeyFrameTime frameTime);
- public void RenderForOutput(RenderContext context, DrawingSurface renderTarget, RenderOutputProperty output)
- {
- if(IsDisposed)
- {
- return;
- }
-
- var renderObjectContext = CreateSceneContext(context, renderTarget, output);
- int renderSaved = renderTarget.Canvas.Save();
- VecD scenePos = GetScenePosition(context.FrameTime);
- VecD sceneSize = GetSceneSize(context.FrameTime);
- //renderTarget.Canvas.ClipRect(new RectD(scenePos - (sceneSize / 2f), sceneSize));
- Render(renderObjectContext);
- renderTarget?.Canvas.RestoreToCount(renderSaved);
- }
- protected SceneObjectRenderContext CreateSceneContext(RenderContext context, DrawingSurface renderTarget,
- RenderOutputProperty output)
- {
- var sceneSize = GetSceneSize(context.FrameTime);
- RectD localBounds = new RectD(0, 0, sceneSize.X, sceneSize.Y);
- SceneObjectRenderContext renderObjectContext = new SceneObjectRenderContext(output, renderTarget, localBounds,
- context.FrameTime, context.ChunkResolution, context.DocumentSize, renderTarget == context.RenderSurface,
- context.ProcessingColorSpace,
- context.Opacity);
- renderObjectContext.FullRerender = context.FullRerender;
- return renderObjectContext;
- }
- public abstract void Render(SceneObjectRenderContext sceneContext);
- protected void ApplyMaskIfPresent(DrawingSurface surface, RenderContext context)
- {
- if (MaskIsVisible.Value)
- {
- if (CustomMask.Value != null)
- {
- int layer = surface.Canvas.SaveLayer(maskPaint);
- surface.Canvas.Scale((float)context.ChunkResolution.Multiplier());
- CustomMask.Value.Paint(context, surface);
-
- surface.Canvas.RestoreToCount(layer);
- }
- else if (EmbeddedMask != null)
- {
- if (context.FullRerender)
- {
- EmbeddedMask.DrawMostUpToDateRegionOn(
- new RectI(0, 0, EmbeddedMask.LatestSize.X, EmbeddedMask.LatestSize.Y),
- ChunkResolution.Full,
- surface, VecI.Zero, maskPaint);
- }
- else if(renderedMask != null)
- {
- surface.Canvas.DrawSurface(renderedMask.DrawingSurface, 0, 0, maskPaint);
- }
- }
- }
- }
- protected override bool CacheChanged(RenderContext context)
- {
- int cacheHash = EmbeddedMask?.GetCacheHash() ?? 0;
- return base.CacheChanged(context) || maskCacheHash != cacheHash;
- }
- protected override void UpdateCache(RenderContext context)
- {
- base.UpdateCache(context);
- maskCacheHash = EmbeddedMask?.GetCacheHash() ?? 0;
- }
- public virtual void RenderChunk(VecI chunkPos, ChunkResolution resolution, KeyFrameTime frameTime, ColorSpace processingColorSpace)
- {
- RenderChunkyImageChunk(chunkPos, resolution, EmbeddedMask, 55, processingColorSpace, ref renderedMask);
- }
- protected void RenderChunkyImageChunk(VecI chunkPos, ChunkResolution resolution, ChunkyImage img,
- int textureId, ColorSpace processingColorSpace,
- ref Texture? renderSurface)
- {
- if (img is null)
- {
- return;
- }
- VecI targetSize = img.LatestSize;
-
- renderSurface = RequestTexture(textureId, targetSize, processingColorSpace, false);
- int saved = renderSurface.DrawingSurface.Canvas.Save();
-
- 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.Canvas.RestoreToCount(saved);
- }
- protected void ApplyRasterClip(DrawingSurface toClip, DrawingSurface clipSource)
- {
- if (ClipToPreviousMember && Background.Value != null)
- {
- toClip.Canvas.DrawSurface(clipSource, 0, 0, clipPaint);
- }
- }
- protected bool IsEmptyMask()
- {
- return EmbeddedMask != null && MaskIsVisible.Value && !EmbeddedMask.LatestOrCommittedChunkExists();
- }
- protected bool HasOperations()
- {
- return (MaskIsVisible.Value && (EmbeddedMask != null || CustomMask.Value != null)) || ClipToPreviousMember;
- }
- protected void DrawClipSource(DrawingSurface drawOnto, IClipSource clipSource, SceneObjectRenderContext context)
- {
- blendPaint.Color = Colors.White;
- clipSource.DrawClipSource(context, drawOnto);
- }
- public abstract RectD? GetTightBounds(KeyFrameTime frameTime);
- public override void SerializeAdditionalData(Dictionary<string, object> additionalData)
- {
- base.SerializeAdditionalData(additionalData);
- if (EmbeddedMask != null)
- {
- additionalData["embeddedMask"] = EmbeddedMask;
- }
- if (ClipToPreviousMember)
- {
- additionalData["clipToPreviousMember"] = ClipToPreviousMember;
- }
- }
- internal override OneOf<None, IChangeInfo, List<IChangeInfo>> DeserializeAdditionalData(IReadOnlyDocument target,
- IReadOnlyDictionary<string, object> data)
- {
- base.DeserializeAdditionalData(target, data);
- bool hasMask = data.ContainsKey("embeddedMask");
- if (hasMask)
- {
- ChunkyImage? mask = (ChunkyImage?)data["embeddedMask"];
- EmbeddedMask?.Dispose();
- EmbeddedMask = mask;
- return new List<IChangeInfo> { new StructureMemberMask_ChangeInfo(Id, mask != null) };
- }
-
- if (data.ContainsKey("clipToPreviousMember"))
- {
- ClipToPreviousMember = (bool)data["clipToPreviousMember"];
- return new List<IChangeInfo> { new StructureMemberClipToMemberBelow_ChangeInfo(Id, ClipToPreviousMember) };
- }
- return new None();
- }
- public override RectD? GetPreviewBounds(int frame, string elementFor = "")
- {
- if (elementFor == nameof(EmbeddedMask) && EmbeddedMask != null)
- {
- return new RectD(VecD.Zero, EmbeddedMask.LatestSize);
- }
- return null;
- }
- public override bool RenderPreview(DrawingSurface renderOn, RenderContext context,
- string elementToRenderName)
- {
- if (elementToRenderName != nameof(EmbeddedMask))
- {
- return false;
- }
- var img = EmbeddedMask;
- if (img is null)
- {
- return false;
- }
- renderOn.Canvas.DrawSurface(renderedMask.DrawingSurface, VecI.Zero, maskPreviewPaint);
- return true;
- }
- public override void Dispose()
- {
- Output.Value = null;
- base.Dispose();
- maskPaint.Dispose();
- blendPaint.Dispose();
- }
- }
|