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
@@ -79,9 +79,9 @@ export class PlaySession {
|
||||
this.host.gameView.setWorld(world);
|
||||
this.host.showGame();
|
||||
this.state.setNotice(
|
||||
world.firstOfType('camera')
|
||||
world.activeCamera()
|
||||
? 'Playing · edits are not saved · Esc stops'
|
||||
: 'This scene has no camera – nothing is rendered · Esc stops',
|
||||
: 'No camera is switched on – nothing is rendered · Esc stops',
|
||||
);
|
||||
if (world.stopRequested) this.stop();
|
||||
}
|
||||
|
||||
+17
-3
@@ -3,7 +3,7 @@ import { newId } from '../core/ids';
|
||||
import type { Asset } from '../core/model/Asset';
|
||||
import { isPlaceableType } from '../core/model/AssetTypes';
|
||||
import { bakeInstances, materializeInstance } from '../core/model/instance';
|
||||
import { findObject } from '../core/model/hierarchy';
|
||||
import { findObject, treeOrder } from '../core/model/hierarchy';
|
||||
import { descendantsBelow } from '../core/model/walk';
|
||||
import { findAsset, findScene, type Project } from '../core/model/Project';
|
||||
import { createSceneObject, type SceneObject } from '../core/model/SceneObject';
|
||||
@@ -274,8 +274,22 @@ export class World {
|
||||
return this.entities.find((e) => e.name === name);
|
||||
}
|
||||
|
||||
firstOfType(type: Entity['type']): Entity | undefined {
|
||||
return this.entities.find((e) => e.type === type);
|
||||
/**
|
||||
* The camera the game is seen through: of the cameras that are switched on (itself and every
|
||||
* parent, see `properties/enabled.ts`) the first one in hierarchy order. Undefined while none
|
||||
* is on, and then nothing is rendered – switching one off is how a scene hands the view over.
|
||||
*/
|
||||
activeCamera(): Entity | undefined {
|
||||
const on = this.entities.filter((e) => e.type === 'camera' && isHandleEnabled(e));
|
||||
if (on.length < 2) return on[0];
|
||||
// Ranked only when the order can decide something, since this runs per frame.
|
||||
const scene = findScene(this.project, this.sceneId);
|
||||
const order = scene ? treeOrder(scene).map(({ object }) => object.id) : [];
|
||||
const rank = (camera: Entity) => {
|
||||
const index = order.indexOf(camera.objectId);
|
||||
return index < 0 ? order.length : index;
|
||||
};
|
||||
return on.reduce((first, camera) => (rank(camera) < rank(first) ? camera : first));
|
||||
}
|
||||
|
||||
/** Removes an entity and, recursively, everything parented to it. */
|
||||
|
||||
@@ -36,12 +36,17 @@ export class GameViewport extends WorldViewport {
|
||||
}
|
||||
|
||||
protected override currentView(): View | null {
|
||||
const camera = this.playWorld?.firstOfType('camera');
|
||||
const camera = this.playWorld?.activeCamera();
|
||||
return camera ? cameraView(camera, this.w, this.h) : null;
|
||||
}
|
||||
|
||||
/** `camera`: object id of the camera the view is through, empty when none is switched on. */
|
||||
override debugInfo(): { rendering: boolean; visibleItems: number; camera: string } {
|
||||
return { ...super.debugInfo(), camera: this.playWorld?.activeCamera()?.objectId ?? '' };
|
||||
}
|
||||
|
||||
protected override collectFrame(): Frame {
|
||||
// Only reached with a view, which requires a world with a camera.
|
||||
// Only reached with a view, which requires a world with a switched-on camera.
|
||||
return this.playWorld ? collectWorldItems(this.playWorld) : { items: [], background: LETTERBOX_COLOR };
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user