phaser/wip/core/Signal.js

506 lines
16 KiB
JavaScript
Raw Normal View History

/**
* @author Miller Medeiros http://millermedeiros.github.com/js-signals/
2013-10-01 12:54:29 +00:00
* @author Richard Davey <rich@photonstorm.com>
2016-04-04 21:15:01 +00:00
* @copyright 2016 Photon Storm Ltd.
2013-10-01 12:54:29 +00:00
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
/**
2016-04-07 01:44:29 +00:00
* Signals are what Phaser uses to handle events and event dispatching.
* You can listen for a Signal by binding a callback / function to it.
* This is done by using either `Signal.add` or `Signal.addOnce`.
2014-11-30 23:56:20 +00:00
*
2016-04-07 01:44:29 +00:00
* For example you can listen for a touch or click event from the Input Manager
* by using its `onDown` Signal:
*
* `game.input.onDown.add(function() { ... });`
*
* Rather than inline your function, you can pass a reference:
*
* `game.input.onDown.add(clicked, this);`
* `function clicked () { ... }`
*
* In this case the second argument (`this`) is the context in which your function should be called.
*
* Now every time the InputManager dispatches the `onDown` signal (or event), your function
* will be called.
*
* Very often a Signal will send arguments to your function.
* This is specific to the Signal itself.
* If you're unsure then check the documentation, or failing that simply do:
*
* `Signal.add(function() { console.log(arguments); })`
*
* and it will log all of the arguments your function received from the Signal.
*
* Sprites have lots of default signals you can listen to in their Events class, such as:
*
* `sprite.events.onKilled`
*
2016-04-07 01:44:29 +00:00
* Which is called automatically whenever the Sprite is killed.
* There are lots of other events, see the Events component for a list.
*
* As well as listening to pre-defined Signals you can also create your own:
*
* `var mySignal = new Phaser.Signal();`
*
* This creates a new Signal. You can bind a callback to it:
*
* `mySignal.add(myCallback, this);`
*
* and then finally when ready you can dispatch the Signal:
*
* `mySignal.dispatch(your arguments);`
*
* And your callback will be invoked. See the dispatch method for more details.
*
2013-10-01 12:54:29 +00:00
* @class Phaser.Signal
* @constructor
*/
2016-04-07 01:44:29 +00:00
Phaser.Signal = function () {};
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
Phaser.Signal.prototype = {
/**
* @property {?Array.<Phaser.SignalBinding>} _bindings - Internal variable.
* @private
*/
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
_bindings: null,
2014-03-23 07:59:28 +00:00
/**
2013-11-28 15:57:09 +00:00
* @property {any} _prevParams - Internal variable.
* @private
*/
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
_prevParams: null,
/**
2014-11-30 23:56:20 +00:00
* Memorize the previously dispatched event?
*
* If an event has been memorized it is automatically dispatched when a new listener is added with {@link #add} or {@link #addOnce}.
* Use {@link #forget} to clear any currently memorized event.
*
* @property {boolean} memorize
*/
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
memorize: false,
/**
2014-03-23 07:59:28 +00:00
* @property {boolean} _shouldPropagate
* @private
*/
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
_shouldPropagate: true,
/**
2015-04-17 16:35:52 +00:00
* Is the Signal active? Only active signals will broadcast dispatched events.
2014-11-30 23:56:20 +00:00
*
* Setting this property during a dispatch will only affect the next dispatch. To stop the propagation of a signal from a listener use {@link #halt}.
*
* @property {boolean} active
2013-10-01 12:54:29 +00:00
* @default
*/
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
active: true,
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
/**
* @property {function} _boundDispatch - The bound dispatch function, if any.
* @private
*/
_boundDispatch: false,
/**
* @method Phaser.Signal#validateListener
* @param {function} listener - Signal handler function.
2013-11-28 15:57:09 +00:00
* @param {string} fnName - Function name.
* @private
*/
validateListener: function (listener, fnName) {
2014-07-02 14:25:07 +00:00
if (typeof listener !== 'function')
{
throw new Error('Phaser.Signal: listener is a required param of {fn}() and should be a Function.'.replace('{fn}', fnName));
}
2014-07-02 14:25:07 +00:00
},
/**
* @method Phaser.Signal#_registerListener
* @private
* @param {function} listener - Signal handler function.
* @param {boolean} isOnce - Should the listener only be called once?
* @param {object} [listenerContext] - The context under which the listener is invoked.
* @param {number} [priority] - The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added. (default = 0).
* @return {Phaser.SignalBinding} An Object representing the binding between the Signal and listener.
*/
_registerListener: function (listener, isOnce, listenerContext, priority, args) {
2014-07-02 14:25:07 +00:00
var prevIndex = this._indexOfListener(listener, listenerContext);
var binding;
2014-07-02 14:25:07 +00:00
if (prevIndex !== -1)
{
binding = this._bindings[prevIndex];
2014-07-02 14:25:07 +00:00
if (binding.isOnce() !== isOnce)
{
2014-03-23 08:29:04 +00:00
throw new Error('You cannot add' + (isOnce ? '' : 'Once') + '() then add' + (!isOnce ? '' : 'Once') + '() the same listener without removing the relationship first.');
}
2014-07-02 14:25:07 +00:00
}
else
{
binding = new Phaser.SignalBinding(this, listener, isOnce, listenerContext, priority, args);
this._addBinding(binding);
}
2014-07-02 14:25:07 +00:00
if (this.memorize && this._prevParams)
{
binding.execute(this._prevParams);
}
return binding;
2014-07-02 14:25:07 +00:00
},
/**
2014-03-23 07:59:28 +00:00
* @method Phaser.Signal#_addBinding
* @private
* @param {Phaser.SignalBinding} binding - An Object representing the binding between the Signal and listener.
*/
_addBinding: function (binding) {
2014-07-02 14:25:07 +00:00
if (!this._bindings)
{
this._bindings = [];
}
2014-07-02 14:25:07 +00:00
// Simplified insertion sort
var n = this._bindings.length;
2014-07-02 14:25:07 +00:00
do {
n--;
}
while (this._bindings[n] && binding._priority <= this._bindings[n]._priority);
this._bindings.splice(n + 1, 0, binding);
2014-07-02 14:25:07 +00:00
},
/**
* @method Phaser.Signal#_indexOfListener
* @private
* @param {function} listener - Signal handler function.
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
* @param {object} [context=null] - Signal handler function.
* @return {number} The index of the listener within the private bindings array.
*/
_indexOfListener: function (listener, context) {
2014-07-02 14:25:07 +00:00
if (!this._bindings)
{
return -1;
}
if (context === undefined) { context = null; }
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
2014-07-02 14:25:07 +00:00
var n = this._bindings.length;
var cur;
while (n--)
{
cur = this._bindings[n];
2014-07-02 14:25:07 +00:00
if (cur._listener === listener && cur.context === context)
{
return n;
}
}
2014-07-02 14:25:07 +00:00
return -1;
2014-07-02 14:25:07 +00:00
},
/**
2014-11-30 23:56:20 +00:00
* Check if a specific listener is attached.
2014-03-23 07:59:28 +00:00
*
* @method Phaser.Signal#has
* @param {function} listener - Signal handler function.
* @param {object} [context] - Context on which listener will be executed (object that should represent the `this` variable inside listener function).
* @return {boolean} If Signal has the specified listener.
*/
has: function (listener, context) {
2014-07-02 14:25:07 +00:00
return this._indexOfListener(listener, context) !== -1;
2014-07-02 14:25:07 +00:00
},
/**
* Add an event listener for this signal.
*
* An event listener is a callback with a related context and priority.
*
* You can optionally provide extra arguments which will be passed to the callback after any internal parameters.
*
* For example: `Phaser.Key.onDown` when dispatched will send the Phaser.Key object that caused the signal as the first parameter.
* Any arguments you've specified after `priority` will be sent as well:
*
* `fireButton.onDown.add(shoot, this, 0, 'lazer', 100);`
*
* When onDown dispatches it will call the `shoot` callback passing it: `Phaser.Key, 'lazer', 100`.
*
* Where the first parameter is the one that Key.onDown dispatches internally and 'lazer',
* and the value 100 were the custom arguments given in the call to 'add'.
2014-03-23 07:59:28 +00:00
*
* @method Phaser.Signal#add
* @param {function} listener - The function to call when this Signal is dispatched.
* @param {object} [listenerContext] - The context under which the listener will be executed (i.e. the object that should represent the `this` variable).
* @param {number} [priority] - The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added (default = 0)
* @param {...any} [args=(none)] - Additional arguments to pass to the callback (listener) function. They will be appended after any arguments usually dispatched.
* @return {Phaser.SignalBinding} An Object representing the binding between the Signal and listener.
*/
add: function (listener, listenerContext, priority) {
2014-07-02 14:25:07 +00:00
this.validateListener(listener, 'add');
2014-07-02 14:25:07 +00:00
var args = [];
if (arguments.length > 3)
{
for (var i = 3; i < arguments.length; i++)
{
args.push(arguments[i]);
}
}
return this._registerListener(listener, false, listenerContext, priority, args);
2014-07-02 14:25:07 +00:00
},
/**
2014-11-30 23:56:20 +00:00
* Add a one-time listener - the listener is automatically removed after the first execution.
*
* If there is as {@link Phaser.Signal#memorize memorized} event then it will be dispatched and
* the listener will be removed immediately.
*
* @method Phaser.Signal#addOnce
* @param {function} listener - The function to call when this Signal is dispatched.
* @param {object} [listenerContext] - The context under which the listener will be executed (i.e. the object that should represent the `this` variable).
* @param {number} [priority] - The priority level of the event listener. Listeners with higher priority will be executed before listeners with lower priority. Listeners with same priority level will be executed at the same order as they were added (default = 0)
* @param {...any} [args=(none)] - Additional arguments to pass to the callback (listener) function. They will be appended after any arguments usually dispatched.
* @return {Phaser.SignalBinding} An Object representing the binding between the Signal and listener.
*/
addOnce: function (listener, listenerContext, priority) {
2014-07-02 14:25:07 +00:00
this.validateListener(listener, 'addOnce');
2014-07-02 14:25:07 +00:00
var args = [];
if (arguments.length > 3)
{
for (var i = 3; i < arguments.length; i++)
{
args.push(arguments[i]);
}
}
return this._registerListener(listener, true, listenerContext, priority, args);
2014-07-02 14:25:07 +00:00
},
/**
2014-11-30 23:56:20 +00:00
* Remove a single event listener.
*
* @method Phaser.Signal#remove
* @param {function} listener - Handler function that should be removed.
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
* @param {object} [context=null] - Execution context (since you can add the same handler multiple times if executing in a different context).
* @return {function} Listener handler function.
*/
remove: function (listener, context) {
this.validateListener(listener, 'remove');
var i = this._indexOfListener(listener, context);
if (i !== -1)
{
this._bindings[i]._destroy(); //no reason to a Phaser.SignalBinding exist if it isn't attached to a signal
this._bindings.splice(i, 1);
}
return listener;
},
/**
2014-11-30 23:56:20 +00:00
* Remove all event listeners.
*
* @method Phaser.Signal#removeAll
* @param {object} [context=null] - If specified only listeners for the given context will be removed.
*/
removeAll: function (context) {
if (context === undefined) { context = null; }
2014-07-02 14:25:07 +00:00
if (!this._bindings)
{
return;
}
var n = this._bindings.length;
2014-07-02 14:25:07 +00:00
while (n--)
{
if (context)
{
if (this._bindings[n].context === context)
{
2014-07-03 09:50:12 +00:00
this._bindings[n]._destroy();
this._bindings.splice(n, 1);
}
}
else
{
this._bindings[n]._destroy();
}
}
2014-07-02 14:25:07 +00:00
if (!context)
{
this._bindings.length = 0;
}
2014-07-02 14:25:07 +00:00
},
/**
* Gets the total number of listeners attached to this Signal.
*
* @method Phaser.Signal#getNumListeners
2014-11-30 23:56:20 +00:00
* @return {integer} Number of listeners attached to the Signal.
*/
getNumListeners: function () {
2014-07-02 14:25:07 +00:00
return this._bindings ? this._bindings.length : 0;
2014-07-02 14:25:07 +00:00
},
/**
* Stop propagation of the event, blocking the dispatch to next listener on the queue.
2014-11-30 23:56:20 +00:00
*
2015-04-17 16:35:52 +00:00
* This should be called only during event dispatch as calling it before/after dispatch won't affect another broadcast.
2014-11-30 23:56:20 +00:00
* See {@link #active} to enable/disable the signal entirely.
*
* @method Phaser.Signal#halt
*/
halt: function () {
2014-07-02 14:25:07 +00:00
this._shouldPropagate = false;
2014-07-02 14:25:07 +00:00
},
/**
2014-11-30 23:56:20 +00:00
* Dispatch / broadcast the event to all listeners.
*
2014-11-30 23:56:20 +00:00
* To create an instance-bound dispatch for this Signal, use {@link #boundDispatch}.
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
*
* @method Phaser.Signal#dispatch
2013-11-28 15:57:09 +00:00
* @param {any} [params] - Parameters that should be passed to each handler.
*/
dispatch: function () {
if (!this.active || !this._bindings)
{
return;
}
var paramsArr = Array.prototype.slice.call(arguments);
var n = this._bindings.length;
var bindings;
if (this.memorize)
{
this._prevParams = paramsArr;
}
if (!n)
{
// Should come after memorize
return;
}
bindings = this._bindings.slice(); //clone array in case add/remove items during dispatch
this._shouldPropagate = true; //in case `halt` was called before dispatch or during the previous dispatch.
//execute all callbacks until end of the list or until a callback returns `false` or stops propagation
//reverse loop since listeners with higher priority will be added at the end of the list
2014-07-02 14:25:07 +00:00
do {
n--;
}
while (bindings[n] && this._shouldPropagate && bindings[n].execute(paramsArr) !== false);
2014-03-23 07:59:28 +00:00
},
/**
2014-11-30 23:56:20 +00:00
* Forget the currently {@link Phaser.Signal#memorize memorized} event, if any.
*
* @method Phaser.Signal#forget
*/
2014-07-02 14:25:07 +00:00
forget: function() {
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
if (this._prevParams)
{
this._prevParams = null;
}
2014-07-02 14:25:07 +00:00
},
/**
2014-11-30 23:56:20 +00:00
* Dispose the signal - no more events can be dispatched.
*
* This removes all event listeners and clears references to external objects.
* Calling methods on a disposed objects results in undefined behavior.
*
* @method Phaser.Signal#dispose
*/
dispose: function () {
2014-07-02 14:25:07 +00:00
this.removeAll();
2014-07-02 14:25:07 +00:00
this._bindings = null;
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
if (this._prevParams)
{
this._prevParams = null;
}
2014-07-02 14:25:07 +00:00
},
/**
2014-11-30 23:56:20 +00:00
* A string representation of the object.
*
* @method Phaser.Signal#toString
* @return {string} String representation of the object.
2013-10-01 12:54:29 +00:00
*/
toString: function () {
2014-07-02 14:25:07 +00:00
return '[Phaser.Signal active:'+ this.active +' numListeners:'+ this.getNumListeners() +']';
2014-07-02 14:25:07 +00:00
}
};
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
/**
2014-11-30 23:56:20 +00:00
* Create a `dispatch` function that maintains a binding to the original Signal context.
*
* Use the resulting value if the dispatch function needs to be passed somewhere
* or called independently of the Signal object.
Signal - memory optimization / reductions There are a fair amount of Signal objects created. In the current implementation these are somewhat "fat" objects for two reasons: - A closure / ad-hoc `dispatch` is created for each new Signal - this increases the retained size by 138+ bytes/Signal in Chrome. - There are a number of instance variables that never change from their default value, and the bindings array is always created, even if never used. This change "lightens" the Signals such that there is significantly less penalty for having many (unusued) signals. As an example of how much this _does_ play a role, in the "Random Sprite" demo ~2000 Signals are created, with only 12 of these signals being subscribed to. This results in a shallow size of ~300K and a retained size of ~600K (which is almost as much memory as required by the Sprites/Sprites themselves!) for .. nothing. With these changes the shallow and retained sizes are less than 50K each - and this is with only ~200 sprites! This change addresses these issues by - Changing it so there is _no_ `dispatch` closure created. This is a _breaking change_ (although there is no usage of such in core where it breaks); the code referenced "#24", but no such issue could be found on github. In the rare case that code needs to obtain a dispatch-closure, the `boundDispatch` property can be used to trivially obtain a (cached) closure. - The properties and default values are moved into the prototype; and the `_bindings` array creation is deferred. This change, coupled with the removal of the automatic closure, results in a very lightweight ~24bytes/object (in Chrome) for unbound signals. This is minor breaking change, as per the removal of the automatic closure; but no such need/usage was found in the core. (There may be cases in the examples, which were not checked.) If merely opting for the array creation delay and keeping the default properties in the prototype the shallow size is still halved; less significant but still a consideration.
2014-11-24 12:37:24 +00:00
*
* @memberof Phaser.Signal
* @property {function} boundDispatch
*/
Object.defineProperty(Phaser.Signal.prototype, "boundDispatch", {
get: function () {
var _this = this;
return this._boundDispatch || (this._boundDispatch = function () {
return _this.dispatch.apply(_this, arguments);
});
}
});
Phaser.Signal.prototype.constructor = Phaser.Signal;