The object form of AudioValue — file tracks plus, optionally, a
synthesised score (issue #331’s voices/score/master, matching the
issue body’s example verbatim). bpm/beat_offset default to the
scenario’s own Scenario::bpm/Scenario::beat_offset when
absent here — see AudioConfig::as_score’s caller in rustmotion’s
encode crate, which is where that fallback is actually applied (this
crate only carries the override, it does not resolve it: Scenario
alone does not know its own bpm by the time include::resolve_includes
has consumed it — the caller captures both before that happens).
A coloured border traced along an iris mask’s moving edge. Inside the
ring is whichever scene the mask currently reveals, outside it is the one
it is covering.
Deliberately not#[derive(Deserialize)] — see
[ScenarioDe]/impl From<ScenarioDe> for Scenario just below for why:
this type needs a post-deserialize pass (propagating bpm/beat_offset/
timing/snap down onto every reachable Scene) that a plain derive
can’t express, and every call site that builds a Scenario from JSON
(loader.rs, include.rs’s own included-file loading) is outside this
workstream’s owned files this wave — the propagation has to happen
insideScenario::deserialize itself so those callers need no changes.
Scenario::audio’s wire shape (issue #331): either the legacy bare
array of file-based AudioTracks, or a single object that can carry
both file tracks and a synthesised score, mixed into one bus. Which
shape a given "audio" value is is unambiguous from its JSON kind
(array vs. object), so #[serde(untagged)] needs no help distinguishing
them.
The arbitrary silhouette a mask transition scales up from origin,
authored in the shape’s own local coordinates (whatever range its points
or path data use — a 100x100 star, a 24x24 icon glyph, anything). The
silhouette’s own bounding-box centre is what tracks origin, not a fixed
point like (0, 0), so a lopsided glyph still grows from its visual
middle. Reuses the same kind vocabulary as style.clip-path
(polygon, path) rather than inventing a second grammar for the same
idea.
The literal string "auto" — the only value SceneStart::Auto can
hold. Its own tiny externally-tagged enum so it round-trips as the bare
string "auto" (serde’s default representation for a fieldless
variant), matching every other snake_case string enum in this file.
What Scenario.snap rounds resolved times onto. Currently only the beat
grid; the variant exists so the field reads as intent ("beat") rather
than a bare boolean.