@motion-script/core / Scene
Class: Scene
Defined in: nodes/scene/scene-node.ts:85
A self-contained unit of a project's timeline.
A scene is not a node and is not composed. It owns a root Rect
(a viewport-sized world container) and a generator that builds into it. This
is what makes scene-level hot reloading work: each scene file is its own HMR
boundary (import scene from './scene?scene'), and a scene can be swapped in
place without rebuilding the rest of the timeline.
Authored with createScene — you never construct one directly:
// scenes/intro.tsx export default createScene(function* (stage) { stage.set({ fill: 'bg' }); stage.add(<Rect … />); yield* …; });
The runtime drives a scene through reset → bindAssets → ellapse → build → prepareLayoutAssets → layout → prepareRenderAssets → prepareAudioAssets → render → dispose, each forwarding to the root. Image/video/paint and font
assets are no longer hand-declared — they're inferred automatically from the
same render()/layout() calls (TrackRenderContext/TrackMeasureScope,
see Precomp.precompScene). prepareLayoutAssets/prepareRenderAssets
remain only for opaque async setup (e.g. Code's syntax grammar);
prepareAudioAssets is the one asset concern that's neither drawable nor a
simple async load — a playing clip's frame-ranged timeline registration.
The scene's authoring methods (add/set/to/camera/paint/sounds) all act
on its RootNode root. They're merged with a BuildStage into
the Stage a generator receives — see Scene.build.
Constructors
Constructor
new Scene(
generator):Scene
Defined in: nodes/scene/scene-node.ts:112
Parameters
generator
Returns
Scene
Properties
__sceneHotId?
optional__sceneHotId?:string
Defined in: nodes/scene/scene-node.ts:100
Stable identity of the scene's source module, stamped by the ?scene Vite
transform (the scene file's path relative to the project root). Used to
route a hot update back to the right timeline slot. undefined outside the
dev-server ?scene pipeline.
name
name:
string="Scene"
Defined in: nodes/scene/scene-node.ts:104
Human-readable name for the timeline/errors. Defaults to "Scene"; the
?scene transform overrides it with the file's basename.
root
readonlyroot:RootNode
Defined in: nodes/scene/scene-node.ts:89
The world container this scene builds into. Viewport-sized, top-level. A RootNode: a layouting Rect that also acts as the scene camera.
Accessors
align
Get Signature
get align():
Anchor
Defined in: nodes/scene/scene-node.ts:206
Alignment of the root's children within the viewport.
Returns
Set Signature
set align(
value):void
Defined in: nodes/scene/scene-node.ts:207
Parameters
value
Returns
void
assets
Get Signature
get assets():
AssetCatalog
Defined in: nodes/scene/scene-node.ts:233
The asset catalog bound to the scene (via bindAssets).
Returns
clock
Get Signature
get clock():
Readonly<NodeClock>
Defined in: nodes/scene/scene-node.ts:228
Internal timing state of the root (scene-relative clock).
Returns
Readonly<NodeClock>
fill
Get Signature
get fill():
Fill
Defined in: nodes/scene/scene-node.ts:189
The root's background fill.
Returns
Set Signature
set fill(
value):void
Defined in: nodes/scene/scene-node.ts:190
Parameters
value
Returns
void
gap
Get Signature
get gap():
GapSize
Defined in: nodes/scene/scene-node.ts:203
Spacing between the root's children along the layout's main axis. Set via stage.set({ gap }).
Returns
group
Get Signature
get group():
LayoutMode
Defined in: nodes/scene/scene-node.ts:199
The root's layout mode for children: row / column / stack.
Returns
Set Signature
set group(
value):void
Defined in: nodes/scene/scene-node.ts:200
Parameters
value
Returns
void
heading
Get Signature
get heading():
number
Defined in: nodes/scene/scene-node.ts:224
Camera view rotation in degrees (clockwise).
Returns
number
Set Signature
set heading(
value):void
Defined in: nodes/scene/scene-node.ts:225
Parameters
value
number
Returns
void
origin
Get Signature
get origin():
Vector2
Defined in: nodes/scene/scene-node.ts:220
World-space point that maps to the centre of the viewport.
Returns
Set Signature
set origin(
value):void
Defined in: nodes/scene/scene-node.ts:221
Parameters
value
Returns
void
overlay
Get Signature
get overlay():
Fill
Defined in: nodes/scene/scene-node.ts:193
The root's overlay.
Returns
Set Signature
set overlay(
value):void
Defined in: nodes/scene/scene-node.ts:194
Parameters
value
Returns
void
padding
Get Signature
get padding():
Insets
Defined in: nodes/scene/scene-node.ts:210
Inner spacing between the viewport edges and the root's children.
Returns
Set Signature
set padding(
value):void
Defined in: nodes/scene/scene-node.ts:211
Parameters
value
Returns
void
viewportSize
Get Signature
get viewportSize():
Size2D|null
Defined in: nodes/scene/scene-node.ts:124
The full viewport this scene renders its world against.
Returns
Size2D | null
zoom
Get Signature
get zoom():
number
Defined in: nodes/scene/scene-node.ts:216
Camera magnification factor. > 1 zooms in; < 1 zooms out.
Returns
number
Set Signature
set zoom(
value):void
Defined in: nodes/scene/scene-node.ts:217
Parameters
value
number
Returns
void
Methods
add()
add(
node):void
Defined in: nodes/scene/scene-node.ts:141
Add a node (or array of nodes) as a child of the scene's root.
Parameters
node
Node<NodeProps> | Node<NodeProps>[]
Returns
void
bindAssets()
bindAssets(
context):void
Defined in: nodes/scene/scene-node.ts:317
Bind the asset catalog to the scene's whole node subtree.
Parameters
context
Returns
void
bindContext()
bindContext(
context,runInit):void
Defined in: nodes/scene/scene-node.ts:327
Push inherited context (theme/data/seed/text-style and user tokens) down
the scene's whole subtree. runInit true at start-of-pass (also fires each
node's init); false for the per-frame structural re-push. Mirrors
bindAssets. See Node.bindContext.
Parameters
context
runInit
boolean
Returns
void
build()
build(
stage):FrameGenerator
Defined in: nodes/scene/scene-node.ts:292
Produce this scene's frame generator. The generator is handed a single
Stage object that exposes both surfaces: this scene's authoring
methods (add/set/to/zoomTo/sounds/…) and the build stage's
determinism (viewport/fps/random/noise/seed).
The merge is a view created with the scene as its prototype (so authoring
resolves to real Scene members) overlaid with the stage's own properties
and its methods bound to the stage (so determinism keeps the stage's
this). One view is built per build pass.
Parameters
stage
BuildStage<Scene>
Returns
dispose()
dispose():
void
Defined in: nodes/scene/scene-node.ts:380
Returns
void
ellapse()
ellapse(
totalTime):void
Defined in: nodes/scene/scene-node.ts:332
Advance the scene's clock and per-frame sampling for the whole subtree.
Parameters
totalTime
number
Returns
void
fillTo()
fillTo(
to,duration,options?):FrameGenerator
Defined in: nodes/scene/scene-node.ts:179
Animate the root fill (the scene-wide background).
Parameters
to
duration
number
options?
Returns
headingTo()
headingTo(
heading,duration,ease?):FrameGenerator
Defined in: nodes/scene/scene-node.ts:172
Animate the camera view rotation (heading) in degrees.
Parameters
heading
number
duration
number
ease?
Returns
layout()
layout(
rect,scope):void
Defined in: nodes/scene/scene-node.ts:343
Lay the scene's world out against the given (full-viewport) bounds.
Parameters
rect
scope
Returns
void
overlayTo()
overlayTo(
to,duration,options?):FrameGenerator
Defined in: nodes/scene/scene-node.ts:184
Animate the root overlay (painted over fill + children, viewport-wide).
Parameters
to
duration
number
options?
Returns
panTo()
panTo(
lookAt,duration,ease?):FrameGenerator
Defined in: nodes/scene/scene-node.ts:167
Animate the camera focus point (lookAt) — the world point at viewport centre.
Parameters
lookAt
duration
number
ease?
Returns
playSound()
playSound(
src,opts?):FrameGenerator
Defined in: nodes/scene/scene-node.ts:264
Play a sound on the scene's audio timeline. Blocks for the clip's duration.
Use as yield* stage.playSound(...) inside a scene generator.
Parameters
src
string | Sound
opts?
Omit<SoundProps, "src">
Returns
prepareAudioAssets()
prepareAudioAssets(
tracker):void
Defined in: nodes/scene/scene-node.ts:375
Collect the scene's audio-scheduling requests — nodes with a playing clip (e.g. Video) and managed sounds (startSound/ playSound). Has no layout dependency, so it can run either side of layout; kept after by convention.
Parameters
tracker
Returns
void
prepareLayoutAssets()
prepareLayoutAssets():
void
Defined in: nodes/scene/scene-node.ts:357
Fire the scene's pre-layout async setup (e.g. Code's syntax
grammar). Called before layout; fire-and-forget, see
Node.prepareLayoutAssets.
Returns
void
prepareRenderAssets()
prepareRenderAssets():
void
Defined in: nodes/scene/scene-node.ts:365
Fire the scene's pre-render async setup. Called after layout; fire-and-forget, see Node.prepareRenderAssets.
Returns
void
render()
render(
context):void
Defined in: nodes/scene/scene-node.ts:348
Render the scene's world into context.
Parameters
context
Returns
void
reset()
reset():
void
Defined in: nodes/scene/scene-node.ts:300
Clear all dynamically-added children and managed sounds, and reset the clock.
Returns
void
sample()
sample():
void
Defined in: nodes/scene/scene-node.ts:338
Seed per-frame derived state (motion) without a full ellapse.
Returns
void
set()
set(
props):void
Defined in: nodes/scene/scene-node.ts:150
Set one or more reactive props on the root container.
Parameters
props
align?
Alignment of children within the content box: a named position
('center', 'topLeft', …) or an explicit per-axis pivot Vector2
(x: -1 left … +1 right, y: -1 bottom … +1 top).
blend?
"color" | "multiply" | "screen" | "overlay" | "darken" | "lighten" | "color-dodge" | "color-burn" | "hard-light" | "soft-light" | "difference" | "exclusion" | "hue" | "saturation" | "luminosity" | "normal" | "pass-through" | (() => "color" | "multiply" | "screen" | "overlay" | "darken" | "lighten" | "color-dodge" | "color-burn" | "hard-light" | "soft-light" | "difference" | "exclusion" | "hue" | "saturation" | "luminosity" | "normal" | "pass-through")
Layer blend mode. 'pass-through' (default) does not isolate the node — its opacity scales each child/fill while they blend against the backdrop. Any other mode isolates the node and blends its flattened result against the backdrop.
bottomCenter?
Vector2 | (() => Vector2) | (() => Vector2 | (() => Vector2))
bottomLeft?
Vector2 | (() => Vector2) | (() => Vector2 | (() => Vector2))
bottomRight?
Vector2 | (() => Vector2) | (() => Vector2 | (() => Vector2))
center?
Vector2 | (() => Vector2) | (() => Vector2 | (() => Vector2))
centerLeft?
Vector2 | (() => Vector2) | (() => Vector2 | (() => Vector2))
centerRight?
Vector2 | (() => Vector2) | (() => Vector2 | (() => Vector2))
children?
NodeChildren | (() => NodeChildren)
Child nodes. A single Node, or an arbitrarily-nested array of them
— the constructor flattens nesting (.flat(Infinity)), so .map() results
can be dropped in directly as a child without spreading, like React.
clip?
boolean | (() => boolean)
When true, content drawn outside this node's outline is clipped away (see Node.clipSelf).
colSpan?
number | (() => number)
How many grid columns this child spans. Default 1.
column?
number | (() => number)
1-based column index for explicit grid placement. Undefined = auto-placed.
effects?
fill?
Background fill layer(s). Each item can be a CSS color string, a fill
prop object, an already-resolved fill, or a FillChain from the
Fills builder. Painted behind the scene's children.
flex?
number | (() => number)
Proportional share of the free space along the parent's main axis,
relative to sibling fill children (like Flutter's Expanded(flex:)).
Only meaningful when this node fills the main axis — in a row that's
width:'fill', in a column height:'fill'. Two siblings with flex 2
and 1 split the free space 2:1. Defaults to 1. Specifying flex without
an explicit width/height defaults both to 'fill'.
gap?
Spacing between children along the layout's main axis.
group?
LayoutMode | (() => LayoutMode)
Layout mode for children: flex row / column, or overlapping stack.
heading?
number | (() => number)
Rotation of the camera view in degrees (clockwise).
height?
SizeInput | (() => SizeInput)
lookAt?
World-space point that maps to the centre of the viewport.
opacity?
number | (() => number)
overlay?
Overlay layer(s) — same loose values as fill, but painted over the fill and the children (clipped to the viewport). Use for textures laid across the whole scene, e.g. a VHS-grain image or video.
padding?
Inner spacing between this node's edges and its content/children.
pivot?
Pivot point for rotation and scale. Either a named anchor ('center',
'topRight', 'bottomLeft', … — the node align vocabulary) or an explicit
Vector2: (0,0)=center, (-1,1)=top-left, (1,-1)=bottom-right. Set
automatically when an anchor positioning prop is used.
rotation?
number | (() => number)
row?
number | (() => number)
1-based row index for explicit grid placement. Undefined = auto-placed.
rowSpan?
number | (() => number)
How many grid rows this child spans. Default 1.
scale?
number | (() => number)
seed?
string | number | (() => string | number)
Origin seed for this node's Node.random source. Defaults to 0.
Set it to give the node a reproducible-but-distinct random stream without
re-seeding by hand. The constructor adopts it as random's origin, and the
runtime rebuilds the node each playback pass, so draws stay reproducible
across scrub/precomp/HMR.
size?
SizeInput | (() => SizeInput)
Sets width and height to the same value in one go. Pure sugar: at
construction time, an author-facing size is expanded into width/
height before either is applied. Explicit width or height takes
precedence over size (mirroring padding's side-vs-shorthand rule),
so { size: 200, width: 100 } yields width: 100, height: 200.
Reactive bindings and to()/set() targets both work the same as
width/height — size: 'fill', size: () => ..., or
node.to({ size: 300 }, 0.5) are all valid.
topCenter?
Vector2 | (() => Vector2) | (() => Vector2 | (() => Vector2))
topLeft?
Vector2 | (() => Vector2) | (() => Vector2 | (() => Vector2))
topRight?
Vector2 | (() => Vector2) | (() => Vector2 | (() => Vector2))
width?
SizeInput | (() => SizeInput)
x?
number | (() => number)
y?
number | (() => number)
zoom?
number | (() => number)
Camera magnification factor. Values > 1 zoom in; < 1 zoom out.
Returns
void
setViewport()
setViewport(
size):void
Defined in: nodes/scene/scene-node.ts:129
Record the full viewport (called by the playback engine).
Parameters
size
Returns
void
startSound()
startSound(
src,opts?):Sound
Defined in: nodes/scene/scene-node.ts:241
Start a sound on the scene's audio timeline without blocking, and return the Sound handle. Pair with stopSound to end playback.
Parameters
src
string | Sound
opts?
Omit<SoundProps, "src">
Returns
stopSound()
stopSound(
sound):void
Defined in: nodes/scene/scene-node.ts:255
Stop a sound started via startSound. No-op if it isn't playing.
Parameters
sound
Returns
void
to()
to(
props,duration,easing?):AnimationBuilder<RootProps>
Defined in: nodes/scene/scene-node.ts:155
Animate any root props in one call — yield* stage.to({ zoom: 2, fill: 'red' }, 1).
Parameters
props
Partial<RootProps>
duration
number
easing?
Returns
zoomTo()
zoomTo(
zoom,duration,ease?):FrameGenerator
Defined in: nodes/scene/scene-node.ts:162
Animate the camera magnification (zoom). > 1 zooms in; < 1 zooms out.
Parameters
zoom
number
duration
number