import { Seconds } from "../type/Units"; import { Timeline, TimelineEvent } from "./Timeline"; import { assertRange } from "./Debug"; export type BasicPlaybackState = "started" | "stopped"; export type PlaybackState = BasicPlaybackState | "paused"; export interface StateTimelineEvent extends TimelineEvent { state: PlaybackState; } /** * A Timeline State. Provides the methods: `setStateAtTime("state", time)` and `getValueAtTime(time)` * @param initial The initial state of the StateTimeline. Defaults to `undefined` */ export class StateTimeline extends Timeline { readonly name: string = "StateTimeline"; /** * The initial state */ private _initial: PlaybackState; constructor(initial: PlaybackState = "stopped") { super(); this._initial = initial; this.setStateAtTime(this._initial, 0); } /** * Returns the scheduled state scheduled before or at * the given time. * @param time The time to query. * @return The name of the state input in setStateAtTime. */ getValueAtTime(time: Seconds): PlaybackState { const event = this.get(time); if (event !== null) { return event.state; } else { return this._initial; } } /** * Add a state to the timeline. * @param state The name of the state to set. * @param time The time to query. * @param options Any additional options that are needed in the timeline. */ setStateAtTime(state: PlaybackState, time: Seconds, options?: AdditionalOptions): this { assertRange(time, 0); this.add(Object.assign({}, options, { state, time, })); return this; } /** * Return the event before the time with the given state * @param state The state to look for * @param time When to check before * @return The event with the given state before the time */ getLastState(state: PlaybackState, time: number): StateTimelineEvent & AdditionalOptions | undefined { // time = this.toSeconds(time); const index = this._search(time); for (let i = index; i >= 0; i--) { const event = this._timeline[i]; if (event.state === state) { return event; } } } /** * Return the event after the time with the given state * @param state The state to look for * @param time When to check from * @return The event with the given state after the time */ getNextState(state: PlaybackState, time: number): StateTimelineEvent & AdditionalOptions | undefined { // time = this.toSeconds(time); const index = this._search(time); if (index !== -1) { for (let i = index; i < this._timeline.length; i++) { const event = this._timeline[i]; if (event.state === state) { return event; } } } } }