Mutable builder for an ExprNodeGraph. Each method returns the node (or
port handle) so call sites can chain add() / connect() calls without
juggling raw ids.
Local variable declared at the top of a graph block. Lives for the duration
of one block execution (one particle per frame). initial may reference
earlier-declared variables but not itself or later ones; if omitted the
variable is zero-initialized.
A composable graph of variables and actions. Used as the body of an
'expression' ModifierNode (regular per-frame update) or as the action list
for an on_spawn / on_death event.
Editor-visible position of a node on its sub-canvas. Runtime ignores it.
A single node in an ExprNodeGraph. The graph stores nodes by id; the
kind indexes NODE_KINDS for ports + codegen; params carries
kind-specific non-wired configuration (constant value, attribute name,
math op variant, etc.); inputValues carries per-input literal defaults
(number / vec3 / vec4 / bool) used when an input port has no incoming edge.
Directed edge from one node's output port to another node's input port.
Node-graph form. nodes/edges form the DAG; statements is the ordered
list of effect-node ids (SetAttribute/SetVariable) that drive side effects;
variables declares local variables visible to VariableGet/VariableSet
(same shape as ExpressionGraph.variables).
Port definition exposed by a node kind. Type is documentation today; the WGSL compiler is the authoritative type checker.
Declarative spec for a node kind. Drives both the editor (palette label, port rendering, property inspector) and the compiler (input/output wiring, Expr/Action codegen).
One row of a compound setAttribute node. attr picks the particle
attribute to write; mode picks the composition (overwrite/add/...).
Each entry adds one data input port to the node, named after attr.
One row of a compound attribute (Get Attribute) source node. Each entry
adds one typed output port to the node, named after attr. Lets a single
Get Attribute node expose several attributes at once with one output per
attribute (mirror of setAttribute's compound input model).
Describes how a particle system spawns new particles each frame.
One-shot actions triggered at a specific point in a particle's life.
Sub-emitter: when a parent particle hits the trigger, atomically appends
count spawn requests (parent state + inheritance) into a GPU queue. The
child pass's queue-spawn shader consumes the queue each frame.
Full description of a particle system, consumed by the particle pass and shader builders.
Particle attributes that expressions can read from or assign to. Map to
fields on the Particle struct (see particle_builder.ts header):
How setAttribute composes the new value with the existing attribute:
overwrite (default): replaceadd / subtract / multiply: in-place arithmeticmin / max: component-wise min/maxHow a random node draws its seed:
Value-producing expression node. Recursive — operators take other Exprs
as inputs. Each node produces a single value whose WGSL type is implied by
its kind and inputs; mismatched types surface as WGSL compile errors at
pipeline-creation time.
Side-effecting graph statement. Actions execute top-to-bottom inside the graph block and can mutate particle attributes or declared variables.
Which shader stage an expression block is being compiled into. Affects how random seeds and a few attributes are resolved.
Param spec for the editor's property inspector. Runtime just reads params
out of ExprNode.params directly.
Concrete WGSL-style type; never 'any' after inference. 'bool' is the
bottom; vector types form a 2/3/4-wide ladder above f32.
Type per (node, output port). Use keyOf to build/lookup keys.
Geometric region used by an emitter to choose initial particle position and velocity direction.
Coordinate space for a modifier's position/center fields. 'world' treats
the literal as a world-space point; 'emitter' treats it as an offset from
the emitter's effective origin (the GameObject transform plus the emitter's
local position).
Per-frame behavior applied to live particles in the update compute pass.
Constructor helpers for Expr nodes. Equivalent to building the discriminated
union by hand, but shorter and accepts plain numbers in any slot.
Constructor helpers for Action nodes. Use action.set(attr, value) for the
common overwrite case; pass a third arg for add/multiply/etc. modes.
Registry of all known expression-graph node kinds. The editor reads this to build its palette and property inspector; the compiler reads it to wire inputs and synthesise WGSL.
Stable display color per concrete type. Used by the overlay for port circles and edge strokes. Pinned palette so colors stay consistent across the overlay, the editor, and any future visual tools.
Compile an ExpressionGraph to a WGSL { ... } block, ready to slot into
the modifier sequence in spawn or update shaders.
Effective input ports for a node instance: kind.dynamicInputs(params) if
defined, else the static kind.inputs. Use this everywhere (compiler,
type inference, overlay) instead of reading kind.inputs directly so
compound nodes work without special-casing each call site.
Effective output ports for a node instance: kind.dynamicOutputs(params)
if defined, else the static kind.outputs. Mirror of getNodeInputPorts
for output ports — used wherever code needs the live port list (compiler,
type inference, overlay, editor).
Normalize a attribute (Get Attribute) node's params to a list of
resolved entries (each with its port name). Accepts both the compound form
(params: { entries: [{attr}, ...] }) and the legacy single-attr form
(params: { attr }). Legacy entries keep the historical 'value' port
name; compound entries use the attribute name as the port name.
Normalize a setAttribute node's params to a list of resolved entries
(each with its port name). Accepts both the compound form
(params: { entries: [{attr,mode},...] }) and the legacy single-attr form
(params: { attr, mode }). Legacy entries keep the historical 'value'
port name; compound entries use the attribute name as the port name so the
editor can render the attribute label next to the port.
Convert a primitive literal (number / vec / bool) to an Expr. Used both
by defaultExprForPort and by the compiler's inline-value path.
Build a default Expr for a port whose incoming edge is absent and which
has no per-node inline value. Honors the port's kind-wide default if
given; otherwise produces a zero value of the port's declared type.
Compile a node-graph form to the existing ExpressionGraph AST. The result
plugs into the 'expression' ModifierNode the same way a hand-built AST
does, so the whole spawn/update pipeline downstream is unchanged.
Infer the type of every (node, output port) in the graph. The returned
TypeMap is keyed by keyOf(nodeId, outputPort). Nodes participating in
cycles (which the compiler would reject anyway) are conservatively
resolved to 'f32'.
Convenience: get the inferred type for a (node, port), or 'f32' if the
pair isn't in the map (e.g. the node has no outputs).
Concrete type for an input port, given the inferred graph types. Same precedence as the compiler's input resolution (edge > inputValues > port.default > port.type), so the editor's port color matches what the WGSL compiler will actually see.
The GPU particle system: the graph node types (emitters, spawn shapes, modifiers, render nodes) and expression helpers that describe a particle effect, which
ParticlePass(undersrc/renderer/render_graph/passes/) compiles and simulates on the GPU.