Create dimension animation manager
Singleton manager for dimension state
Controller for frame updates
OptionalcommittedQuality: () => number | null
Optional probe for the worst-served laddered node's committed energy.
Supplied by the wiring in input/.../dimension-navigation/setup.ts, which
has the scene. Absent (or returning null) falls back to cadence-only
feedback, which is the honest behaviour when nothing on screen is stamped.
PrivateanimationAnimation state per dimension (sparse map)
PrivateisWhether we've registered with AnimationController
PrivatedimensionCached dimension ranges for performance
PrivatedefaultThe detail a fresh dimension state starts with (see setDefaultLadderDepth).
PrivatependingPer-dimension update tracking — prevents advancing faster than data loads
PrivateremoveUnsubscribe function for sceneDimsManager listener
Private_True while dispose() runs — suppresses the pause() refine re-trigger (a torn-down scene must not receive a fresh dimension update).
PrivatesceneSingleton manager for dimension state
PrivateanimationController for frame updates
Private OptionalcommittedOptional probe for the worst-served laddered node's committed energy.
Supplied by the wiring in input/.../dimension-navigation/setup.ts, which
has the scene. Absent (or returning null) falls back to cadence-only
feedback, which is the honest behaviour when nothing on screen is stamped.
PrivateupdateUpdate cached dimension ranges
PrivateensureRegister frame callback with animation controller Called automatically when first animation starts
PrivateonPer-frame callback - update all active animations Called by AnimationController on each animation frame (~60 FPS)
PrivateupdateUpdate a single dimension's animation
Includes frame synchronization: if a data update is still in progress, this method skips the frame to prevent advancing animation faster than data loading can keep up. This ensures complete rendering of each frame.
Dimension index to update
Current timestamp in milliseconds
PEEK the value the next playback tick would move to — loop/bounce/ backward aware, WITHOUT mutating any animation state. Used by the t+1 slice prefetcher to warm the S-cache for the upcoming tick.
The predicted next value, or null when the dimension is not playing, dims/ranges are unavailable, or the next step would STOP playback (loop mode 'once' at its boundary — nothing to prefetch).
Indices of every dimension currently playing.
Whether ANY dimension is currently playing (== getFrameBudgetMs() !== null).
Start or resume animation for a dimension
Dimension index to animate
Optionaloptions: PlayOptions
Animation options (FPS, loop mode, direction)
True if animation started, false if already playing
Pause animation for a dimension
Dimension index to pause
True if animation was paused, false if already paused
Per-tick LOD time budget for the progressive loaders, or null when no
dimension animation is playing (normal full-refinement behavior).
While playing, each update pass should finish within the animation frame
window so every tick commits a frame (see the pacing gate in
updateDimension). The budget is a fraction of the frame window of the
FASTEST currently-playing dimension (config.dimensionAnimation.playback),
floored at minBudgetMs. Read per-update by the dims listener and
threaded to the loaders as a per-pass directive — never persisted.
Playback "detail" for the current tick: the pinned additive-ladder depth
(rungs) the progressive loaders must load for every frame, or null when no
playing dimension pins one (time-budgeted streaming). With several playing
dimensions the DEEPEST pin wins — a pinned dim must never be drawn below
its setting because another dim plays on Auto. Threaded to the loaders as
ViewState.ladderDepth by updateAllNDNodes, and to the t+1 shadow
prefetch, so the next frame's S-cache entry carries the pinned prefix.
The detail a SCRUB pass (a slider drag, a keyboard step, the pause
re-trigger — any slice change while nothing plays) is pinned to: the
deepest explicit pin among all dimensions' settings, else 'auto' if any
dimension asks for it, else null. Dimensions never touched inherit
getDefaultLadderDepth. The orchestrator pins the scrub pass to it
and follows up with an unpinned settle pass once the scrub is quiet, so a
paused view still refines to the full ladder.
The detail a dimension starts with before anyone sets it: the scene's
authored viewer_config.playback_lod_depth when present, else
config.dimensionAnimation.defaults.ladderDepth. Setting it also updates
every dimension still on the previous default, so an authored value read
after the slider panel created its states still takes effect.
Set the playback detail for a dimension: a pinned additive-ladder depth
(rungs, Infinity = whole ladder) every frame is drawn at while it plays or
scrubs, 'auto' for the energy rule, or null for Fast (time-budgeted
streaming). Takes effect on the next tick.
Toggle play/pause for a dimension
Dimension index to toggle
Optionaloptions: PlayOptions
Animation options (only used if starting)
True if now playing, false if now paused
Stop animation and remove state for a dimension
Dimension index to stop
Check if a dimension is currently animating
Dimension index to check
True if animating, false otherwise
Get animation state for a dimension
Dimension index
Animation state, or undefined if not animating
Set target FPS for a dimension
Dimension index
Target FPS (clamped to valid range)
Increase speed to next preset or by increment
Dimension index
Decrease speed to previous preset or by decrement
Dimension index
PrivatecreateFresh per-dimension state seeded from config.dimensionAnimation.defaults. Single source for play()/setTargetFPS()/setLoopMode()/setStepSize() so a new default (like stepSize) cannot be forgotten at one call site.
PrivateresolveThe per-tick step handed to advanceDimensionValue: the user's explicit override when set (quantized to the authored grid for discrete dims, one cell minimum — see #1520), else the authored step for discrete dims, else null (continuous fps-derived increment). MUST be used by BOTH updateDimension and peekNextValue — the playhead and the t+1 prefetch have to agree.
Set (or clear, with null) the per-dimension step override. Drives the animation per-tick increment AND the [ / ] keyboard navigation; the slider wheel/drag deliberately stay on the dimension's own base step. Values are validated (finite, > 0) and clamped to the dimension's range width so one step can never overshoot the whole range.
The per-dimension step override, or null when on Auto / no state yet.
Set loop mode for a dimension
Dimension index
Loop mode to set
Clean up all animations and unregister from animation controller
Manages animation state for multiple dimensions