From 40027db357ff39f7aa9255c4c2a088bdc6996db4 Mon Sep 17 00:00:00 2001 From: meleki Date: Sun, 27 Sep 2026 21:56:30 +0200 Subject: [PATCH] Describe inline lists and the Variables tab, 1486 editor checks (#252) --- Architecture.md | 7 +++++-- Behaviors.md | 35 +++++++++++++++++++++++------------ Development.md | 4 ++-- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/Architecture.md b/Architecture.md index 1c6aa71..e3650fe 100644 --- a/Architecture.md +++ b/Architecture.md @@ -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, diff --git a/Behaviors.md b/Behaviors.md index 6e3008c..2222bb8 100644 --- a/Behaviors.md +++ b/Behaviors.md @@ -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:` 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), diff --git a/Development.md b/Development.md index e5cbf81..6fc66f7 100644 --- a/Development.md +++ b/Development.md @@ -15,7 +15,7 @@ npm run build # writes dist/ and regenerates index.html php tools/make-user.php [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`,