Until now a behavior could not move an object in front of another while the game runs. Set position writes only x and y, and z lives on the running object rather than in its props, so Properties cannot reach it either. Drawing already reads the z every frame, so only the nodes were missing. - Get Z (data): object in, z and world z out. World z is summed up with the parents, the way drawing does it (worldTransformOf). - Set Z (action): object and z in. It sets the object's own z, local to its parent like Set position. Higher is drawn in front from the next frame on. - Two nodes of their own rather than a z port on Set position and Get position, as asked. Tests: - node-catalog: Get Z for a child (2 below 5 is world z 7) and for no object, Set Z writes only z and leaves x/y. - set-z.test.ts: in a running world a key sets the lower of two sprites to z 2, drawSlots then draws it in front, Get Z logs 2 and 2. - Two counter-checks bite: Set Z without the write and Get Z without the parent fail 3 tests. - Gate: 233 files, 3548 tests (3542 + 6), CHECK EXIT 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
52 lines
2.0 KiB
TypeScript
52 lines
2.0 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { PlaceAssetCommand } from '../../src/core/commands/sceneObjectCommands';
|
|
import { drawSlots } from '../../src/viewport/drawOrder';
|
|
import { collectWorldItems } from '../../src/viewport/items';
|
|
import { graphEditor, makeBehavior, makeSpriteScene, place, startWorld } from '../helpers';
|
|
|
|
/**
|
|
* Two sprites on the same spot, "front" at z 1 and "back" at z 0. On `f` a behavior on "back" sets
|
|
* its z to 2 with `Set Z` and logs `Get Z` of it: z, then world z.
|
|
*/
|
|
function start() {
|
|
const f = makeSpriteScene();
|
|
const back = place(f, f.spriteId, { x: 0, y: 0, z: 0 });
|
|
const front = place(f, f.spriteId, { x: 0, y: 0, z: 1 });
|
|
const behavior = makeBehavior(f, 'Raise');
|
|
f.stack.execute(new PlaceAssetCommand(f.sceneId, behavior.id, { x: 0, y: 0 }, back));
|
|
const edit = graphEditor(f, behavior);
|
|
const owner = edit.addNode('Owner');
|
|
const set = edit.addNode('SetZ', { z: 2 });
|
|
edit.connect(edit.addNode('OnKeyDown', { key: 'f' }), 'exec', set, 'exec');
|
|
edit.connect(owner, 'object', set, 'object');
|
|
const get = edit.addNode('GetZ');
|
|
edit.connect(owner, 'object', get, 'object');
|
|
let from = set;
|
|
for (const output of ['z', 'worldZ']) {
|
|
const log = edit.addNode('Log');
|
|
edit.connect(get, output, log, 'message');
|
|
edit.connect(from, 'exec', log, 'exec');
|
|
from = log;
|
|
}
|
|
|
|
const started = startWorld(f, { behaviors: true });
|
|
const name = (id: string) => (id === back ? 'back' : id === front ? 'front' : id);
|
|
const order = () =>
|
|
drawSlots(collectWorldItems(started.world).items.filter((item) => item.type === 'sprite')).map((slot) =>
|
|
name(slot.id),
|
|
);
|
|
started.frame();
|
|
return { ...started, order };
|
|
}
|
|
|
|
describe('a graph changes the z of an object during the run', () => {
|
|
it('draws the object in front once Set Z has raised it, and Get Z reads the new z', () => {
|
|
const r = start();
|
|
expect(r.order()).toEqual(['back', 'front']);
|
|
r.input.press('f');
|
|
r.frame();
|
|
expect(r.order()).toEqual(['front', 'back']);
|
|
expect(r.world.log).toEqual(['2', '2']);
|
|
});
|
|
});
|