/**
* Animation system is consist of two powerful sub-systems:
*
* 1. Tween : a classic but better tween engine.
* 2. Action: a Blender/Flash like, keyframe based timeline animation system.
*
* @module engine/anime
*
* @requires engine/system
* @requires engine/utils/array
* @requires engine/anime/tween
* @requires engine/anime/action
*/
const System = require('engine/system');
const { removeItems } = require('engine/utils/array');
const Tween = require('./tween');
const { ActionPlayer } = require('./action');
/**
* Anime sub-system.
* @class
* @extends {System}
*/
class SystemAnime extends System {
/**
* @constructor
*/
constructor() {
super();
/**
* Name of this system.
* @type {String}
*/
this.name = 'Anime';
/**
* Animation item collection
* @type {Object}
*/
this.anims = {
'0': [],
};
/**
* Activated tags
* @type {Array}
*/
this.activeTags = ['0'];
/**
* Deactivated tags
* @type {Array}
*/
this.deactiveTags = [];
}
/**
* Overrided update.
* @memberof SystemAnime#
* @method update
* @protected
* @param {number} dt Delta time
*/
update(dt) {
let i, key, anims, t;
for (key in this.anims) {
if (this.activeTags.indexOf(key) < 0) {continue;}
anims = this.anims[key];
for (i = 0; i < anims.length; i++) {
t = anims[i];
if (!t.isRemoved) {
t._step(dt);
if (t.isRemoved) {
t.recycle();
removeItems(anims, i--, 1);
}
}
}
}
}
/**
* Pause animations with a specific tag.
* @memberof SystemAnime#
* @method pauseAnimesTagged
* @param {string} tag Tag of the animations to pause.
* @return {SystemAnime} System itself.
*/
pauseAnimesTagged(tag) {
if (this.timers[tag]) {
removeItems(this.activeTags, this.activeTags.indexOf(tag), 1);
this.deactiveTags.push(tag);
}
return this;
}
/**
* Resume animations with a specific tag.
* @memberof SystemAnime#
* @method resumeAnimesTagged
* @param {string} tag Tag of the animations to resume.
* @return {SySystemAnime} System itself.
*/
resumeAnimesTagged(tag) {
if (this.timers[tag]) {
removeItems(this.deactiveTags, this.deactiveTags.indexOf(tag), 1);
this.activeTags.push(tag);
}
return this;
}
/**
* Create a tween for an object.
* @method tween
* @memberOf SystemAnime#
* @param {Oblject} context Context of this tween.
* @param {string} [tag] Tag of this tween (default is '0').
* @return {module:engine/anime/tween~Tween} Tween instance.
*/
tween(context, tag = '0') {
if (!this.anims[tag]) {
// Create a new tween list
this.anims[tag] = [];
// Active new tag by default
this.activeTags.push(tag);
}
let tween = Tween.create(context);
this.anims[tag].push(tween);
return tween;
}
/**
* Run an action on a target object
* @memberof SystemAnime#
* @method runAction
* @param {module:engine/animation/action~Action} action Action to run
* @param {object} target Target object
* @param {string} [tag] Tag of this action player (default is '0')
* @return {module:engine/anime/action~ActionPlayer} An ActionPlayer instance that runs the specific Action
*/
runAction(action, target, tag = '0') {
if (!this.anims[tag]) {
// Create a new tween list
this.anims[tag] = [];
// Active new tag by default
this.activeTags.push(tag);
}
let player = ActionPlayer.create(action, target);
this.anims[tag].push(player);
return player;
}
}
module.exports = SystemAnime;