Play through the first camera that is switched on
The game view took whatever camera came first in the scene, ignoring the switch, so `enabled = false` on a camera did nothing and a second camera never got its turn. `World.activeCamera()` now decides: of the cameras switched on – the whole parent chain counted, as for any object – the first in hierarchy order, and none on renders nothing at all. It is asked per frame, so a graph switching cameras hands the view over immediately. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
75be133374
commit
37fff5dabf
8 files changed
+227
-13
No files matched your search
@@ -0,0 +1,82 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { CreateAssetCommand } from '../../src/core/commands/assetCommands';
|
||||
import { SetOverrideCommand } from '../../src/core/commands/sceneObjectCommands';
|
||||
import { treeOrder } from '../../src/core/model/hierarchy';
|
||||
import { makeSpriteScene, place, startWorld } from '../helpers';
|
||||
|
||||
/** The fixture's scene with a camera asset, and switching a placed object off the way the inspector does. */
|
||||
function sceneWithCamera() {
|
||||
const fixture = makeSpriteScene();
|
||||
const camera = new CreateAssetCommand('camera', 'Cam');
|
||||
fixture.stack.execute(camera);
|
||||
return {
|
||||
...fixture,
|
||||
cameraId: camera.asset.id,
|
||||
switchOff: (objectId: string) =>
|
||||
fixture.stack.execute(new SetOverrideCommand(fixture.sceneId, objectId, 'enabled', false)),
|
||||
};
|
||||
}
|
||||
|
||||
describe('the camera the game is seen through', () => {
|
||||
it('skips a camera that is switched off, so nothing is rendered while it is the only one', () => {
|
||||
const f = sceneWithCamera();
|
||||
const cam = place(f, f.cameraId, { x: 0, y: 0 });
|
||||
const { world } = startWorld(f);
|
||||
expect(world.activeCamera()?.objectId).toBe(cam);
|
||||
|
||||
// Switching it off reaches the running world through the same sync an inspector edit uses.
|
||||
f.switchOff(cam);
|
||||
world.syncFromModel();
|
||||
expect(world.activeCamera()).toBeUndefined();
|
||||
|
||||
f.stack.undo();
|
||||
world.syncFromModel();
|
||||
expect(world.activeCamera()?.objectId).toBe(cam);
|
||||
});
|
||||
|
||||
it('is off as well when a parent above it is off', () => {
|
||||
const f = sceneWithCamera();
|
||||
const holder = place(f, f.spriteId, { x: 0, y: 0 });
|
||||
const cam = place(f, f.cameraId, { x: 0, y: 0 }, holder);
|
||||
const { world } = startWorld(f);
|
||||
expect(world.activeCamera()?.objectId).toBe(cam);
|
||||
|
||||
f.switchOff(holder);
|
||||
world.syncFromModel();
|
||||
expect(world.activeCamera()).toBeUndefined();
|
||||
});
|
||||
|
||||
it('takes the first switched-on one, and hands the view over when that one goes off', () => {
|
||||
const f = sceneWithCamera();
|
||||
const first = place(f, f.cameraId, { x: 0, y: 0 });
|
||||
const second = place(f, f.cameraId, { x: 500, y: 0 });
|
||||
const { world } = startWorld(f);
|
||||
expect(world.activeCamera()?.objectId).toBe(first);
|
||||
|
||||
f.switchOff(first);
|
||||
world.syncFromModel();
|
||||
expect(world.activeCamera()?.objectId).toBe(second);
|
||||
|
||||
// And back: the order decides again as soon as both are on.
|
||||
f.stack.undo();
|
||||
world.syncFromModel();
|
||||
expect(world.activeCamera()?.objectId).toBe(first);
|
||||
|
||||
f.switchOff(second);
|
||||
world.syncFromModel();
|
||||
expect(world.activeCamera()?.objectId).toBe(first);
|
||||
});
|
||||
|
||||
it('reads "first" in hierarchy order – what the panel shows – not in storage order', () => {
|
||||
const f = sceneWithCamera();
|
||||
const holder = place(f, f.spriteId, { x: 0, y: 0 });
|
||||
const stored = place(f, f.cameraId, { x: 500, y: 0 });
|
||||
const nested = place(f, f.cameraId, { x: 0, y: 0 }, holder);
|
||||
// The nested camera is stored last but listed first, right below its parent.
|
||||
expect(f.sceneOf().objects.map((o) => o.id)).toEqual([holder, stored, nested]);
|
||||
expect(treeOrder(f.sceneOf()).map(({ object }) => object.id)).toEqual([holder, nested, stored]);
|
||||
|
||||
const { world } = startWorld(f);
|
||||
expect(world.activeCamera()?.objectId).toBe(nested);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user