import {TimelineKeyframe} from '../index.js';
/**
* Creates timelines.
*
* @example
*
* const timeline = new Timeline(keyframes);
* timeline.seekTimecode(0);
* timeline.tick(timetick);
*/
class Timeline {
/**
* Stores the keyframes.
* @type {Array<TimelineKeyframe>}
* @private
*/
$keyframes;
/**
* Stores the timecode.
* @type {number}
* @private
*/
$timecode;
/**
* Gets the keyframes.
* @type {Array<TimelineKeyframe>}
* @public
*/
get keyframes() {
return this.$keyframes;
}
/**
* Gets the timecode.
* @type {number}
* @public
*/
get timecode() {
return this.$timecode;
}
/**
* Creates a new timeline.
* @param {Array<TimelineKeyframe>} [$keyframes] The keyframes.
*/
constructor($keyframes = []) {
this.$keyframes = [...$keyframes].sort(($a, $b) => ($a.timecode - $b.timecode));
this.$timecode = 0;
}
/**
* Adds the given timeline.
* @param {Timeline} $timeline The timeline to add.
* @param {number} $timecode The timecode offset of the timeline to add.
* @public
*/
addTimeline($timeline, $timecode) {
this.$keyframes = this.$keyframes
.concat($timeline.clone().offset($timecode).keyframes)
.sort(($a, $b) => ($a.timecode - $b.timecode));
}
/**
* Clones the timeline.
* @returns {Timeline}
* @public
*/
clone() {
return new Timeline(this.$keyframes.map(($keyframe) => {
return $keyframe.clone();
}));
}
/**
* Adds a timecode offset.
* @param {number} $timecode The timecode offset to add.
* @returns {this}
* @public
*/
offset($timecode) {
this.$keyframes = this.$keyframes.map(($keyframe) => {
return $keyframe.offset($timecode);
});
return this;
}
/**
* Seeks to the first keyframe with the given name.
* @param {string} $name The name of the keyframe to seek to.
* @returns {this}
* @public
*/
seekName($name) {
const result = this.$keyframes.find(($keyframe) => ($keyframe.name === $name));
if (typeof result !== 'undefined') {
this.seekTimecode(result.timecode);
}
return this;
}
/**
* Seeks to the given timecode.
* @param {number} $timecode The timecode to seek to (in ms).
* @returns {this}
* @public
*/
seekTimecode($timecode) {
this.$timecode = $timecode;
this.$keyframes.forEach(($keyframe) => {
if ($keyframe.timecode !== this.$timecode) {
return;
}
$keyframe.onEnter(this);
});
return this;
}
/**
* Updates the timeline by one tick update.
* @param {number} $timetick The tick duration (in ms).
* @returns {this}
* @public
*/
tick($timetick) {
if ($timetick === 0) {
return this;
}
const previous = this.$timecode;
this.$timecode += $timetick;
const current = this.$timecode;
this.$keyframes.forEach(($keyframe) => {
if ($keyframe.timecode <= previous) {
return;
}
if ($keyframe.timecode > current) {
return;
}
$keyframe.onEnter(this);
});
return this;
}
}
export {
Timeline
};
export default Timeline;