Let structs and lists nest to any depth (#239)
1 parent
da7ddd21c8
commit
19fa428d46
2 files changed
+22
-16
No files matched your search
+21
-15
@@ -39,7 +39,7 @@ playing use the same two words.
|
||||
type as a setting row (*Type: Sprite*, plus *Behavior: Game* under that type). Textures and
|
||||
scenes are no type here: they are not objects in a running game. A variable is a
|
||||
**number, a text, a yes/no, a colour, a texture, a state machine, an asset, an object, a list or a struct**; a list declares **nothing** about its items —
|
||||
each one is a number, a text, a yes/no, a colour, a texture, a state machine, an asset, an object or a struct and says so itself, so one list may
|
||||
each one is a number, a text, a yes/no, a colour, a texture, a state machine, an asset, an object, a list or a struct and says so itself, so one list may
|
||||
hold several kinds at once. A list is
|
||||
compared by its items, never by identity — otherwise every reload would look like an override.
|
||||
**Objects** can be held wherever a value can (#238): an **object variable**, an **object field** of a
|
||||
@@ -61,10 +61,12 @@ playing use the same two words.
|
||||
of type *Behavior* reads and writes another behavior's object variable.
|
||||
A list property is shown as a button saying how many items it holds;
|
||||
clicking it opens the **List** tab, which gives each item a row with the same widget the
|
||||
inspector would use for that kind — a struct item is its fields as rows under each other. The inspector stays visible beside the tab, so what the list
|
||||
inspector would use for that kind — a struct item is its fields as rows under each other, a list item is a count button again. The inspector stays visible beside the tab, so what the list
|
||||
belongs to is still on screen. Which list the tab shows is a `ListSlot` (asset property, object
|
||||
override or node setting, plus the `field` of a struct that holds one) on the editor state,
|
||||
because no tab may reach into the `Editor` to switch itself on. An **unconnected `list` input**
|
||||
override or node setting, plus a `path` of struct keys and list indices when the list sits inside
|
||||
the value, #239) on the editor state, because no tab may reach into the `Editor` to switch itself
|
||||
on. The tab title spells that path out, for example `Enemies · [3] · drops`, and clicking the
|
||||
count of a list item or of a list field opens the tab one level further down. An **unconnected `list` input**
|
||||
of a node is the same button and the same tab: its inline value lives in the very same params
|
||||
bag a setting does, and the slot stops resolving the moment an edge feeds the port. What an item holds
|
||||
is **its own** and is chosen there: the **kind mark** in front of a row (`#` for a number, `Aa` for a text, a
|
||||
@@ -74,7 +76,8 @@ playing use the same two words.
|
||||
value, every such change is an ordinary **value edit**: one command, one undo step, and no
|
||||
neighbouring item touched. A **struct item** carries its own shape the same way: its fields are
|
||||
renamed, retyped, added (`+ Field ▾`) and removed on its own rows, which grows that one item and
|
||||
not the list. Three kinds need saying, because JSON cannot tell them from the value beside them: a
|
||||
not the list. A field of a struct item may be a struct again, drawn below it one indent step
|
||||
further in with a `+ Field ▾` of its own, or a list, which is a count button. Three kinds need saying, because JSON cannot tell them from the value beside them: a
|
||||
**colour** is a number, and a **texture** or a **state machine** is an id, which is a text. Such a *tagged* kind wears its
|
||||
name as the one key of a small object — `{"$color": 16711680}`, `{"$texture": "walk-up"}` (the
|
||||
picker a sprite's `texture` property has — a whole picture or one frame of a sheet),
|
||||
@@ -99,7 +102,10 @@ playing use the same two words.
|
||||
each other right in the inspector. Its head row renames it and adds fields (`+ Field`), each
|
||||
field row below carries its own name, its value and a remove — the port editor `Pack` already
|
||||
has, one level down and with a value column — and a field may itself be a **list**, which is
|
||||
the one count button that opens the tab one level deeper. Adding, renaming or removing a field reaches the
|
||||
the one count button that opens the tab one level deeper, or a **struct** (#239), which declares
|
||||
its own fields: it is a head row with its own `+ Field`, and its fields sit below it one indent
|
||||
step further in, at any depth. What arrives in such a field is brought into that declared shape,
|
||||
like the struct variable itself. Adding, renaming or removing a field reaches the
|
||||
declaration, the behavior's own value **and every instance override** in one command, so no
|
||||
stored value keeps a shape its declaration no longer promises. A placed instance draws every
|
||||
variable, whatever its kind, with the very same rows (`buildVariable`), minus the renaming, the
|
||||
@@ -200,15 +206,15 @@ playing use the same two words.
|
||||
have yet as one undo step and leaves the ones it has alone. Writing a struct variable keeps the
|
||||
fields it declares: what arrives fills the ones it names, the rest stay put (`mergeStruct`), so
|
||||
one node can set part of a bundle without erasing it — "the same piece, one row lower" is a
|
||||
`Pack` of that one field. Depth is bounded by the *value*, not by convention: a list item is a primitive, a
|
||||
tagged colour, texture or state machine, or a struct of flat ones (`listItems.ts`), a struct field says what it holds
|
||||
(`StructFieldKind`, primitives plus `list`), and the list a *field* holds takes flat items only.
|
||||
Forbidding just that one combination is what keeps the shapes finite:
|
||||
`list → struct → primitive` and `struct → list → primitive` are the two deepest a stored value
|
||||
goes — exactly what `asStoredValue` lets through an untyped slot — so the deep compare and the
|
||||
editor stay finite. The List tab **offers only the kinds its slot can hold** (`ListAccess.kinds`):
|
||||
on a list of its own all six, on a list a struct field holds the five flat ones. Offering the
|
||||
struct there would add an item the next write drops — which reads as the menu entry doing nothing. A live entity is
|
||||
`Pack` of that one field. **Nothing bounds the depth** (#239): a list item and a struct field may
|
||||
each be any kind, a list or a struct included (`NestedKind` in `kinds.ts`), and nothing deeper is
|
||||
dropped on load, in a node setting or on the way through a graph. There is no depth limit either.
|
||||
A struct inside a struct field is **declared** (`fields` on the field, like a struct variable),
|
||||
while a list still declares nothing about its items, so a struct item in a list takes its shape
|
||||
from its value at any depth. Named struct types that several variables share are a topic of their
|
||||
own. `Pack`, `Expand` and `Item at` take nested data apart **one level at a time**: a struct in a
|
||||
struct is two `Expand` nodes in a row, and there is no path syntax like `a.b[2].c`. The List tab
|
||||
offers every kind, on a list of its own and on one a struct field holds alike. A live entity is
|
||||
an object on a data edge too, so it carries a `Symbol` brand (`ENTITY_HANDLE`) that no struct
|
||||
field name can impersonate; nothing may hand a property value to `String()` (`textOf` instead),
|
||||
or a struct would read as `[object Object]`. A struct port has no inline value (its parts come
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ npm run build # writes dist/ and regenerates index.html
|
||||
php tools/make-user.php <name> <password> [admin|user] # an account; every tool signs in (see Accounts)
|
||||
php tests/php/accounts.test.php # the API's account rules, no server needed (CI's gate job)
|
||||
php tests/php/snapshots.test.php # the snapshot store (#231), the same way
|
||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1407 editor checks, screenshots in /tmp/gm-e2e-*.png
|
||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1416 editor checks, screenshots in /tmp/gm-e2e-*.png
|
||||
GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step
|
||||
./e2e.sh start [GM_STEPS] # the same run detached, see below
|
||||
./e2e.sh status # live progress, or the last run's result
|
||||
|
||||
Reference in new issue
Block a user