Log inGet started

procNode — custom procedural nodes as content

A .procNode is a procedural operation authored as content: a folder whose init.luau returns a def table. When the asset registers, its def joins the proc op registry keyed by the asset's stable GUID,…

MyNode.procNode/
  init.luau     -- returns the def table
  README.md
  .metadata

Two def kinds

Op-style — a custom operation

init.luau returns an op def: typed input sockets, params, typed output sockets, and an eval that produces the outputs.

return {
    kind = "op",
    description = "Scale a Geometry uniformly.",
    inputs = { geometry = { type = "Geometry" } },
    params = { factor = { type = "Float", default = 2.0 } },
    outputs = { geometry = { type = "Geometry", default = true } },
    -- eval(ctx, inputs, params) -> outputs table.
    -- ctx carries seed / nodeId / compositePath / hash / checkpoint.
    eval = function(ctx, inputs, params)
        return { geometry = inputs.geometry:scaled(params.factor) }
    end,
}

The def's version is derived from the source text on every registration, so editing init.luau re-keys the node caches of every graph that reaches this node — downstream cooks refresh automatically.

init.luau is compiled from its current source on each registration, so any module it pulls in uses an absolute require (require("@builtin::…")).

Subgraph-style — a .procGraph graph used as a node

init.luau returns a def bound to a .procGraph graph asset. The graph's declared inputs become the node's params; its declared outputs become the node's outputs. Evaluating the node evaluates the graph.

return {
    kind = "graph",
    -- A `.procGraph` asset ref (resolve it by guid, not by name).
    graph = asset.resolve("<graph-guid>", "procGraph"),
}

A .procGraph graph can also be used as a node directly, without a wrapping procNode, by passing its asset ref to Graph.node:

local g = proc.graph("parent")
local childRef = asset.resolve("<graph-guid>", "procGraph")
g:node("sub", childRef):param("radius", 3)

Either way, referencing a graph as a node persists a typed GUID ref in the parent's graph.json, so the referenced asset travels with the parent as a dependency (it appears in asset.deps). A graph that reaches itself — directly or transitively — errors loudly at eval rather than recursing without bound.

Registration is push-model

The registry is populated by this type's lifecycle hooks: onRegister registers instances present at load, onChange re-registers + hot-reloads on edit, onDelete unregisters. A graph that references a procNode which is not registered errors loudly at load/eval, naming the missing GUID — there is no name-probing fallback.

  • asset-type
  • reference