Connections & the dataflow graph
A document is also a graph
A property need not store its value — it can connect to another prim's output and take its value from there. The moment one connection exists, the Document is no longer just a tree: it is a directed graph laid over the same prims.
def group "world" {
def material "mat" { float3 out = (0.8, 0.1, 0.1) }
def object "ball" {
float3 albedo = (1, 1, 1) # fallback if nothing is connected
albedo.connect = </world/mat.out> # …but the value flows from the material
}
}
A connection is written slot.connect = <path> and is, fundamentally, two paths: a target property and a source property. Because both endpoints are paths, the entire web of dataflow is plain, diffable text, and — since identity is hierarchical — it can never form a cycle through the tree structure itself.
doc.connect(Path("/world/ball.albedo"), Path("/world/mat.out"));
for (const Connection& c : doc.connections()) // the graph is just data
/* c.target, c.source */;
The evaluator
Resolving a connected, possibly animated property is the job of the evaluator. It walks the connection to its source, resolves that source property at the requested time (interpolating samples, following further connections), and returns the concrete value:
Value albedo = evaluate(s, Path("/world/ball.albedo"), /*time*/ 0);
// → (0.8, 0.1, 0.1): pulled through the connection to the material's output
Connections compose: a chain of them is a small dataflow program, pulled on demand. A generator feeding a transform feeding a material is just three prims and two connections, evaluated lazily when something asks for the end of the chain.
The dependency graph
So that an edit does not force a full recompute, Core tracks a dependency graph: which prims depend on which, derived from the connections. When an input changes, only the outputs that actually depend on it are invalidated, and an evaluation cache keeps repeated reads of unchanged values cheap.
Crucially, none of this lives in a parallel "compute graph" you must keep in sync with the document. The graph the evaluator pulls through is the prims and their connections — the same Document you saved. There is no build step from "document" to "scene graph," which is the property that makes the model safe to drive live from a UI or an agent: change a value, and exactly the dependent values recompute, with no separate structure to rebuild.
Connections link properties within one document. To link across documents — to reuse whole subtrees — see composition.