Let a behavior be a node in another graph
A behavior that has a Start and an End node can now be dropped into any other graph as a node of its own. What is declared on the start node becomes the inputs of that node, what hangs on the end node its outputs; the port list is derived from the sub graph, not copied, so declaring a port in one graph grows the node in the other without touching it. The node carries the behavior's name and the palette lists behaviors by name, so a call is one grab instead of a node plus a dropdown. An embedded behavior has no object and therefore no place for variables: every call starts on the asset defaults and communicates only through its ports. That is the conservative direction - state can still be added later, and shared state already has a home in a behavior object in the scene. Node ids are unique per graph only, so each call gets its own pulse cache; without that, two graphs would collide. Renaming a port used to silently drop the value typed on the calling node. It is carried along now, project wide, like the edges.
This commit is contained in:
1 parent
64e034ffb9
commit
6702ff8abe
31 files changed
+1402
-107
No files matched your search
@@ -1,5 +1,15 @@
|
||||
// Importing the graph package index is what registers the built-in nodes.
|
||||
import { createEmptyGraph, type Graph, type GraphEdge, type GraphNode, nodeDef } from '../graph';
|
||||
import {
|
||||
createEmptyGraph,
|
||||
DECLARED_PORT_KINDS,
|
||||
type DeclaredPort,
|
||||
type DeclaredPortKind,
|
||||
type Graph,
|
||||
type GraphEdge,
|
||||
type GraphNode,
|
||||
isValidPortName,
|
||||
nodeDef,
|
||||
} from '../graph';
|
||||
import type { Asset, TextureFrame } from '../model/Asset';
|
||||
import { isAssetType } from '../model/AssetTypes';
|
||||
import { emptyEdit, type InstanceEdit, isEmptyEdit } from '../model/instance';
|
||||
@@ -166,6 +176,22 @@ function normalizeVariables(raw: unknown): PropertyDef[] {
|
||||
return defs;
|
||||
}
|
||||
|
||||
function normalizePorts(raw: unknown): DeclaredPort[] {
|
||||
const ports: DeclaredPort[] = [];
|
||||
const seen = new Set<string>();
|
||||
for (const item of Array.isArray(raw) ? raw : []) {
|
||||
const p = asRecord(item);
|
||||
const key = typeof p.key === 'string' ? p.key : '';
|
||||
if (!isValidPortName(key) || seen.has(key)) continue;
|
||||
seen.add(key);
|
||||
const kind = (DECLARED_PORT_KINDS as readonly string[]).includes(String(p.kind))
|
||||
? (p.kind as DeclaredPortKind)
|
||||
: 'number';
|
||||
ports.push({ key, kind });
|
||||
}
|
||||
return ports;
|
||||
}
|
||||
|
||||
function normalizeGraph(raw: unknown): Graph {
|
||||
const g = asRecord(raw);
|
||||
const graph = createEmptyGraph();
|
||||
@@ -182,6 +208,8 @@ function normalizeGraph(raw: unknown): Graph {
|
||||
params[key] = value;
|
||||
}
|
||||
const node: GraphNode = { id, type, x: toNumber(n.x), y: toNumber(n.y), params };
|
||||
const ports = normalizePorts(n.ports);
|
||||
if (ports.length > 0) node.ports = ports;
|
||||
graph.nodes.push(node);
|
||||
}
|
||||
const edgeIds = new Set<string>();
|
||||
|
||||
Reference in new issue
Block a user