Show lists in the inspector and variables in their own tab (#252)
The List tab could show one list at a time and was the only place to see its items. A list now shows its items right where it lives, and a new Variables tab shows all variables of an asset or placed object. - InlineList draws the items of a list under its row in the inspector, in struct fields and in the Variables tab. A list inside a list or a struct field is drawn the same way, one step indented. - The index column is the indent. Items sit under their list without an own margin, and the index column is 16 px wide instead of 28 px. - Above 20 items (INLINE_LIMIT) the rest collapses into "... N more - open in tab". During a run the rows show the values from the game. - ListHead puts "N items" and "+ Item" in one row. "N items" opens the list in a tab. A separate Open button squeezed the counter to zero width in the narrow inspector column. - VariablesEditor shows every variable of a behavior asset, a variables asset or a placed behavior. On an asset it edits the declarations. On a placed object an edit only overrides that object, with the usual reset and push buttons. - Opening a list inside a tab adds a new tab and keeps the open one. valuesKey gives each list its own document, so a list that is already open is shown instead of opened twice. - Titles read "Pickup · Variables" or "Listy · nums · [3]". The tab closes when its asset or object is deleted. - Lists on node inputs stay inline only, a node owns no variables. - The List tab, ListEditor and the __gm.list hook are gone. Tests: - ./check.sh: 181 files, 2645 tests, CHECK EXIT 0 - GM_STEPS=1,21,22,32: ALL PASSED, 123 checks - e2e 21 is rewritten for inline lists and the new tab, 22 and 32 are adapted. Sum in README: 1486 (+6 in 21, -1 in 22), counted by hand. - Counter-probes fail as expected: sub-lists not told apart (1 unit test), sub-list replacing the open tab, all items drawn inline (60 rows instead of 20), no live values (0 rows at 24 items in a run). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
92fad6b9e3
commit
4857bb75e6
26 files changed
+1203
-427
No files matched your search
+18
-16
@@ -120,10 +120,10 @@ export async function structVariable(t) {
|
||||
JSON.stringify(await piece()),
|
||||
);
|
||||
|
||||
// 22f. A field may itself be a list. Its row is the same "n items" button a list property has,
|
||||
// and it opens the List tab one level down – on the field, not on the whole bundle.
|
||||
// 22f. A field may itself be a list. Its items are drawn inline under it (#252), and its
|
||||
// title names the field inside the bundle – not the whole bundle.
|
||||
await clickText('+ Field');
|
||||
// "List" is also the tab bar's own label, so the menu entry is reached as the last drawn one.
|
||||
// "List" is also a word elsewhere on screen, so the menu entry is reached as the last drawn one.
|
||||
const listOption = await json(`__gm.locate('List', true)`);
|
||||
await click(listOption.x, listOption.y);
|
||||
check(
|
||||
@@ -131,28 +131,32 @@ export async function structVariable(t) {
|
||||
Array.isArray((await piece()).field1),
|
||||
JSON.stringify(await piece()),
|
||||
);
|
||||
const itemsButton = await find('0 items');
|
||||
check('and that field reads as an item count', itemsButton !== null);
|
||||
|
||||
await click(itemsButton.x, itemsButton.y);
|
||||
check('clicking it opens the List tab', (await json('__gm.tab()')) === 'list');
|
||||
const info = await json('__gm.list.info()');
|
||||
check('whose title names the field inside the bundle', info.title.endsWith('· field1'), info.title);
|
||||
check('and that field reads as an item count', (await find('0 items')) !== null);
|
||||
const fieldList = async () =>
|
||||
(await json(`__gm.values.lists('inspector')`)).find((l) => l.title.endsWith('· field1')) ?? null;
|
||||
const drawn = await fieldList();
|
||||
check(
|
||||
'whose items are drawn inline, titled by the field inside the bundle',
|
||||
drawn !== null,
|
||||
JSON.stringify(drawn),
|
||||
);
|
||||
|
||||
// Nothing bounds the depth any more (#239): a list in a struct field offers what any list does.
|
||||
await clickText('+ Item');
|
||||
const head = await json(`__gm.values.headAt('inspector', ${JSON.stringify(drawn?.title ?? '')})`);
|
||||
await click(head.add.x, head.add.y);
|
||||
check(
|
||||
'the menu of a list in a struct field offers every kind, the struct included',
|
||||
(await find('Number')) !== null &&
|
||||
(await find('Struct')) !== null &&
|
||||
(await json('__gm.list.info()')).offers.includes('list'),
|
||||
JSON.stringify((await json('__gm.list.info()')).offers),
|
||||
(await fieldList()).offers.includes('list'),
|
||||
JSON.stringify((await fieldList()).offers),
|
||||
);
|
||||
await pickKind('Number');
|
||||
await sleep(250);
|
||||
check(
|
||||
'and an item added there leaves the neighbouring fields alone',
|
||||
JSON.stringify(await piece()) === '{"column":30,"tag":"tee","field1":[0]}',
|
||||
JSON.stringify(await piece()) === '{"column":30,"tag":"tee","field1":[0]}' &&
|
||||
(await fieldList()).rows === 1,
|
||||
JSON.stringify(await piece()),
|
||||
);
|
||||
await shot('03-list-field');
|
||||
@@ -164,8 +168,6 @@ export async function structVariable(t) {
|
||||
JSON.stringify(await piece()),
|
||||
);
|
||||
|
||||
await mutate('__gm.state.openList(null)');
|
||||
|
||||
// 22f-ii. A field may be a struct again (#239): a head row with a `+ Field` of its own, and its
|
||||
// fields one indent step further in. Both menus with real clicks.
|
||||
const declaredLast = () =>
|
||||
|
||||
Reference in new issue
Block a user