2019-07-30 19:35:27 +00:00
|
|
|
import { Seconds } from "../type/Units";
|
2019-05-22 04:14:43 +00:00
|
|
|
import { Timeline, TimelineEvent } from "./Timeline";
|
2019-11-21 16:04:00 +00:00
|
|
|
import { assertRange } from "./Debug";
|
2019-05-22 04:14:43 +00:00
|
|
|
|
2019-07-23 17:43:11 +00:00
|
|
|
export type BasicPlaybackState = "started" | "stopped";
|
|
|
|
export type PlaybackState = BasicPlaybackState | "paused";
|
2019-05-22 04:14:43 +00:00
|
|
|
|
|
|
|
export interface StateTimelineEvent extends TimelineEvent {
|
|
|
|
state: PlaybackState;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-09-14 20:39:18 +00:00
|
|
|
* A Timeline State. Provides the methods: `setStateAtTime("state", time)` and `getValueAtTime(time)`
|
2019-08-30 16:06:38 +00:00
|
|
|
* @param initial The initial state of the StateTimeline. Defaults to `undefined`
|
2019-05-22 04:14:43 +00:00
|
|
|
*/
|
2019-07-23 17:43:11 +00:00
|
|
|
export class StateTimeline<AdditionalOptions extends {} = {}> extends Timeline<StateTimelineEvent & AdditionalOptions> {
|
2019-05-22 04:14:43 +00:00
|
|
|
|
2019-09-04 23:18:44 +00:00
|
|
|
readonly name: string = "StateTimeline";
|
2019-08-27 17:02:31 +00:00
|
|
|
|
2019-05-22 04:14:43 +00:00
|
|
|
/**
|
2019-09-14 20:39:18 +00:00
|
|
|
* The initial state
|
2019-05-22 04:14:43 +00:00
|
|
|
*/
|
|
|
|
private _initial: PlaybackState;
|
|
|
|
|
|
|
|
constructor(initial: PlaybackState = "stopped") {
|
|
|
|
super();
|
|
|
|
this._initial = initial;
|
2019-12-14 21:11:56 +00:00
|
|
|
this.setStateAtTime(this._initial, 0);
|
2019-05-22 04:14:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-09-14 20:39:18 +00:00
|
|
|
* Returns the scheduled state scheduled before or at
|
|
|
|
* the given time.
|
2019-08-30 16:06:38 +00:00
|
|
|
* @param time The time to query.
|
|
|
|
* @return The name of the state input in setStateAtTime.
|
2019-05-22 04:14:43 +00:00
|
|
|
*/
|
2019-06-19 13:55:08 +00:00
|
|
|
getValueAtTime(time: Seconds): PlaybackState {
|
2019-05-22 04:14:43 +00:00
|
|
|
const event = this.get(time);
|
|
|
|
if (event !== null) {
|
|
|
|
return event.state;
|
|
|
|
} else {
|
|
|
|
return this._initial;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-09-14 20:39:18 +00:00
|
|
|
* Add a state to the timeline.
|
2019-07-23 17:43:11 +00:00
|
|
|
* @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.
|
2019-05-22 04:14:43 +00:00
|
|
|
*/
|
2019-07-23 17:43:11 +00:00
|
|
|
setStateAtTime(state: PlaybackState, time: Seconds, options?: AdditionalOptions): this {
|
2019-11-21 16:04:00 +00:00
|
|
|
assertRange(time, 0);
|
2019-07-23 17:43:11 +00:00
|
|
|
this.add(Object.assign({}, options, {
|
2019-05-22 04:14:43 +00:00
|
|
|
state,
|
|
|
|
time,
|
2019-07-23 17:43:11 +00:00
|
|
|
}));
|
2019-05-22 04:14:43 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-09-14 20:39:18 +00:00
|
|
|
* Return the event before the time with the given state
|
2019-08-30 16:06:38 +00:00
|
|
|
* @param state The state to look for
|
|
|
|
* @param time When to check before
|
|
|
|
* @return The event with the given state before the time
|
2019-05-22 04:14:43 +00:00
|
|
|
*/
|
2019-07-23 17:43:11 +00:00
|
|
|
getLastState(state: PlaybackState, time: number): StateTimelineEvent & AdditionalOptions | undefined {
|
2019-05-22 04:14:43 +00:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-09-14 20:39:18 +00:00
|
|
|
* Return the event after the time with the given state
|
2019-08-30 16:06:38 +00:00
|
|
|
* @param state The state to look for
|
|
|
|
* @param time When to check from
|
|
|
|
* @return The event with the given state after the time
|
2019-05-22 04:14:43 +00:00
|
|
|
*/
|
2019-07-23 17:43:11 +00:00
|
|
|
getNextState(state: PlaybackState, time: number): StateTimelineEvent & AdditionalOptions | undefined {
|
2019-05-22 04:14:43 +00:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|