- Graph: nodes.ts split into nodes/<category>/<Type>.ts (62 files) with shared.ts factories and index.ts registry; NodeContext/values/NodeRegistry separated, writeTyped() replaces duplicated typed writes - Comments: one style (JSDoc on non-obvious exports, // for decisions and traps), wrong/stale comments fixed or removed, ids.ts now real 10 base-36 chars - Core: chainOf, shared worldPosition/editorPosition core, commands/require.ts, commands/naming.ts, util/list.ts, setBagValue/toPosition/propDef; dead code removed (isBehaviorAsset, SCENE_OBJECT_SCHEMA, CommandStack.subscribe, Input.axis, setMode, titleText, World.worldPosition, unused ctor params) - Editor: Inspector split into inspector/ sections, App.ts into Editor.ts + debugHook.ts + shortcuts.ts, Viewport into items.ts + symbols.ts, shared "Add collider" action, unified type labels/swatches - UI toolkit: Widget.trackHover/onPointerRelease, drawControlBox, math helpers, Popup.openBelow, Menu/Dialog/ColorPicker/ListRow in own files, named Theme sizes - Tools: seed-demo/smoke-demo and demo-check project removed, tools/lib (harness, projects, builders), e2e.mjs as runner over tools/e2e/*.mjs sections - Tests: tests/helpers.ts replaces copied fixtures and NodeContext doubles Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
85 lines
3.6 KiB
JavaScript
85 lines
3.6 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Writes the fixture scene tools/e2e.mjs asserts against: two top-level crates with a collider
|
|
* child each, a camera, the Mover behavior owning the red crate and a Spawner. The objects are
|
|
* uniquely named and positioned exactly where the checks expect them.
|
|
*
|
|
* Usage: PATH=/opt/node22/bin:$PATH node tools/seed-e2e.mjs [projectId] [baseUrl]
|
|
*/
|
|
import { edge, node, sceneObject, variable } from './lib/builders.mjs';
|
|
import { PROJECTS, cliArgs, writeProject } from './lib/projects.mjs';
|
|
|
|
const { projectId, baseUrl } = cliArgs('seed-e2e.mjs', PROJECTS.fixture);
|
|
|
|
/**
|
|
* "Mover" in five nodes: every frame, move the owner along the normalized arrow-key axis,
|
|
* scaled by the `speed` variable per second (On update's dt feeds the dt input). "Collide with
|
|
* solids" stops the owner's solid colliders at other solid colliders.
|
|
*/
|
|
const moverGraph = {
|
|
nodes: [
|
|
node('n-update', 'OnUpdate', 0, 0),
|
|
node('n-owner', 'Owner', 0, 120),
|
|
node('n-axis', 'AxisInput', 0, 200),
|
|
node('n-speed', 'GetVariable', 0, 400, { variable: 'speed' }),
|
|
node('n-move', 'Move', 340, 0, { collide: true }),
|
|
],
|
|
edges: [
|
|
edge('e1', 'n-update', 'exec', 'n-move', 'exec'),
|
|
edge('e6', 'n-update', 'dt', 'n-move', 'dt'),
|
|
edge('e2', 'n-owner', 'object', 'n-move', 'object'),
|
|
edge('e3', 'n-axis', 'x', 'n-move', 'dx'),
|
|
edge('e4', 'n-axis', 'y', 'n-move', 'dy'),
|
|
edge('e5', 'n-speed', 'value', 'n-move', 'scale'),
|
|
],
|
|
};
|
|
|
|
/** "Spawner": pressing Space places a new Crate at world (0, 150) and logs its name. */
|
|
const spawnerGraph = {
|
|
nodes: [
|
|
node('s-key', 'OnKeyDown', 0, 0, { key: ' ' }),
|
|
node('s-spawn', 'Spawn', 260, 0, { asset: 'crate', y: 150 }),
|
|
node('s-log', 'Log', 520, 0),
|
|
],
|
|
edges: [
|
|
edge('s-e1', 's-key', 'exec', 's-spawn', 'exec'),
|
|
edge('s-e2', 's-spawn', 'exec', 's-log', 'exec'),
|
|
edge('s-e3', 's-spawn', 'object', 's-log', 'message'),
|
|
],
|
|
};
|
|
|
|
const project = {
|
|
formatVersion: 1,
|
|
id: projectId,
|
|
name: 'E2E fixture',
|
|
activeSceneId: 'scene1',
|
|
assets: [
|
|
{
|
|
id: 'scene1',
|
|
type: 'scene',
|
|
name: 'Level 1',
|
|
props: { backgroundColor: 0x22252c },
|
|
objects: [
|
|
sceneObject('o1', 'crate', { x: -150 }),
|
|
sceneObject('o2', 'crate', { name: 'Blue crate', x: 120, y: -80, overrides: { width: 140, color: 0x4488ff } }),
|
|
sceneObject('o3', 'cam'),
|
|
// The Mover is parented to the red crate (its owner); its position is local to it.
|
|
sceneObject('o4', 'mover', { y: 110, parentId: 'o1' }),
|
|
// Both crates carry the shared collider as a centred child; the blue one is widened to
|
|
// match its 140-wide sprite override.
|
|
sceneObject('oc1', 'collider', { parentId: 'o1' }),
|
|
sceneObject('oc2', 'collider', { parentId: 'o2', overrides: { width: 140 } }),
|
|
// Top-level spawner (no owner) left of the red crate: Space spawns a crate.
|
|
sceneObject('o5', 'spawner', { x: -300 }),
|
|
],
|
|
},
|
|
{ id: 'crate', type: 'sprite', name: 'Crate', props: { width: 100, height: 60, color: 0xe0553f } },
|
|
{ id: 'cam', type: 'camera', name: 'Main camera', props: { width: 640, height: 360, zoom: 1 } },
|
|
{ id: 'collider', type: 'collider', name: 'Crate collider', props: { shape: 'box', width: 100, height: 60, radius: 50, isTrigger: false } },
|
|
{ id: 'mover', type: 'behavior', name: 'Mover', props: { speed: 200 }, variables: [variable('speed', 'number', 0)], graph: moverGraph },
|
|
{ id: 'spawner', type: 'behavior', name: 'Spawner', props: {}, variables: [], graph: spawnerGraph },
|
|
],
|
|
};
|
|
|
|
await writeProject(projectId, baseUrl, project);
|