Quellcode durchsuchen

Merge branch 'funcy-nodes' into node-backend

flabbet vor 1 Jahr
Ursprung
Commit
971c4128a1

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

@@ -19,6 +19,13 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
     private Paint blendPaint = new Paint();
     private Paint maskPaint = new Paint() { BlendMode = DrawingApi.Core.Surface.BlendMode.DstIn };
 
+    // Handled by overriden CacheChanged
+    protected override bool AffectedByAnimation => false;
+
+    protected override bool AffectedByChunkResolution => true;
+
+    protected override bool AffectedByChunkToUpdate => true;
+
     public ImageLayerNode(VecI size)
     {
         LockTransparency = CreateInput<bool>("LockTransparency", "LOCK_TRANSPARENCY", false);

+ 9 - 3
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Node.cs

@@ -23,7 +23,13 @@ public abstract class Node : IReadOnlyNode, IDisposable
     public Image? CachedResult { get; private set; }
 
     public virtual string InternalName { get; }
+    
+    protected virtual bool AffectedByAnimation { get; }
+    
+    protected virtual bool AffectedByChunkResolution { get; }
 
+    protected virtual bool AffectedByChunkToUpdate { get; }
+    
     protected Node()
     {
         InternalName = $"PixiEditor.{GetType().Name}";
@@ -51,9 +57,9 @@ public abstract class Node : IReadOnlyNode, IDisposable
     
     protected virtual bool CacheChanged(RenderingContext context)
     {
-        return !context.FrameTime.Equals(_lastFrameTime)
-               || context.Resolution != _lastResolution
-               || context.ChunkToUpdate != _lastChunkPos
+        return (!context.FrameTime.Equals(_lastFrameTime) && AffectedByAnimation)
+               || (context.Resolution != _lastResolution && AffectedByChunkResolution)
+               || (context.ChunkToUpdate != _lastChunkPos && AffectedByChunkToUpdate)
                || inputs.Any(x => x.CacheChanged);
     }
     

+ 55 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/NoiseNode.cs

@@ -0,0 +1,55 @@
+using PixiEditor.ChangeableDocument.Changeables.Animations;
+using PixiEditor.ChangeableDocument.Rendering;
+using PixiEditor.DrawingApi.Core.ColorsImpl;
+using PixiEditor.DrawingApi.Core.Surface.ImageData;
+using PixiEditor.DrawingApi.Core.Surface.PaintImpl;
+using PixiEditor.Numerics;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+
+public class NoiseNode : Node
+{
+    private double previousScale = double.NaN;
+    private Paint paint = new();
+    
+    public OutputProperty<Image> Noise { get; }
+
+    public InputProperty<VecI> Size { get; }
+    
+    public InputProperty<double> Scale { get; }
+    
+    public InputProperty<double> Seed { get; }
+
+    public NoiseNode()
+    {
+        Noise = CreateOutput<Image>(nameof(Noise), "NOISE", null);
+        Size = CreateInput(nameof(Size), "SIZE", new VecI());
+        Scale = CreateInput(nameof(Scale), "SCALE", 0d);
+        Seed = CreateInput(nameof(Seed), "SEED", 0d);
+    }
+    
+    protected override Image OnExecute(RenderingContext context)
+    {
+        if (Math.Abs(previousScale - Scale.Value) > 0.000001 || double.IsNaN(previousScale))
+        {
+            var shader = Shader.CreatePerlinNoiseTurbulence((float)(1d / Scale.Value), (float)(1d / Scale.Value), 4, (float)Seed.Value);
+            paint.Shader = shader;
+
+            previousScale = Scale.Value;
+        }
+        
+        var size = Size.Value;
+        
+        using var workingSurface = new Surface(size);
+        
+        workingSurface.DrawingSurface.Canvas.DrawPaint(paint);
+
+        Noise.Value = workingSurface.DrawingSurface.Snapshot();
+        
+        return Noise.Value;
+    }
+
+    public override bool Validate() => Size.Value is { X: > 0, Y: > 0 };
+
+    public override Node CreateCopy() => new NoiseNode();
+}

+ 1 - 0
src/PixiEditor.DrawingApi.Core/Bridge/NativeObjectsImpl/IShaderImplementation.cs

@@ -11,5 +11,6 @@ public interface IShaderImplementation
     public void Dispose(IntPtr shaderObjPointer);
     public Shader? CreateFromSksl(string sksl, bool isOpaque, out string errors);
     public Shader CreateLinearGradient(VecI p1, VecI p2, Color[] colors);
+    public Shader CreatePerlinNoiseTurbulence(float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed);
     public object GetNativeShader(IntPtr objectPointer);
 }

+ 5 - 0
src/PixiEditor.DrawingApi.Core/Surface/PaintImpl/Shader.cs

@@ -27,4 +27,9 @@ public class Shader : NativeObject
     {
         return DrawingBackendApi.Current.ShaderImplementation.CreateLinearGradient(p1, p2, colors);
     }
+
+    public static Shader CreatePerlinNoiseTurbulence(float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed)
+    {
+        return DrawingBackendApi.Current.ShaderImplementation.CreatePerlinNoiseTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed);
+    }
 }

+ 12 - 0
src/PixiEditor.DrawingApi.Skia/Implementations/SkiaShaderImplementation.cs

@@ -46,6 +46,18 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
             return new Shader(shader.Handle);
         }
 
+        public Shader CreatePerlinNoiseTurbulence(float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed)
+        {
+            SKShader shader = SKShader.CreatePerlinNoiseTurbulence(
+                baseFrequencyX,
+                baseFrequencyY,
+                numOctaves,
+                seed);
+
+            ManagedInstances[shader.Handle] = shader;
+            return new Shader(shader.Handle);
+        }
+
         public object GetNativeShader(IntPtr objectPointer)
         {
             return ManagedInstances[objectPointer];