summaryrefslogtreecommitdiffstats
path: root/Scripts
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2026-01-02 16:21:34 -0800
committeryum <yum.food.vr@gmail.com>2026-01-02 17:32:14 -0800
commitfcc76b257ef5cfb4514669df3b0144f8e8dd76ef (patch)
treebb6e73c8f199699b3e88afb85e24e2c8b3df5aab /Scripts
parent43d81e11992c11eda06e4b67d2c5bd0b9c4b729b (diff)
Fold: implement dynamic branching in shader
Switch from static branching approach using per-op data and fixed execution order to dynamic branching approach using dynamic data. This confers the main benefit of letting us dynamically reorder ops and duplicate them. It also lets us eliminate some of the plumbing tedium whenever we want to add new ops.
Diffstat (limited to 'Scripts')
-rw-r--r--Scripts/Fold/Editor/FoldNodeSerialized.cs4
-rw-r--r--Scripts/Fold/Editor/KeyframeNodeView.cs53
-rw-r--r--Scripts/Fold/Editor/PointAlignNode.cs2
3 files changed, 56 insertions, 3 deletions
diff --git a/Scripts/Fold/Editor/FoldNodeSerialized.cs b/Scripts/Fold/Editor/FoldNodeSerialized.cs
index 4836811..62431ae 100644
--- a/Scripts/Fold/Editor/FoldNodeSerialized.cs
+++ b/Scripts/Fold/Editor/FoldNodeSerialized.cs
@@ -2,11 +2,15 @@ using UnityEngine;
public class FoldNodeSerialized
{
+ public int opcode;
+
+ // Correspond to _Vertex_Deformation_Float_0, etc.
public float float0;
public float float1;
public float float2;
public float float3;
+ // _Vertex_Deformation_Vector_0, etc.
public Vector4 vec0;
public Vector4 vec1;
public Vector4 vec2;
diff --git a/Scripts/Fold/Editor/KeyframeNodeView.cs b/Scripts/Fold/Editor/KeyframeNodeView.cs
index fd90c75..225b5b6 100644
--- a/Scripts/Fold/Editor/KeyframeNodeView.cs
+++ b/Scripts/Fold/Editor/KeyframeNodeView.cs
@@ -2,6 +2,7 @@ using GraphProcessor;
using UnityEngine.UIElements;
using UnityEngine;
using System.Linq;
+using System.Collections.Generic;
[NodeCustomEditor(typeof(KeyframeNode))]
public class KeyframeNodeView : BaseNodeView
@@ -25,10 +26,58 @@ public class KeyframeNodeView : BaseNodeView
void OnGenerateClick()
{
var go = GetConnectedGameObject();
- if (go?.GetComponent<MeshRenderer>() == null) return;
+ if (go == null) return;
+ var rend = go.GetComponent<MeshRenderer>();
+ if (rend == null) return;
var foldNode = GetConnectedFoldNode();
- Debug.Log($"Generating Keyframe for '{go.name}' using Fold Data: {(foldNode?.name ?? "None")}");
+
+ // Accumulate nodes. We are going backwards from the output node
+ // (KeyframeNode) to the root node.
+ var foldNodes = new Stack<BaseFoldNode>();
+ var cur = foldNode;
+ while (cur != null) {
+ foldNodes.Push(cur);
+ cur = GetInputFoldNode(cur);
+ }
+
+ var mpb = new MaterialPropertyBlock();
+ rend.GetPropertyBlock(mpb);
+
+ // Set material properties for all 16 slots.
+ for (int i = 0; i < 16; i++) {
+ string slotPrefix = $"_Vertex_Deformation_Slot_{i}_";
+ BaseFoldNode node = (foldNodes.Count > 0) ? foldNodes.Pop() : null;
+ FoldNodeSerialized data = node?.Serialize();
+
+ bool active = data != null;
+ mpb.SetFloat(slotPrefix + "Enabled", active ? 1.0f : 0.0f);
+ mpb.SetInt(slotPrefix + "Opcode", active ? data.opcode : 0);
+
+ mpb.SetFloat(slotPrefix + "Float_0", active ? data.float0 : 0.0f);
+ mpb.SetFloat(slotPrefix + "Float_1", active ? data.float1 : 0.0f);
+ mpb.SetFloat(slotPrefix + "Float_2", active ? data.float2 : 0.0f);
+ mpb.SetFloat(slotPrefix + "Float_3", active ? data.float3 : 0.0f);
+
+ mpb.SetVector(slotPrefix + "Vector_0", active ? data.vec0 : Vector4.zero);
+ mpb.SetVector(slotPrefix + "Vector_1", active ? data.vec1 : Vector4.zero);
+ mpb.SetVector(slotPrefix + "Vector_2", active ? data.vec2 : Vector4.zero);
+ mpb.SetVector(slotPrefix + "Vector_3", active ? data.vec3 : Vector4.zero);
+ }
+
+ rend.SetPropertyBlock(mpb);
+ Debug.Log($"Generated Keyframe for '{go.name}' with properties applied to all 16 slots.");
+ }
+
+ BaseFoldNode GetInputFoldNode(BaseFoldNode node)
+ {
+ // Traverse via edges in the graph model, as 'input' field might not be populated in Editor
+ var port = node.GetPort(nameof(BaseFoldNode.input), null);
+ if (port == null) return null;
+
+ // Find the edge connected to this input port
+ var edge = node.graph.edges.FirstOrDefault(e => e.inputPort == port);
+ return edge?.outputNode as BaseFoldNode;
}
T GetConnectedNode<T>(string fieldName) where T : class
diff --git a/Scripts/Fold/Editor/PointAlignNode.cs b/Scripts/Fold/Editor/PointAlignNode.cs
index 7ab094b..c113928 100644
--- a/Scripts/Fold/Editor/PointAlignNode.cs
+++ b/Scripts/Fold/Editor/PointAlignNode.cs
@@ -15,7 +15,7 @@ public class PointAlignNode : BaseFoldNode
public override FoldNodeSerialized Serialize()
{
- return new FoldNodeSerialized { vec0 = po };
+ return new FoldNodeSerialized { opcode = 0, vec0 = po };
}
}