Browse Source

Moved variable attachments into separate NodeVariableAttachments class

CPKreuz 11 months ago
parent
commit
63d5f1f3be

+ 6 - 24
src/PixiEditor.ChangeableDocument/Changeables/Graph/Context/FuncContext.cs

@@ -110,14 +110,6 @@ public class FuncContext
         return Builder.ConstructHalf4(r, g, b, a);
     }
 
-    /// <summary>
-    /// Gets a Half4 that can be used multiple times by the same node.
-    /// The node and property are used to generate a unique hash. <br/>
-    /// <example>If you have one input and multiple outputs use this generate a single variable that can be accessed from the multiple output. In that case set the <see cref="property"/> parameter to the input property</example>
-    /// </summary>
-    public Half4 GetOrNewAttachedHalf4(Node node, INodeProperty property, Func<Expression> assignment) =>
-        Builder.GetOrNewAttachedHalf4(node.GetHashCode(), property.GetHashCode(), assignment);
-    
     public Half4 HsvaToRgba(Expression h, Expression s, Expression v, Expression a)
     {
         if (!HasContext && h is Float1 firstFloat && s is Float1 secondFloat && v is Float1 thirdFloat && a is Float1 fourthFloat)
@@ -160,12 +152,9 @@ public class FuncContext
         return Builder.AssignNewHalf4(Builder.Functions.GetHslToRgb(h, s, l, a));
     }
     
-    /// <summary>
-    /// The node and property parameter are used to generate a hash. <br/> See <see cref="GetOrNewAttachedHalf4"/> for more information
-    /// </summary>
-    public Half4 RgbaToHsva(Node node, INodeProperty property, Func<Expression> color)
+    public Half4 RgbaToHsva(Expression color)
     {
-        if (!HasContext && color() is Half4 constantColor)
+        if (!HasContext && color is Half4 constantColor)
         {
             var variable = new Half4(string.Empty);
             constantColor.ConstantValue.ToHsv(out float h, out float s, out float l);
@@ -174,17 +163,12 @@ public class FuncContext
             return variable;
         }
 
-        return Builder.GetOrNewAttachedHalf4(node.GetHashCode(), property.GetHashCode(), RgbToHsvGetter);
-
-        Expression RgbToHsvGetter() => Builder.Functions.GetRgbToHsv(color());
+        return Builder.AssignNewHalf4(Builder.Functions.GetRgbToHsv(color));
     }
     
-    /// <summary>
-    /// The node and property parameter are used to generate a hash. <br/> See <see cref="GetOrNewAttachedHalf4"/> for more information
-    /// </summary>
-    public Half4 RgbaToHsla(Node node, INodeProperty property, Func<Expression> color)
+    public Half4 RgbaToHsla(Expression color)
     {
-        if (!HasContext && color() is Half4 constantColor)
+        if (!HasContext && color is Half4 constantColor)
         {
             var variable = new Half4(string.Empty);
             constantColor.ConstantValue.ToHsl(out float h, out float s, out float l);
@@ -193,9 +177,7 @@ public class FuncContext
             return variable;
         }
 
-        return Builder.GetOrNewAttachedHalf4(node.GetHashCode(), property.GetHashCode(), RgbToHslGetter);
-
-        Expression RgbToHslGetter() => Builder.Functions.GetRgbToHsl(color());
+        return Builder.AssignNewHalf4(Builder.Functions.GetRgbToHsl(color));
     }
 
     public Half4 NewHalf4(Expression assignment)

+ 8 - 3
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/SeparateColorNode.cs

@@ -10,6 +10,8 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.CombineSeparate;
 [NodeInfo("SeparateColor", "SEPARATE_COLOR_NODE", Category = "COLOR")]
 public class SeparateColorNode : Node
 {
+    private readonly NodeVariableAttachments contextVariables = new();
+    
     public FuncInputProperty<Half4> Color { get; }
     
     public InputProperty<CombineSeparateColorMode> Mode { get; }
@@ -45,11 +47,14 @@ public class SeparateColorNode : Node
             CombineSeparateColorMode.HSL => GetHsla(ctx)
         };
 
-    private Half4 GetRgba(FuncContext ctx) => ctx.GetOrNewAttachedHalf4(this, Color, () => Color.Value(ctx));
+    private Half4 GetRgba(FuncContext ctx) => 
+        contextVariables.GetOrAttachNew(ctx, Color, () => Color.Value(ctx));
 
-    private Half4 GetHsva(FuncContext ctx) => ctx.RgbaToHsva(this, Color, () => ctx.GetValue(Color));
+    private Half4 GetHsva(FuncContext ctx) =>
+        contextVariables.GetOrAttachNew(ctx, Color, () => ctx.RgbaToHsva(ctx.GetValue(Color)));
 
-    private Half4 GetHsla(FuncContext ctx) => ctx.RgbaToHsla(this, Color, () => ctx.GetValue(Color));
+    private Half4 GetHsla(FuncContext ctx) =>
+        contextVariables.GetOrAttachNew(ctx, Color, () => ctx.RgbaToHsla(ctx.GetValue(Color)));
 
     public override Node CreateCopy() => new SeparateColorNode();
 }

+ 46 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/NodeVariableAttachments.cs

@@ -0,0 +1,46 @@
+using PixiEditor.ChangeableDocument.Changeables.Graph.Context;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
+using PixiEditor.DrawingApi.Core.Shaders.Generation;
+
+namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+
+internal class NodeVariableAttachments
+{
+    private readonly List<(INodeProperty key, ShaderExpressionVariable variable)> _variables = new();
+    
+    public FuncContext LastContext { get; private set; }
+
+    /// <summary>
+    /// Tries getting a shader variable associated to the property. Otherwise, it creates a new one from the variable factory
+    /// </summary>
+    /// <typeparam name="T">The shader variable type. i.e. Half4, Float1</typeparam>
+    /// <returns>The attached or new variable</returns>
+    public T GetOrAttachNew<T>(FuncContext context, INodeProperty property, Func<T> variable) where T : ShaderExpressionVariable
+    {
+        if (LastContext != context)
+        {
+            LastContext = context;
+            _variables.Clear();
+            
+            return AttachNew(property, variable);
+        }
+
+        var existing = _variables.FirstOrDefault(x => x.key == property);
+
+        if (existing == default)
+        {
+            existing.variable = AttachNew(property, variable);
+        }
+
+        return (T)existing.variable;
+    }
+
+    private T AttachNew<T>(INodeProperty property, Func<T> variable) where T : ShaderExpressionVariable
+    {
+        var newVariable = variable();
+        
+        _variables.Add((property, newVariable));
+
+        return newVariable;
+    }
+}

+ 0 - 14
src/PixiEditor.DrawingApi.Core/Shaders/Generation/ShaderBuilder.cs

@@ -181,20 +181,6 @@ public class ShaderBuilder
         return result;
     }
 
-    public Half4 GetOrNewAttachedHalf4(int hash1, int hash2, Func<Expression> assignment)
-    {
-        var name = $"color_attached_{hash1}_{hash2}";
-        
-        var result = _variables.FirstOrDefault(x => x.VariableName == name);
-
-        if (result == null)
-        {
-            return AssignNewHalf4(name, assignment());
-        }
-
-        return (Half4)result;
-    }
-
     public void Dispose()
     {
         _bodyBuilder.Clear();