scene_authoring library

The scene/motion authoring core — the vocabulary a generated .scene.dart is built from, plus the pure document models and the motion runtime that evaluates them.

This library is pure Dart, so a plain dart process (the fw CLI, the MCP server, a codemod) can import it and parse, edit, emit and evaluate without a Flutter engine. A test guards the import graph. The Flutter half (players, widget bridges) lives in package:flutterware/scene.dart.

Experimental. This surface still moves with the editor and is not yet a supported API.

Classes

AnimateGroup
One late final <name> = scene.<node>.animate(…) field.
Arg<T>
One parameter a widget declaration names, with the value it falls back to when a scene sets nothing.
AtExpr
BoundGroup
One group, bound to its node: the leaf writer. The group object itself is the writer identity in the fx stack, so first write fixes its position and re-writes stay put (probe M8).
BoundMotion
A motion document bound to one scene: the timeline built as a playable tree, and the pair guarded. Unplaced groups bind too — group hands them out for independent play — but only the timeline plays through apply.
ClipBlocks
Several blocks on one track — animationTime: ClipBlocks([ClipBlock(clip: 'Walk', at: 0.ms, length: 1000.ms), ClipBlock(clip: 'Run', at: 700.ms, length: 1700.ms)]) — crossfading where they overlap.
ClipTrack
What a motion file spells for a block: animationTime: ClipTrack(at: 0.ms, length: 2400.ms). A MotionTrack with the block and no keys, so the typed animate() signatures take it where they take any track.
Effect
One app-side fx writer: cosmetic, composed, never saved. Setting a property to null removes that contribution; clear removes them all.
ExternalNode
A widget from the app, placed in a scene.
ExternalWidget
What the app says about a widget a scene may place: its label, the arguments it takes, and how to make one.
FillLayer
FrameNode
ItemRef
The property reads one field of the item a repeat is drawing. Recorded against the LIST parameter rather than the closure's own name, because the closure's name is local and the binding has to outlive it.
KindNode
A node of a registered kind (SceneKind): its rows live in values, read and written by the table, and its children exist when the kind says so. A thin subclass per kind gives the file its constructor and the motion its typed animate(); everything else — the wire, the JSON, the file's arguments, copy, undo, the inspector — reads the descriptor.
LinearPaint
A gradient down the box by default, which is what a metal or a sunset face wants.
ModelNode
MotionClip
A run through a placement's clip, as one block on the timeline: from at for length, the clip's own time advancing at speed from offset — backwards when reverse. It stands on a number track (a placement's animationTime) and lowers to a straight ramp: the value at a moment is where the clip's time has got to. Past the block's end the value holds, like a track past its last key; how a time past the clip's own end reads is the placement's loop row, which wraps it.
MotionDocument
MotionKey
One keyframe. value is a double or a Color per the owning track's kind; curve is one of Curves (null = linear); paramRef is provenance — which motion parameter fed the value. The reference is the stronger of the two: an edit to the key moves the parameter's default (reconcileMotionBindings), and a save always spells the reference.
MotionSnapshot
One motion's state at a moment: opaque, made by MotionDocument.snapshot, consumed by MotionDocument.restore.
MotionTrack
A mutable track with the door the probes demanded: key values retune freely; key time moves, inserts and removes go through methods that keep the list sorted — the everyday editor drag past a neighbour would otherwise silently break the hold rule.
ParamRef
The property reads one of the scene's own parameters, by name.
ParExpr
Playable
Anything that can play: a duration and a total apply — a child before its window applies at 0, after it at its end (the hold rule, one level up). Groups, whole motions and combinators are all this one thing, which is what makes independent play the same call as playing the motion.
RadialPaint
A gradient out from a point, STRETCHED TO THE BOX: at radius 1 it reaches the edges on both axes, so on a wide headline it is an ellipse. Flutter's RadialGradient measures its radius against the shortest side instead, and on a 600×80 title that is a dot in the middle.
RepeatExpr
SceneAlignment
A point in a box, in the -1..1 space Flutter's Alignment uses — where a gradient starts and ends.
SceneArgs
An external node's arguments, read by name and by kind.
SceneBinding
Where a property's value comes from, when it is not a literal in the file. One entry per bound property in SceneNode.bindings.
SceneBindSources
What can drive key on node: the sources a bind menu offers, and whether a parameter can be made of it.
SceneChoices
The members a ScenePropKind.choice property can take and how the file spells them: NodeLayout.row, SceneFontWeight.w700.
SceneColor
An ARGB color. Files spell it Color(0xAARRGGBB) — the only accepted color spelling; the mirror carries exactly that.
SceneCorners
A node's corner radii, one per corner, clockwise from the top left.
SceneCurve
SceneCurves
The curve allowlist, as the file spells it. SceneCurves.easeOutBack in a scene file is exactly this constant — so a mistyped curve is a compile error rather than a silent fall back to linear.
SceneDefinition
What a .scene.dart class extends — the seam between a scene as Dart and a scene as a document.
SceneDocument
SceneEdges
Space inside a frame, per side.
SceneExtArgs
SceneExtTracks
The generated track object a motion carries — a slot per animatable argument, so args: {'progress': …} for a parameter the widget does not have is not refused but unwritable.
SceneFontWeight
The nine weights, file-spelled FontWeight.w<value>.
SceneGradient
The three gradients, and what they share: colours, where each one sits, and the even spread a missing position means.
SceneKey
What a key names.
SceneKind
One node kind, as the file, the wire and the editor know it.
SceneListenable
SceneMotion<T extends SceneDefinition>
What a .scene.dart motion class extends.
SceneNode
SceneNodeArgs
The generated argument object a node carries — one class per declared widget or nested scene, with a field per argument.
ScenePaint
What a pass paints with: one colour, a gradient across the box, or one of the project's own fragment shaders.
SceneParamDecl
ScenePartKey
One named part of a property's value.
SceneProp
One authorable property.
ScenePropertyKey
A property, whole: fill, fontSize, style.
ScenePropSpec
What an editor needs to know about an animatable property without a switch on its name: what it is, where it rests, how it reads, and where a slider would mean something.
SceneQuad
Four numbers that are one when they agree: edges, corners. What the property table needs to spell either as one number or four named parts.
SceneRect
A laid-out rectangle in artboard coordinates — what the renderer measured, never something a file spells.
SceneRefArgs
SceneRefNode
An instance of another scene, by class name, with that scene's parameters overridden by args.
SceneRepeat
A frame drawn once per item of a list.
SceneSnapshot
The authored half of a document at one moment. Opaque: made by SceneDocument.snapshot, consumed by SceneDocument.restore, reusable — restoring copies out of it, never hands its own nodes over.
SceneStyleField
One property a SceneTextStyle may set: the property table's name for it, and how to read it off a style.
SceneTextStyle
A text style: the text subset of the property table, as one value — what a token names and a TextNode takes as style:, so a whole typographic treatment is shared in one move.
SceneTokenDecl
SceneValue<T>
SeqExpr
ShaderPaint
A pass painted by one of the project's own fragment shaders.
ShapeNode
SolidPaint
SpeedExpr
StrokeLayer
A stroke around the glyph outline. It widens the mark without touching the metrics, which is the whole reason several passes stay registered.
StyleRef
The node takes a shared text style whole — keyed under styleBindingKey rather than any one property, because a style is several at once. Each of them stays the node's to override; see SceneTextStyle.
SurfaceNode
A placed asset whose named mesh shows the node's first child.
SweepPaint
A gradient around a point, the way a clock hand sweeps: 0° is twelve o'clock and angles run clockwise, in degrees — the unit rotate uses. Flutter's SweepGradient starts at three o'clock in radians; the renderer turns it, so the file never has to.
TextLayer
One pass over a laid-out paragraph.
TextNode
TextRun
One stretch of a paragraph, and what it differs by.
TimelineExpr
The arrangement — a pure time-transform tree over group references. A group appears at most once in the whole tree; groups it never names are library assets (independently playable, no autoplay).
Token<T>
One token as the app declares it, in a final sceneTokens = [ … ] list beside the externals: Token<SceneColor>('brand', SceneColor(0xFF…)). The type argument is what the generated SceneTokens class types the field as, and the value is its default — so the declaration file compiles before anything has been generated from it, and the generated class is derived from it, never the other way round.
TokenRef
The property reads one of the package's shared tokens, by name — the file spells tokens.brand through the scene's tokens formal.
View3DNode
What a scene file calls. The named parameters are the rows, and the common ones are every node's; the body is one map.

Enums

NodeLayout
How a frame arranges its children.
SceneBlendMode
How a pass lands on what is already there — the modes a design tool offers on a layer, by Flutter's names. normal is the engine's srcOver; the rest are spelled the same on both sides, which the bridge test pins name by name.
SceneCrossAxisAlignment
File-spelled CrossAxisAlignment.<name>; declaration order matches Flutter's, because the wire carries the index.
SceneLayerBox
What a pass's paint is laid across. A solid colour is the same either way; a gradient is not — a two-line title in gold wants the gold to run down EACH line, not once down the paragraph with the second line in its darker half.
SceneMainAxisAlignment
Same contract as SceneCrossAxisAlignment, for the main axis.
SceneParamKind
The typed hole: a constructor parameter whose default is the mockup. Declared in the file as a primary-constructor formal with a default; referenced by node properties by bare identifier. Parameters share the class namespace with node fields.
ScenePick
Where the editor finds the choices for a string row — see SceneProp.pick. Each names something in the project, and the two that depend on a model read the same node's asset row for which one.
ScenePropKind
The kinds a property's value can take. Each has one wire spelling here and one file spelling in the tool; a property's kind is what a parameter binding is checked against.
ScenePropOwner
Which node kinds carry a property.
SceneStrokeJoin
How a stroke turns a corner. Declaration order matches Flutter's, because the bridge indexes it.
SceneTextAlign
How a text sits in the box it was given. Flutter's own names, because that is what the file spells and what it becomes.
SceneTextCase
How a text's case is forced, whatever the string says. Not a Flutter property — the renderer applies it to the string — but a design tool's, and the reason a kicker can be typed in the language it reads in and still be drawn in caps.
SceneTextDecoration
The line a text carries. Flutter's TextDecoration is a set rather than an enum, so the bridge switches rather than indexing; one line is what a design tool offers and what an import brings.
SceneTextDecorationStyle
How that line is drawn; declaration order matches Flutter's, because the bridge indexes it.
SceneTokenOwner
One shared value the package declares, as the editor reads it — the name, the kind, and the value the declaration gives.
TrackKind
What a track's values are. Mirrors the scene's parameter kinds minus string — words are not tweened.

Extensions

ExternalNodeAnimate on ExternalNode
FrameNodeAnimate on FrameNode
ModelNodeAnimate on ModelNode
MotionDocumentJson on MotionDocument
MotionTimelineLayout on MotionDocument
The timeline expression, laid out: where each placed group starts and how long the whole runs. What a timeline panel draws from, and what the runtime computes for itself when it binds — the same arithmetic, kept here so the picture and the playback cannot disagree.
MotionTrackBlend on MotionTrack
MotionTrackEvaluate on MotionTrack
SceneDocumentJson on SceneDocument
SceneMillis on int
Milliseconds, so a file can write 240.ms — the only spelling the motion grammar accepts for a time.
SceneMotionPlay on SceneMotion<SceneDefinition>
A compiled motion's timeline as a playable tree, built once per motion.
SceneNodeAnimate on SceneNode
The imposed properties, animatable on every node whatever its kind.
SceneReadPlane on SceneDocument
The read plane: what a document with no constructor does instead of one.
SceneRefNodeAnimate on SceneRefNode
ShapeNodeAnimate on ShapeNode
SurfaceNodeAnimate on SurfaceNode
TextNodeAnimate on TextNode
View3DNodeAnimate on View3DNode
The typed animate() a motion file spells — the one place per kind the table cannot write, because it is a Dart signature.

Constants

imposedProps → const List<ScenePropSpec>
The imposed vocabulary: every node kind animates these.
motionReservedNames → const Set<String>
Names a motion class member may not take: the header's super field, the mandatory arrangement, and the derived copy member.
sceneArgsPrefix → const String
The prefix an argument's key carries, because its name is the child's and could be any property's.
sceneArgsProps → const List<SceneProp>
What a node that stands for something else passes it. One row, whose PARTS are the child's own parameter names — the only property whose parts this table cannot list, which is why they carry a prefix.
sceneAxesPrefix → const String
The prefix an axis's key carries, for the same reason an argument's does: the tags come from the font, not from this table.
sceneCommonProps → const List<SceneProp>
Every node's properties, in the order the file writes them.
sceneCurvesByName → const Map<String, SceneCurve>
The same thirteen by name — what JSON reads back, and what the parser resolves SceneCurves.<name> through. A test holds this list to Curves.
sceneFrameProps → const List<SceneProp>
A frame's own properties, after the common ones. children and the repeat are not here: they are structure, not values.
sceneShapeProps → const List<SceneProp>
sceneStyleProps → const List<SceneProp>
The table's STYLE SUBSET: exactly what a SceneTextStyle carries, and exactly what sceneTextStyleFields names — pinned both ways, so a row added here without a field there would be authorable and unshareable. Every one of these is spelled inside the node's one style: argument.
sceneTextOwnProps → const List<SceneProp>
What a text spells for itself, beside its style.
sceneTextProps → const List<SceneProp>
Every property a text carries, its own and its style's.
sceneTextStyleFields → const List<SceneStyleField>
styleBindingKey → const String
The key a StyleRef sits under in SceneNode.bindings — the name the file spells it with, style: tokens.title.

Properties

modelKind → SceneKind
One placed asset inside a 3D view.
final
sceneFlushScheduler ↔ void Function(void flush())
How a batch of fx writes schedules its coalesced flush. The default coalesces on a microtask — right for a headless process, where nothing frames. A Flutter process installs the frame-aligned one (post-frame callback + ensureVisualUpdate, the probed 500-writes-to-1-rebuild shape) via the bridge's installSceneFrameFlush.
getter/setter pair
sceneKinds → List<SceneKind>
Every registered kind. Seeded with the kinds the core ships as data; a package adds its own with registerSceneKind before a scene is read.
final
sceneProps → List<SceneProp>
The table, whole — the hand-written kinds' rows, plus every registered kind's.
no setter
surfaceKind → SceneKind
A placed asset with a slot: its first child is drawn onto the mesh named by mesh — or, with no asset, onto a quad one unit tall (times size) whose width follows the child's box.
final
view3dKind → SceneKind
A 3D view: an orbit camera around a target, drawing its model children.
final

Functions

animatableProps(SceneNode node) → List<ScenePropSpec>
Imposed plus the target kind's intrinsic properties, in canonical emit order.
animateNode(SceneNode node, Map<String, MotionTrack?> tracks) → AnimateGroup
The door a registered kind's typed animate() goes through — the same one the hand-written kinds use, named so it can be called from outside.
applySceneItem(SceneNode node, String list, SceneItem item) → SceneNode
Fill in one item's fields across a repeated subtree: every property bound to <list>.<field> takes that field's value. Returns node, so a copy can be made and filled in one expression.
bindableKind(SceneNode node, String prop) → SceneParamKind?
The parameter kind prop of node can read, or null when no parameter can fill it — the table's kind, seen as a parameter's. A nested scene's argument reads a parameter of the kind the child declares it; a side of a quad is a number; a list, a choice and a style are things no parameter holds.
bindRepeats(SceneDocument doc) → void
Rebuild the repeat closures of a document that was READ — parsed from source, or decoded from JSON — rather than compiled.
deepCopyNode(SceneNode node, {String rename(String)?}) → SceneNode
A deep copy of node's authored plane — every authored property, bindings and children; never fx, measured geometry or the document pointer. rename maps every name in the subtree (a duplicate needs fresh names — names are field identity, unique per scene); a snapshot passes nothing and keeps them.
getSceneProperty(SceneNode node, String prop) → Object?
Read one authored property by the name a SceneNode.bindings entry keys it under — the table's reader, with the two shapes a binding sees differently: edges as their uniform value, a nested argument at its override else the child's default.
inheritsFromStyle(SceneDocument doc, SceneNode node, String prop) → bool
Whether prop of node is what its style says — set by the style and equal to it. "Equal means inherited": there is no override flag, by decision, so a property overridden back to the style's own value is inherited again and follows the style.
instantiateScene(SceneDocument template, Map<String, Object?> args) → SceneDocument
A fresh copy of template with args applied to its parameters — what a SceneRefNode.instance is. The copy keeps the template's parameter declarations and bindings, so it can take new args later.
isSceneDefault(SceneProp p, Object? value) → bool
Whether value is what the property holds by default — the test that decides whether it is written at all.
isValidNodeName(String name) → bool
motionFromJson(Map<String, Object?> json, {required String sceneClassName, required SceneDocument scene}) → MotionDocument
The inverse of MotionDocumentJson.toJson.
playTimeline(TimelineExpr expr, {Map<AnimateGroup, BoundGroup>? into}) → Playable
An arrangement as something that plays.
propSpecFor(SceneNode node, String prop) → ScenePropSpec?
The spec for one property of one node, or null when that node does not animate it.
readSceneProps(SceneNode node, Map<String, Object?> json) → void
Every table property of node off json, the default where the key is absent — shared by the authored plane and the wire, which spell values the same way and differ only in what else they carry.
reconcileBindings(SceneDocument doc) → List<String>
Route every edit of a bound property to what it is bound to — the other half of a binding, run by the editor after each mutation.
reconcileMotionBindings(MotionDocument motion) → List<String>
The motion half of the binding rule: a key whose value moved off its parameter's default moves the default, and every other key reading that parameter follows. A key reading a parameter that is no longer declared loses the reference in the same edit, reported by group and property, rather than at save. Run by the editor after each mutation.
recordRepeat(FrameNode frame, String source) → void
Record a repeat the way a reader can: the parameter it draws from, with the cells already in place. bindRepeats turns it into the closure.
registerSceneKind(SceneKind kind) → void
resolveSceneKey(SceneNode node, String key) → SceneKey?
Which SceneKey key is on node, or null when it names nothing the node can hold.
sceneArgName(String key) → String?
The argument's own name when key names one, else null.
sceneAxisTag(String key) → String?
The axis's four-letter tag when key names one, else null.
sceneBindSources(SceneDocument doc, SceneNode node, String key) → SceneBindSources
sceneFileFromJson(Map<String, Object?> json) → ({String className, Map<String, MotionDocument> motions, SceneDocument scene})
The inverse of sceneFileToJson.
sceneFileToJson(SceneDocument doc, {required String className, Map<String, MotionDocument> motions = const {}}) → Map<String, Object?>
A whole file as data: the scene, the class it is named after, and the motions that animate it.
sceneFromJson(Map<String, Object?> json) → SceneDocument
sceneFromWire(Map<String, Object?> root) → SceneDocument
Read back what SceneDocument.toWire wrote — a PICTURE, not a document.
sceneKindByConstructor(String constructor) → SceneKind?
sceneKindNamed(String name) → SceneKind?
scenePropNamed(SceneNode node, String name) → SceneProp?
One property by name, when node carries it.
scenePropsOf(SceneNode node) → List<SceneProp>
The properties node carries, in file order: its kind's own after the common ones.
sceneValuesEqual(Object? a, Object? b) → bool
Whether two property values are the same value.
setSceneProperty(SceneNode node, String prop, Object? value) → void
Write one authored property by the name a SceneNode.bindings entry keys it under. The one place that maps a property name to a slot, so an argument and a repeated item's field land the same way.
sizeFromWire(Object? value) → double?
The inverse of sizeToWire.
sizeToWire(double? size) → Object?
A size on its way out to the wire or a file.
styleOf(SceneDocument doc, SceneNode node) → SceneTextStyle?
The shared style node takes, when it is bound to one that exists.
tokenMarker(String name) → Map<String, Object?>
The wire's stand-in for an opaque token's value in an external node's arguments — {'token': 'ctaStyle'}. The object itself cannot travel and the editor never holds it; the guest, which compiled the declaration, resolves the name at build time (bindExternals).
tokenMarkerName(Object? value) → String?
The token a marker names, or null for any other value.
videoStops({required int durationMs, required int fps}) → List<double>
The playhead positions a motion of durationMs should be rendered at to play back at fps.
writeStyle(SceneNode node, SceneTextStyle style) → void
Writes every property style sets onto node — applying a style, or resetting to it. Properties the style leaves alone are untouched.

Typedefs

ClipBlend = ({double blend, String clip, String clip2, double time, double time2})
What a placement plays at one moment: a clip and its time, a second clip and its time when two blocks overlap there, and how far across the overlap the moment is. Empty names mean the placement's own row.
ClipBlock = MotionClip
The file's word for one block among several — see ClipBlocks.
SceneItem = Map<String, Object>
One item of a list parameter: field name to value, and a value is a string or a number — the two kinds a bound property can take.
SceneWidgetBuilder = Object Function(SceneArgs args)
What an ExternalNode builds, given the args of the moment.