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:
rootandClaude Opus 5 committed 2026-09-09 16:13:30 +02:00
1 parent 75be133374
commit 37fff5dabf
8 files changed
+227 -13

No files matched your search

+17 -3
View File
@@ -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. */