Describe inline lists and the Variables tab, 1486 editor checks (#252)

admin committed 2026-09-27 21:56:30 +02:00
1 parent 1c9777a756
commit 40027db357
3 files changed
+30 -16

No files matched your search

+5 -2
@@ -187,7 +187,7 @@ src/editor/viewport/ WorldViewport base → FreeViewport (a camera of its own:
polygonCorners (a polygon collider's corner handles, #151), tilemapSolids (where a placed
map blocks, outlined like a collider, #132/#173)
src/editor/inspector/ Inspector panel, host (what a section builds into), field factory, previewHandlers (scrub → preview → command), valueSpecs
(where a value lives — shared with the List tab),
(where a value lives — shared with the inline lists),
one section per selection kind (asset/object/node/frame/shape), variableRows (one row shape for
every variable), shapeSection (the shapes of a vector drawing: the list, the four order
buttons and the style of the picked one, #129; Fill type and Line type with the stop bar,
@@ -248,7 +248,10 @@ src/editor/shader/ ShaderEditor (graph canvas, preview panel with a slider p
previewPicture (which selection has a picture, what it shows, slider start values,
the built-in test image)
src/editor/PreviewSplit.ts graph left, preview panel right, the splitter between them (Particles, Shader)
src/editor/list/ ListEditor (a row per item), slot (which list is being edited, and how it is written back)
src/editor/list/ InlineList (a list's items drawn where the list stands, a row per item, #252),
slot (where a list lives, and how it is written back)
src/editor/variables/ VariablesEditor (the Variables tab: every variable of an owner, or one list),
target (the document of a tab, how much of a list the inspector draws)
src/editor/console/ log (ring buffer, argument formatting, the console.* capture), ConsolePanel (the tail under the tabs)
api/ PHP backend: index.php (routing and the sign-in gate),
lib/{Store,TextureStore,FontStore,SoundStore,PluginStore,OriginalName,Response}.php,
+23 -12
@@ -49,7 +49,7 @@ playing use the same two words.
`Raycast all` (#157) hands out a list of objects, and written into a list variable it stays one.
An object lives for the run only. At rest (in the file, a snapshot, the inspector) its place
always holds the empty object, stored as `{"$object": ""}` wherever it sits, and the inspector and
the List tab show `(null)` and offer nothing to pick. During a run the object sits right in the
its inline lists show `(null)` and offer nothing to pick. During a run the object sits right in the
value, and every way out of the run empties it again (`core/graph/liveObjects.ts`,
`withoutObjects`): the values the editor run writes back into the scene as overrides, the save of
a persistent Variables asset, the live values the inspector shows and the test hooks. A struct
@@ -59,16 +59,27 @@ playing use the same two words.
"Is it still there?" is `Equals` with the object on `a` and `b` left empty: true once it is gone.
Kept variables of a called behavior (#229) keep their objects across calls too, and `Properties`
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, 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 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
A list is **drawn inline** (#252): its row says how many items it holds and has a `+ Item ▾`,
and right under it each item gets a row with the same widget the inspector would use for that
kind — a struct item is its fields as rows under each other, a list item is a list again, drawn
inline one step further in. The inspector draws the first **20** items and then says
`… N more`, a click on that line opens the whole list in a tab; the rows follow a list that a
running game fills. Where the list is
stored (asset property, object override or node setting, plus a `path` of struct keys and list
indices when the list sits inside the value, #239) is a `ListSlot`, resolved again on every edit,
so an inline edit is the same command and the same undo step as any inspector row.
**Variables tab:** the count of a list is a button that opens that list in a **Variables tab** of
its own, all items drawn. Its title spells the path out, for example `Enemies · [3] · drops`, and
clicking the count of a list inside it opens **another** tab beside it — it never replaces the tab
it was clicked in. A list that has its tab already brings that tab up. `Open` in the `VARIABLES`
header of a behavior, a Variables asset or a placed behavior opens a Variables tab with all of
its variables (`Pickup · Variables`, `Coin 3 · Variables`), drawn by the inspector's own rows:
declarations editable on the asset, overrides with reset and apply on a placed object, the values
of the run while one is going. A tab whose owner is deleted closes. The tabs are documents like
an asset's (`values:<key>` in `__gm.documents()`); no tab may reach into the `Editor`, so a button
asks for one through `openValues` on the editor state. An **unconnected `list` input** of a node is
drawn inline too, without a tab to open: 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
small picture for every other kind: a tick for a boolean, a half-filled square for a color, a grid
for a texture, a square with a cross for a struct) is the picker — a click opens the menu, with no chevron, since the mark has to stay as narrow as
@@ -221,7 +232,7 @@ playing use the same two words.
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
struct is two `Expand` nodes in a row, and there is no path syntax like `a.b[2].c`. `+ Item`
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),
+2 -2
@@ -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 # 1481 editor checks, screenshots in /tmp/gm-e2e-*.png
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1486 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
@@ -71,7 +71,7 @@ to touch it.
The e2e run is a list of steps in `tools/e2e/` (hierarchy, inspector, play, assets, drawing,
graph, parenting, colliders, containers, text/enabled, menus, textures, frames, overflow, aspect,
container tab, run-in-editor, pause, nested behaviors, key repeat, list tab, struct variable,
container tab, run-in-editor, pause, nested behaviors, key repeat, inline lists and the Variables tab, struct variable,
variable nodes, property nodes, animations, state machines, console, shaders, transforms, fonts,
particles, shared scope, render on change, sounds, load scene, graph groups, nine-slice, plugins, tiles, tilemaps, physics, shapes, queries, documents, sign-in) that build on each other's
scene state and share the CDP driver in `tools/lib/harness.mjs` — `press`, `undo`, `play`,