Compiled scenes
Resolving frames, reading typed exports, looking up actors, memoizing, and reflecting for editors.
CompiledScene is what createScene returns. It
holds the authored record and turns frame numbers into state.
compiled.fps; // 30
compiled.totalDuration; // authored length, in frames
Resolving a frame
const state = compiled.at(90);
// Scene exports — typed
state.scene.title;
// Camera
state.camera.zoom;
state.camera.centerX;
Typed lookup
For actors that were not exported, look them up by blueprint rather than by string type. The blueprint carries the type, so no cast is needed.
state.findActor(TextBlock); // first instance
state.findActors(TextBlock); // all instances
state.getActor("title", TextBlock); // by id, typed
Resolution options
Pass host values at resolution time rather than baking them into the scene.
const state = compiled.at(frame, {
channelValues: new Map([[createCellKey(actorId, "measuredBox"), box]]),
viewport: { width: 1920, height: 1080 },
});
channelValues overrides are per-resolution only — they never write through to the
channel publication store, which is what makes them safe to
compute inside a React render.
Memoization
memoizedScene(compiled) wraps at() with an LRU keyed on (frame, viewport) and
invalidated per channel key: publishing to channel A does not bust a cached frame that
only read channel B.
const memo = memoizedScene(compiled, { lru: 4 });
const state = memo.at(frame);
SceneRenderer uses it by default.
Reflection
compiled.reflect(frame?) returns editor-facing data — ids, types, tree structure and
signal values — without needing a typed blueprint. This is the surface an editor or an
inspector reads.
const reflection = compiled.reflect(90);
reflection.getActor("title"); // by id, untyped
ResolvedActor
What every lookup and export resolves to:
interface ResolvedActor {
id: string;
type: string;
scopeId: string;
parentId: string | null;
slotName: string | null;
slotChildren: Record<string, string[]>;
signals: Record<string, unknown>;
channels: Record<string, ResolvedChannelHandle<unknown>>;
localLayout: ResolvedLayoutBox;
worldLayout: ResolvedLayoutBox;
effects: ActiveEffect[];
spawnFrame: number;
despawnFrame?: number;
}