The game tab held a "Press Play" hint where the picture belongs. It now previews the scene through the active camera, and says "No active camera" when none is switched on. Camera choice and its world position moved into activeCamera.ts so both are testable without Pixi. Entity.x/.y are parent-relative; the viewport used them as the camera's spot, which framed a parented camera at the wrong place.
72 lines
2.8 KiB
TypeScript
72 lines
2.8 KiB
TypeScript
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 });
|
|
});
|
|
});
|