Let a behavior hear the end of an animation it played itself
A behavior that played an animation on the parent of its owner never heard it finish. On animation finished listened to the owner and to what stands below it, and the parent stands above. - Play animation notes on the player which behavior asked for it. - On animation finished hears, as before, every animation on the owner or below it, and now also every animation the behavior played itself, on whatever object. Its output object names that object. - Two behaviors that both played the same animation on the same object each hear its end once. - A behavior that is called by Run behavior or heard by an On node counts as the behavior it sits in. - The description of the node and the engine prompt say so. Tests: - Gate on melektaus-atx: 218 files, 3392 tests, CHECK EXIT 0. - Two new unit tests: the behavior hears the animation on the parent of its owner while a bystander does not, and two starters hear it once each. - Both counter-probes bite. - e2e 6,17-26 on melektaus-atx: 480 checks, all pass. - No new e2e check, and nothing was looked at in the browser. The rule for called and heard behaviors has no test of its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7dd3ae1131
commit
d6fd000160
7 files changed
+76
-6
No files matched your search
@@ -1307,6 +1307,58 @@ describe('the animation nodes', () => {
|
||||
expect(listening('other').done).toBe(0);
|
||||
});
|
||||
|
||||
/**
|
||||
* Two arms below a box, a behavior on each. The first plays `walk` on the box, its owner's parent;
|
||||
* the second only listens, or plays it too. Both count `On animation finished`.
|
||||
*/
|
||||
function above(second: 'listens' | 'plays too', times = 8) {
|
||||
const f = makeSpriteScene();
|
||||
const box = place(f, f.spriteId, { x: 0, y: 0 });
|
||||
const walk = addAnimation(f, f.spriteId, { fps: 10, playback: 'once' });
|
||||
addRow(f, walk, 'x', [
|
||||
[0, 0],
|
||||
[2, 20],
|
||||
]);
|
||||
const counts = (name: string, plays: boolean) => {
|
||||
const arm = place(f, f.spriteId, { x: 0, y: 0 }, box);
|
||||
const behavior = makeBehavior(f, name, ['done']);
|
||||
place(f, behavior.id, { x: 0, y: 0 }, arm);
|
||||
const edit = graphEditor(f, behavior);
|
||||
const finished = edit.addNode('OnAnimationFinished');
|
||||
const store = edit.variables(['done'], { write: true });
|
||||
const add = edit.addNode('Add', { b: 1 });
|
||||
edit.wire([
|
||||
[finished, 'exec', store, 'exec'],
|
||||
[store, 'done', add, 'a'],
|
||||
[add, 'result', store, 'done'],
|
||||
]);
|
||||
if (!plays) return;
|
||||
const start = edit.addNode('OnStart');
|
||||
const owner = edit.addNode('Owner');
|
||||
const parent = edit.addNode('Parent');
|
||||
const play = edit.addNode('PlayAnimation', { animation: walk.id });
|
||||
edit.wire([
|
||||
[start, 'exec', play, 'exec'],
|
||||
[owner, 'object', parent, 'object'],
|
||||
[parent, 'parent', play, 'object'],
|
||||
]);
|
||||
};
|
||||
counts('First', true);
|
||||
counts('Second', second === 'plays too');
|
||||
const { world, frame } = startWorld(f, { animations: true, behaviors: true });
|
||||
for (let i = 0; i < times; i++) frame(0.1);
|
||||
const done = world.entities.filter((e) => e.type === 'behavior').map((e) => e.props.done);
|
||||
return { done, x: world.findByObjectId(box)!.x };
|
||||
}
|
||||
|
||||
it('hears an animation it played on the parent of its owner, and a bystander does not', () => {
|
||||
expect(above('listens')).toEqual({ done: [1, 0], x: 20 });
|
||||
});
|
||||
|
||||
it('is heard by each behavior that played it, once', () => {
|
||||
expect(above('plays too')).toEqual({ done: [1, 1], x: 20 });
|
||||
});
|
||||
|
||||
it('passes Blend on to the player it starts (#106)', () => {
|
||||
const f = makeSpriteScene();
|
||||
const box = place(f, f.spriteId, { x: 0, y: 0 });
|
||||
|
||||
Reference in new issue
Block a user