Skip to content
MotionActor
Esc
↑↓navigate↵open⌘Jpreview
On this page

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;
}

Was this page helpful?