Reading one field of a struct needed its own Expand node, even where
the graph already knows the struct type. A split output shows the
fields directly on the node, so a Find … Match test becomes a single
Equals and the wires keep running left to right.
- Right-clicking an output pin offers "Split into <Type> fields" when
the type is known and "Split as …" for every other struct asset.
The output is replaced by one pin per field with the field's kind.
- The type is known for typed struct variables, typed Pack/Expand,
fields of another split and item of For each, Find, Match and Item
at over a typed list (portSplits.ts).
- Right-clicking a field pin offers "Recombine". Splitting drops the
edges of the whole output, recombining drops the field edges. One
undo step brings them back.
- The split is stored as GraphNode.splits and saved with the graph.
Copy and paste carry it along.
- Field pins follow the struct asset like a typed Expand. A new field
gets a pin, a removed field loses pin and edge, a renamed field keeps
its edge. Deleting the asset keeps the last fields. The delete dialog
counts splits, so it now says "node(s)" instead of "Pack/Expand
node(s)".
- Renaming a variable carries its split and the field edges along.
- At run time the node still produces the whole value. A field pin
reads its field like Expand, a missing field reads as empty.
- Limits: outputs only, one level, behavior graphs only.
Tests:
- ./check.sh: 185 files, 2706 tests, CHECK EXIT 0
- e2e GM_STEPS=1-6,54,55: ALL PASSED, 303 checks
- New port-splits.test.ts with 12 tests. e2e 6z-vi with 3 checks
using a real mouse: split Find.item, wire item.Name into the test
and Match.item.Amount into the log (logs 7), recombine.
- Counter-checks: without field reads in the interpreter, without
rename in the split, without moving edges on rename and without
cleanup on field removal one unit test fails each. In the browser,
without field reads nothing is logged and without type inference
the split entry is missing.
- Check total in README: 1520.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A struct used to declare its fields wherever it stood. The same shape
in two variables meant typing it twice, and Pack/Expand copied it once
without staying in sync. A Struct asset now holds the shape in one
place, and every struct that picks it as its type follows it.
- New asset type "Struct" (not placeable, group Structs, own icon).
The inspector shows its fields with name, kind and default value,
and "Open" shows them in the variables tab.
- Struct variables and struct fields get a Type row: own fields, any
Struct asset, or "Make struct type". With a type the fields come
from the asset and cannot be added, renamed or removed there. The
values stay per variable, overrides on placed objects still work.
- Pack and Expand get the setting Type. With a type their ports are
the fields of the asset and read-only in the inspector.
- A change to the asset reaches every typed place in one undo step
(syncStructTypes). A new field arrives with its default. A removed
field goes along with its port, edge and typed value. A renamed
field keeps its value in variables, overrides and on ports with
edges, also through nested types.
- Undo for these edits records plain assignments (Recorder), because
the reach of a change is not known in advance.
- Cycles such as Loot in Loot, also through another type, are refused
and not offered in the picker.
- Deleting the asset names how many places use it. Afterwards each
place keeps its fields as its own.
- Loading reshapes a stale copy in a project file to its type.
- "Make struct type" creates an asset from an existing struct and
links the place to it.
Differs from the plan:
- A changed default value applies to new fields and newly typed
places only. Existing values stay.
- Removing a single field shows no warning. Undo brings it back.
Typed lists are left for #254. Lists stay dynamic for now.
Found by e2e: after deleting or renaming the type the inspector did
not rebuild and kept showing the old name. Fixed, the check was red
before.
Tests:
- ./check.sh: 182 files, 2661 tests, CHECK EXIT 0
- GM_STEPS=1,4,21,22,54: ALL PASSED, 176 checks
- 14 unit tests in tests/core/struct-types.test.ts
- New e2e module 54 with 14 checks, real mouse. Module 04 counts
23 asset types.
- Counter-probes: without the rename pass 4 unit tests fail, without
reshaping values 8, without the cycle rule 1. In the browser,
without spreading changes and with + Field despite a type, 3
checks fail.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>