phaser/src/tweens/TweenManager.js
2018-06-26 23:19:14 +01:00

675 lines
15 KiB
JavaScript

/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
var Class = require('../utils/Class');
var NumberTweenBuilder = require('./builders/NumberTweenBuilder');
var PluginCache = require('../plugins/PluginCache');
var TimelineBuilder = require('./builders/TimelineBuilder');
var TWEEN_CONST = require('./tween/const');
var TweenBuilder = require('./builders/TweenBuilder');
/**
* @classdesc
* [description]
*
* @class TweenManager
* @memberOf Phaser.Tweens
* @constructor
* @since 3.0.0
*
* @param {Phaser.Scene} scene - [description]
*/
var TweenManager = new Class({
initialize:
function TweenManager (scene)
{
/**
* [description]
*
* @name Phaser.Tweens.TweenManager#scene
* @type {Phaser.Scene}
* @since 3.0.0
*/
this.scene = scene;
/**
* [description]
*
* @name Phaser.Tweens.TweenManager#systems
* @type {Phaser.Scenes.Systems}
* @since 3.0.0
*/
this.systems = scene.sys;
/**
* [description]
*
* @name Phaser.Tweens.TweenManager#timeScale
* @type {number}
* @default 1
* @since 3.0.0
*/
this.timeScale = 1;
/**
* [description]
*
* @name Phaser.Tweens.TweenManager#_add
* @type {array}
* @private
* @since 3.0.0
*/
this._add = [];
/**
* [description]
*
* @name Phaser.Tweens.TweenManager#_pending
* @type {array}
* @private
* @since 3.0.0
*/
this._pending = [];
/**
* [description]
*
* @name Phaser.Tweens.TweenManager#_active
* @type {array}
* @private
* @since 3.0.0
*/
this._active = [];
/**
* [description]
*
* @name Phaser.Tweens.TweenManager#_destroy
* @type {array}
* @private
* @since 3.0.0
*/
this._destroy = [];
/**
* [description]
*
* @name Phaser.Tweens.TweenManager#_toProcess
* @type {integer}
* @private
* @default 0
* @since 3.0.0
*/
this._toProcess = 0;
scene.sys.events.once('boot', this.boot, this);
scene.sys.events.on('start', this.start, this);
},
/**
* This method is called automatically, only once, when the Scene is first created.
* Do not invoke it directly.
*
* @method Phaser.Tweens.TweenManager#boot
* @private
* @since 3.5.1
*/
boot: function ()
{
this.systems.events.once('destroy', this.destroy, this);
},
/**
* This method is called automatically by the Scene when it is starting up.
* It is responsible for creating local systems, properties and listening for Scene events.
* Do not invoke it directly.
*
* @method Phaser.Tweens.TweenManager#start
* @private
* @since 3.5.0
*/
start: function ()
{
var eventEmitter = this.systems.events;
eventEmitter.on('preupdate', this.preUpdate, this);
eventEmitter.on('update', this.update, this);
eventEmitter.once('shutdown', this.shutdown, this);
this.timeScale = 1;
},
/**
* Create a Tween Timeline and return it, but do NOT add it to the active or pending Tween lists.
*
* @method Phaser.Tweens.TweenManager#createTimeline
* @since 3.0.0
*
* @param {object} config - [description]
*
* @return {Phaser.Tweens.Timeline} [description]
*/
createTimeline: function (config)
{
return TimelineBuilder(this, config);
},
/**
* Create a Tween Timeline and add it to the active Tween list/
*
* @method Phaser.Tweens.TweenManager#timeline
* @since 3.0.0
*
* @param {object} config - [description]
*
* @return {Phaser.Tweens.Timeline} [description]
*/
timeline: function (config)
{
var timeline = TimelineBuilder(this, config);
if (!timeline.paused)
{
this._add.push(timeline);
this._toProcess++;
}
return timeline;
},
/**
* Create a Tween and return it, but do NOT add it to the active or pending Tween lists.
*
* @method Phaser.Tweens.TweenManager#create
* @since 3.0.0
*
* @param {object} config - [description]
*
* @return {Phaser.Tweens.Tween} [description]
*/
create: function (config)
{
return TweenBuilder(this, config);
},
/**
* Create a Tween and add it to the active Tween list.
*
* @method Phaser.Tweens.TweenManager#add
* @since 3.0.0
*
* @param {object} config - [description]
*
* @return {Phaser.Tweens.Tween} [description]
*/
add: function (config)
{
var tween = TweenBuilder(this, config);
this._add.push(tween);
this._toProcess++;
return tween;
},
/**
* Add an existing tween into the active Tween list.
*
* @method Phaser.Tweens.TweenManager#existing
* @since 3.0.0
*
* @param {Phaser.Tweens.Tween} tween - [description]
*
* @return {Phaser.Tweens.TweenManager} This Tween Manager object.
*/
existing: function (tween)
{
this._add.push(tween);
this._toProcess++;
return this;
},
/**
* Create a Tween and add it to the active Tween list.
*
* @method Phaser.Tweens.TweenManager#addCounter
* @since 3.0.0
*
* @param {object} config - [description]
*
* @return {Phaser.Tweens.Tween} [description]
*/
addCounter: function (config)
{
var tween = NumberTweenBuilder(this, config);
this._add.push(tween);
this._toProcess++;
return tween;
},
/**
* [description]
*
* @method Phaser.Tweens.TweenManager#preUpdate
* @since 3.0.0
*/
preUpdate: function ()
{
if (this._toProcess === 0)
{
// Quick bail
return;
}
var list = this._destroy;
var active = this._active;
var i;
var tween;
// Clear the 'destroy' list
for (i = 0; i < list.length; i++)
{
tween = list[i];
// Remove from the 'active' array
var idx = active.indexOf(tween);
if (idx !== -1)
{
tween.state = TWEEN_CONST.REMOVED;
active.splice(idx, 1);
}
}
list.length = 0;
// Process the addition list
// This stops callbacks and out of sync events from populating the active array mid-way during the update
list = this._add;
for (i = 0; i < list.length; i++)
{
tween = list[i];
if (tween.state === TWEEN_CONST.PENDING_ADD)
{
// Return true if the Tween should be started right away, otherwise false
if (tween.init())
{
tween.play();
this._active.push(tween);
}
else
{
this._pending.push(tween);
}
}
}
list.length = 0;
this._toProcess = 0;
},
/**
* [description]
*
* @method Phaser.Tweens.TweenManager#update
* @since 3.0.0
*
* @param {number} timestamp - [description]
* @param {number} delta - [description]
*/
update: function (timestamp, delta)
{
// Process active tweens
var list = this._active;
var tween;
// Scale the delta
delta *= this.timeScale;
for (var i = 0; i < list.length; i++)
{
tween = list[i];
// If Tween.update returns 'true' then it means it has completed,
// so move it to the destroy list
if (tween.update(timestamp, delta))
{
this._destroy.push(tween);
this._toProcess++;
}
}
},
/**
* [description]
*
* @method Phaser.Tweens.TweenManager#makeActive
* @since 3.0.0
*
* @param {Phaser.Tweens.Tween} tween - [description]
*
* @return {Phaser.Tweens.TweenManager} This Tween Manager object.
*/
makeActive: function (tween)
{
if (this._add.indexOf(tween) !== -1 || this._active.indexOf(tween) !== -1)
{
return;
}
var idx = this._pending.indexOf(tween);
if (idx !== -1)
{
this._pending.splice(idx, 1);
}
this._add.push(tween);
tween.state = TWEEN_CONST.PENDING_ADD;
this._toProcess++;
return this;
},
/**
* Passes all Tweens to the given callback.
*
* @method Phaser.Tweens.TweenManager#each
* @since 3.0.0
*
* @param {function} callback - [description]
* @param {object} [scope] - [description]
* @param {...*} [args] - [description]
*/
each: function (callback, scope)
{
var args = [ null ];
for (var i = 1; i < arguments.length; i++)
{
args.push(arguments[i]);
}
for (var texture in this.list)
{
args[0] = this.list[texture];
callback.apply(scope, args);
}
},
/**
* [description]
*
* @method Phaser.Tweens.TweenManager#getAllTweens
* @since 3.0.0
*
* @return {Phaser.Tweens.Tween[]} [description]
*/
getAllTweens: function ()
{
var list = this._active;
var output = [];
for (var i = 0; i < list.length; i++)
{
output.push(list[i]);
}
return output;
},
/**
* [description]
*
* @method Phaser.Tweens.TweenManager#getGlobalTimeScale
* @since 3.0.0
*
* @return {number} [description]
*/
getGlobalTimeScale: function ()
{
return this.timeScale;
},
/**
* [description]
*
* @method Phaser.Tweens.TweenManager#getTweensOf
* @since 3.0.0
*
* @param {(object|array)} target - [description]
*
* @return {Phaser.Tweens.Tween[]} [description]
*/
getTweensOf: function (target)
{
var list = this._active;
var tween;
var output = [];
var i;
if (Array.isArray(target))
{
for (i = 0; i < list.length; i++)
{
tween = list[i];
for (var t = 0; t < target.length; t++)
{
if (tween.hasTarget(target[t]))
{
output.push(tween);
}
}
}
}
else
{
for (i = 0; i < list.length; i++)
{
tween = list[i];
if (tween.hasTarget(target))
{
output.push(tween);
}
}
}
return output;
},
/**
* [description]
*
* @method Phaser.Tweens.TweenManager#isTweening
* @since 3.0.0
*
* @param {object} target - [description]
*
* @return {boolean} [description]
*/
isTweening: function (target)
{
var list = this._active;
var tween;
for (var i = 0; i < list.length; i++)
{
tween = list[i];
if (tween.hasTarget(target) && tween.isPlaying())
{
return true;
}
}
return false;
},
/**
* [description]
*
* @method Phaser.Tweens.TweenManager#killAll
* @since 3.0.0
*
* @return {Phaser.Tweens.TweenManager} [description]
*/
killAll: function ()
{
var tweens = this.getAllTweens();
for (var i = 0; i < tweens.length; i++)
{
tweens[i].stop();
}
return this;
},
/**
* [description]
*
* @method Phaser.Tweens.TweenManager#killTweensOf
* @since 3.0.0
*
* @param {(object|array)} target - [description]
*
* @return {Phaser.Tweens.TweenManager} [description]
*/
killTweensOf: function (target)
{
var tweens = this.getTweensOf(target);
for (var i = 0; i < tweens.length; i++)
{
tweens[i].stop();
}
return this;
},
/**
* [description]
*
* @method Phaser.Tweens.TweenManager#pauseAll
* @since 3.0.0
*
* @return {Phaser.Tweens.TweenManager} [description]
*/
pauseAll: function ()
{
var list = this._active;
for (var i = 0; i < list.length; i++)
{
list[i].pause();
}
return this;
},
/**
* [description]
*
* @method Phaser.Tweens.TweenManager#resumeAll
* @since 3.0.0
*
* @return {Phaser.Tweens.TweenManager} [description]
*/
resumeAll: function ()
{
var list = this._active;
for (var i = 0; i < list.length; i++)
{
list[i].resume();
}
return this;
},
/**
* [description]
*
* @method Phaser.Tweens.TweenManager#setGlobalTimeScale
* @since 3.0.0
*
* @param {number} value - [description]
*
* @return {Phaser.Tweens.TweenManager} [description]
*/
setGlobalTimeScale: function (value)
{
this.timeScale = value;
return this;
},
/**
* The Scene that owns this plugin is shutting down.
* We need to kill and reset all internal properties as well as stop listening to Scene events.
*
* @method Phaser.Tweens.TweenManager#shutdown
* @since 3.0.0
*/
shutdown: function ()
{
this.killAll();
this._add = [];
this._pending = [];
this._active = [];
this._destroy = [];
this._toProcess = 0;
var eventEmitter = this.systems.events;
eventEmitter.off('preupdate', this.preUpdate, this);
eventEmitter.off('update', this.update, this);
eventEmitter.off('shutdown', this.shutdown, this);
},
/**
* The Scene that owns this plugin is being destroyed.
* We need to shutdown and then kill off all external references.
*
* @method Phaser.Tweens.TweenManager#destroy
* @since 3.0.0
*/
destroy: function ()
{
this.shutdown();
this.scene.sys.events.off('start', this.start, this);
this.scene = null;
this.systems = null;
}
});
PluginCache.register('TweenManager', TweenManager, 'tweens');
module.exports = TweenManager;