import { describe, expect, it } from 'vitest'; import { CreateAssetCommand } from '../../src/core/commands/assetCommands'; import { SetOverrideCommand } from '../../src/core/commands/sceneObjectCommands'; import { cameraOfItems, cameraOfWorld } from '../../src/viewport/activeCamera'; import { collectHolderItems } from '../../src/viewport/items'; import { makeSpriteScene, place, startWorld } from '../helpers'; 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)), /** What the game view frames while not playing. */ preview: () => cameraOfItems(collectHolderItems(fixture.project, fixture.sceneOf(), 0).items), }; } describe('the camera the game view frames', () => { it('previews through the very camera that playing would use', () => { 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); const playedThrough = () => world.activeCamera()?.objectId; expect(f.preview()?.id).toBe(first); expect(playedThrough()).toBe(first); f.switchOff(first); world.syncFromModel(); expect(f.preview()?.id).toBe(second); expect(playedThrough()).toBe(second); f.switchOff(second); world.syncFromModel(); expect(f.preview()).toBeNull(); expect(world.activeCamera()).toBeUndefined(); }); it('shows nothing rather than a switched-off camera, parents counted', () => { const f = sceneWithCamera(); const holder = place(f, f.spriteId, { x: 0, y: 0 }); const cam = place(f, f.cameraId, { x: 0, y: 0 }, holder); expect(f.preview()?.id).toBe(cam); f.switchOff(holder); expect(f.preview()).toBeNull(); }); it('has no camera to frame while the scene holds none', () => { const f = sceneWithCamera(); place(f, f.spriteId, { x: 0, y: 0 }); expect(f.preview()).toBeNull(); }); it('places a nested camera at its world position, not at its offset below the parent', () => { const f = sceneWithCamera(); const holder = place(f, f.spriteId, { x: 300, y: 200 }); const cam = place(f, f.cameraId, { x: 320, y: 210 }, holder); const { world } = startWorld(f); // The entity's own coordinates are the offset; framing by them would put the view on the parent. const entity = world.activeCamera()!; expect({ x: entity.x, y: entity.y }).toEqual({ x: 20, y: 10 }); expect(cameraOfWorld(world)).toMatchObject({ id: cam, x: 320, y: 210 }); expect(f.preview()).toMatchObject({ id: cam, x: 320, y: 210 }); }); });