Title a collapsed Variables or Properties node by what it does
Collapsed, the node reads "Set 2 variables", "Get width" or "No properties"; expanded it is always "Variables" / "Properties". The Properties node shows its object type (and behavior) as a line under the title instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
58f19a3451
commit
0376ae175d
11 files changed
+182
-69
No files matched your search
@@ -186,7 +186,53 @@ export async function variableNodes(t) {
|
||||
await sleep(300);
|
||||
check('and undo points it back', (await portsOf('vp-get'))[0].key === 'vx');
|
||||
|
||||
// 23f. A Pack keeps declaring its own fields, but a variable that already carries the shape can
|
||||
// 23f. Collapsed, the ports are out of sight, so the title says what the node does – and only then.
|
||||
const titleOf = (id) => json(`__gm.graph.nodeLabel(${JSON.stringify(id)})`);
|
||||
const toggle = async (id) => {
|
||||
const chevron = await json(`__gm.graph.chevronAt(${JSON.stringify(id)})`);
|
||||
await click(chevron.x, chevron.y);
|
||||
await sleep(250);
|
||||
};
|
||||
/** `locate` matches exactly, so a title cut short by a too-narrow node is not found. */
|
||||
const drawnWhole = async (text) => {
|
||||
const canvas = await json('__gm.graph.canvasRect()');
|
||||
const hits = await json(`__gm.locateAll(${JSON.stringify(text)})`);
|
||||
return hits.some((p) => p.x > canvas.x && p.x < canvas.x + canvas.w);
|
||||
};
|
||||
await toggle('vp-set');
|
||||
await toggle('vp-get');
|
||||
const shut = { set: await titleOf('vp-set'), get: await titleOf('vp-get') };
|
||||
check(
|
||||
'collapsed, a node writing two variables says so, and one only reading two says that',
|
||||
shut.set === 'Set 2 variables' &&
|
||||
shut.get === 'Get 2 variables' &&
|
||||
(await drawnWhole('Set 2 variables')) &&
|
||||
(await drawnWhole('Get 2 variables')),
|
||||
JSON.stringify(shut),
|
||||
);
|
||||
await shot('02b-collapsed-titles');
|
||||
const narrow = (await json(`__gm.graph.nodeRect('vp-get')`)).w;
|
||||
await clickLastSet();
|
||||
const switched = await titleOf('vp-get');
|
||||
check(
|
||||
'switching one to Set while collapsed retitles it and resizes it to the new title',
|
||||
switched === 'Set vy' &&
|
||||
(await drawnWhole('Set vy')) &&
|
||||
(await json(`__gm.graph.nodeRect('vp-get')`)).w < narrow,
|
||||
JSON.stringify({ switched, narrow }),
|
||||
);
|
||||
await undo();
|
||||
await sleep(300);
|
||||
await toggle('vp-set');
|
||||
await toggle('vp-get');
|
||||
const open = [await titleOf('vp-set'), await titleOf('vp-get')];
|
||||
check(
|
||||
'expanded again, both are plain Variables nodes',
|
||||
open.join() === 'Variables,Variables',
|
||||
JSON.stringify(open),
|
||||
);
|
||||
|
||||
// 23g. A Pack keeps declaring its own fields, but a variable that already carries the shape can
|
||||
// hand it over. A color field arrives as a number port – the graph has no colors.
|
||||
await mutate(`
|
||||
const a = __gm.state.project.assets.find((x) => x.id === 'vp-logic');
|
||||
@@ -232,7 +278,7 @@ export async function variableNodes(t) {
|
||||
await sleep(300);
|
||||
check('one undo takes all of them back', (await portsOf('vp-pack')).length === 0);
|
||||
|
||||
// 23g. A list of structs declares the shape of its items, which is the bundle a Pack builds for it.
|
||||
// 23h. A list of structs declares the shape of its items, which is the bundle a Pack builds for it.
|
||||
await click(from.x, from.y);
|
||||
await sleep(200);
|
||||
await clickLast('shapes (item)');
|
||||
@@ -246,7 +292,7 @@ export async function variableNodes(t) {
|
||||
await undo();
|
||||
await sleep(300);
|
||||
|
||||
// 23h. A behavior's own inputs are not fields of a bundle, so the helper stays out of that section.
|
||||
// 23i. A behavior's own inputs are not fields of a bundle, so the helper stays out of that section.
|
||||
await mutate(`
|
||||
__gm.state.project.assets.find((x) => x.id === 'vp-logic').graph.nodes.push(
|
||||
${JSON.stringify(node('vp-start', 'BehaviorStart', 560, 600))},
|
||||
@@ -262,7 +308,7 @@ export async function variableNodes(t) {
|
||||
JSON.stringify(helper),
|
||||
);
|
||||
|
||||
// 23i. From the palette the node comes empty; picking a variable titles it, and switched to Set
|
||||
// 23j. From the palette the node comes empty; picking a variable keeps its title, and switched to Set
|
||||
// it runs `vz = vz + 1` once a frame – its own output feeding its input via Add.
|
||||
const nodeIds = async () => (await asset('vp-logic')).graph.nodes.map((n) => n.id);
|
||||
const idsBefore = await nodeIds();
|
||||
@@ -278,7 +324,6 @@ export async function variableNodes(t) {
|
||||
const added = (await asset('vp-logic')).graph.nodes.find((n) => !idsBefore.includes(n.id));
|
||||
check('the palette offers the Variables node', added?.type === 'Variables', JSON.stringify(added));
|
||||
const variableId = added?.id ?? '';
|
||||
const titleOf = (id) => json(`__gm.graph.nodeLabel(${JSON.stringify(id)})`);
|
||||
const untitled = await titleOf(variableId);
|
||||
const bare = !(await portAt(variableId, 'exec', false));
|
||||
await clickLast('+ Variable');
|
||||
@@ -286,8 +331,8 @@ export async function variableNodes(t) {
|
||||
await sleep(300);
|
||||
await clickLastSet();
|
||||
check(
|
||||
'it starts without pins, and picking its variable makes that the title',
|
||||
untitled === 'Variables' && bare && (await titleOf(variableId)) === 'vz',
|
||||
'it starts without pins, and picking its variable leaves the title Variables',
|
||||
untitled === 'Variables' && bare && (await titleOf(variableId)) === 'Variables',
|
||||
JSON.stringify({ untitled, bare, titled: await titleOf(variableId) }),
|
||||
);
|
||||
check('switched to Set it grows its flow pins', Boolean(await portAt(variableId, 'exec', false)));
|
||||
|
||||
Reference in new issue
Block a user