Luxar Viewer API Documentation - v2026.10.19
    Preparing search index...

    Manages animation state for multiple dimensions

    Hierarchy

    Index
    • Create dimension animation manager

      Parameters

      • sceneDimsManager: SceneDimsManager

        Singleton manager for dimension state

      • animationController: AnimationController

        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.

      Returns DimensionAnimationManager

    animationStates: Map<number, DimensionAnimationState> = ...

    Animation state per dimension (sparse map)

    isRegistered: boolean = false

    Whether we've registered with AnimationController

    dimensionRanges: [number, number][] | null = null

    Cached dimension ranges for performance

    defaultLadderDepth: number | "auto" | null = config.dimensionAnimation.defaults.ladderDepth

    The detail a fresh dimension state starts with (see setDefaultLadderDepth).

    lastFrameTime: number | null = null

    Timestamp of the previous animation frame (for the frame-interval EWMA).

    frameIntervalMs: number = 0

    EWMA of rAF frame intervals in ms; 0 until two frames have been seen.

    pendingUpdates: Set<number> = ...

    Per-dimension update tracking — prevents advancing faster than data loads

    stepCount: number = 0

    Playhead steps taken so far (one per setDimensionValue); see onFrame.

    removeDimsListener: (() => void) | null = null

    Unsubscribe function for sceneDimsManager listener

    _disposing: boolean = false

    True while dispose() runs — suppresses the pause() refine re-trigger (a torn-down scene must not receive a fresh dimension update).

    sceneDimsManager: SceneDimsManager

    Singleton manager for dimension state

    animationController: AnimationController

    Controller for frame updates

    committedQuality?: () => 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.

    • Track the display's frame interval (an EWMA of rAF deltas). Deltas above MAX_FRAME_INTERVAL_MS are gaps (a stopped loop, a hidden tab), not vsync, and are ignored.

      Parameters

      • now: number

      Returns void

    • Schedule-based tick gate (#2944 A7). Ticks are due on a fixed grid (nextDue += period) rather than "one period after the frame that last ticked": the old elapsed-since-last-tick gate drifted by up to a vsync per tick, so 10 fps achieved ~9.2 and 30 fps ~23 on a 60 Hz display. A frame within half a vsync of the due time takes the tick (the nearest frame wins). When the playhead is more than a period late — a data stall, or a pending update that held the gate — the schedule resyncs from now instead of bursting catch-up ticks. Advances the schedule when it returns true.

      Parameters

      Returns boolean

    • Per-frame callback - update all active animations Called by AnimationController on each animation frame (~60 FPS)

      Returns boolean

      whether any playhead stepped this frame (a new slice is drawn). The step's dims listener also wakes the loop, so this does not change WHETHER the frame renders; it keeps the callback's contract honest.

    • Move one playhead (listeners start the data load) and count the step for onFrame — only when the value actually changed: a tick that wraps back onto the same value (a single-timepoint dim) draws no new slice.

      Parameters

      • dimIndex: number
      • value: number

      Returns void

    • Update 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.

      Parameters

      • dimIndex: number

        Dimension index to update

      • currentTime: number

        Current timestamp in milliseconds

      Returns void

    • 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.

      Parameters

      • dimIndex: number

      Returns number | null

      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).

    • The frame period (ms) of the FASTEST playing dimension (1000 / targetFPS), or null when nothing plays. The LOD registry sizes its playback aspiration against it (LODGroupRegistryDeps.getPlaybackPeriodMs).

      Returns number | null

    • 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.

      Returns number | null

    • 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.

      Returns number | "auto" | null

    • 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.

      Returns number | "auto" | null

    • 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.

      Returns number | "auto" | null

    • 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.

      Parameters

      • dimIndex: number
      • ladderDepth: number | "auto" | null

      Returns void

    • The 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.

      Parameters

      Returns number | null

    • 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.

      Parameters

      • dimIndex: number
      • stepSize: number | null

      Returns void