Let Spawn take an asset over an edge and find a child by name (#237)
An asset could only be picked as a setting on the Spawn node. It could not be wired in, held in a variable or put into a list. Finding an object below the own one needed a scene-wide search by name. - "Asset" is now a kind like Animation or Sound: port, variable, list item and a new "Asset" literal node, with its own cube icon. - Spawn and Is asset have an `asset` input. It uses the key of the old setting, so a saved asset reads as the value of the input and older projects keep spawning without a migration. - New node "Child by name" searches below an object level by level. A child wins over a grandchild of the same name. Nothing found or no object gives null. Tests: - ./check.sh: 168 files, 2453 tests, CHECK EXIT 0. - 9 new unit tests in tests/core/asset-kind.test.ts, catalog cases for Spawn, Is asset, Child by name and the literal. - e2e 6z-ii (2 checks): node rows and a real drag of the literal onto `asset`. e2e 6: 119 checks passed. Spawn checks in 3 and 9 passed. - Counter-checks: depth-first search fails 1, Spawn reading only the old setting fails 3, runtime ignoring the parent fails 1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1b3cb625a3
commit
923baf2557
18 files changed
+345
-24
No files matched your search
@@ -1053,6 +1053,51 @@ export async function graph(t) {
|
||||
await mutate(`
|
||||
const p = __gm.state.project;
|
||||
p.assets = p.assets.filter((a) => a.id !== 'picky');
|
||||
`);
|
||||
|
||||
// 6z-ii. An asset is a value (#237): Spawn keeps a pick saved as its old setting as the inline
|
||||
// value of its new `asset` input, an Asset literal plugs into that input, and Child by
|
||||
// name shows its two inputs.
|
||||
await mutate(`
|
||||
const p = __gm.state.project;
|
||||
p.assets.push({
|
||||
id: 'spawny',
|
||||
type: 'behavior',
|
||||
name: 'Spawny',
|
||||
props: { enabled: true, runInEditor: false },
|
||||
variables: [],
|
||||
graph: {
|
||||
nodes: [
|
||||
{ id: 'sp-spawn', type: 'Spawn', x: 300, y: 0, params: { asset: 'crate' } },
|
||||
{ id: 'sp-lit', type: 'Asset', x: 0, y: 0, params: { value: 'crate' } },
|
||||
{ id: 'sp-child', type: 'ChildByName', x: 300, y: 300, params: {} },
|
||||
],
|
||||
edges: [],
|
||||
},
|
||||
});
|
||||
__gm.state.select({ kind: 'asset', assetId: 'spawny' });
|
||||
`);
|
||||
await showTab('graph');
|
||||
const spawnRows = await json(`__gm.graph.nodeInputs('sp-spawn')`);
|
||||
const childRows = await json(`__gm.graph.nodeInputs('sp-child')`);
|
||||
check(
|
||||
'Spawn shows the asset saved before as its input; Child by name shows object and name',
|
||||
JSON.stringify(spawnRows) ===
|
||||
JSON.stringify(['', 'asset Crate', 'x 0', 'y 0', 'z 0', 'parent (null)']) &&
|
||||
JSON.stringify(childRows) === JSON.stringify(['object (null)', 'name (empty)']),
|
||||
JSON.stringify({ spawnRows, childRows }),
|
||||
);
|
||||
await wire('sp-lit', 'value', 'sp-spawn', 'asset');
|
||||
const assetEdge = (await asset('spawny')).graph.edges.find((e) => e.to.node === 'sp-spawn');
|
||||
check(
|
||||
'an Asset literal connects to the asset input of Spawn',
|
||||
assetEdge?.from.node === 'sp-lit' && assetEdge.to.port === 'asset',
|
||||
JSON.stringify(assetEdge ?? null),
|
||||
);
|
||||
await shot('21-asset-input');
|
||||
await mutate(`
|
||||
const p = __gm.state.project;
|
||||
p.assets = p.assets.filter((a) => a.id !== 'spawny');
|
||||
__gm.state.select({ kind: 'asset', assetId: 'mover' });
|
||||
`);
|
||||
|
||||
|
||||
Reference in new issue
Block a user