2018-01-10 16:29:37 +00:00
|
|
|
var Class = require('../utils/Class');
|
2018-01-12 17:09:09 +00:00
|
|
|
var EventEmitter = require('eventemitter3');
|
2017-01-30 00:00:45 +00:00
|
|
|
|
2016-12-07 01:40:56 +00:00
|
|
|
/**
|
|
|
|
* The Data Component features a means to store pieces of data specific to a Game Object,
|
|
|
|
* search it, query it, and retrieve it.
|
|
|
|
*/
|
2017-06-30 14:47:51 +00:00
|
|
|
var Data = new Class({
|
2016-12-07 01:40:56 +00:00
|
|
|
|
2017-06-30 14:47:51 +00:00
|
|
|
initialize:
|
2017-01-30 00:00:45 +00:00
|
|
|
|
2018-01-12 18:59:01 +00:00
|
|
|
function Data (parent, eventEmitter)
|
2017-06-30 14:47:51 +00:00
|
|
|
{
|
|
|
|
this.parent = parent;
|
2016-12-07 01:40:56 +00:00
|
|
|
|
2018-01-12 18:59:01 +00:00
|
|
|
this.events = (eventEmitter) ? eventEmitter : new EventEmitter();
|
2016-12-07 01:40:56 +00:00
|
|
|
|
2017-06-30 14:47:51 +00:00
|
|
|
this.list = {};
|
2016-12-07 01:40:56 +00:00
|
|
|
|
2017-06-30 14:47:51 +00:00
|
|
|
this._beforeCallbacks = {};
|
|
|
|
this._afterCallbacks = {};
|
2016-12-07 01:40:56 +00:00
|
|
|
|
2017-06-30 14:47:51 +00:00
|
|
|
this._frozen = false;
|
|
|
|
},
|
2016-12-07 01:40:56 +00:00
|
|
|
|
|
|
|
// Retrieves the value for the given key, or undefined if it doesn't exist.
|
|
|
|
get: function (key)
|
|
|
|
{
|
|
|
|
return this.list[key];
|
|
|
|
},
|
|
|
|
|
|
|
|
getAll: function ()
|
|
|
|
{
|
|
|
|
var results = {};
|
|
|
|
|
|
|
|
for (var key in this.list)
|
|
|
|
{
|
|
|
|
results[key] = this.list[key];
|
|
|
|
}
|
|
|
|
|
|
|
|
return results;
|
|
|
|
},
|
|
|
|
|
|
|
|
query: function (search)
|
|
|
|
{
|
|
|
|
var results = {};
|
|
|
|
|
|
|
|
for (var key in this.list)
|
|
|
|
{
|
|
|
|
if (key.match(search))
|
|
|
|
{
|
|
|
|
results[key] = this.list[key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return results;
|
|
|
|
},
|
|
|
|
|
|
|
|
set: function (key, data)
|
|
|
|
{
|
|
|
|
if (this._frozen)
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
var listener;
|
|
|
|
var result;
|
|
|
|
|
|
|
|
// If there is a 'before' callback, then check it for a result
|
2017-06-30 03:32:41 +00:00
|
|
|
// This means a property can only ever have 1 callback, which isn't right - we may need more
|
|
|
|
// Dispatch event instead?
|
2016-12-07 01:40:56 +00:00
|
|
|
if (this._beforeCallbacks.hasOwnProperty(key))
|
|
|
|
{
|
|
|
|
listener = this._beforeCallbacks[key];
|
|
|
|
|
|
|
|
result = listener.callback.call(listener.scope, this.parent, key, data);
|
|
|
|
|
|
|
|
if (result !== undefined)
|
|
|
|
{
|
|
|
|
data = result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-22 00:00:26 +00:00
|
|
|
// this.events.dispatch(new Event.LOADER_START_EVENT(this));
|
2017-01-30 00:00:45 +00:00
|
|
|
|
2016-12-07 01:40:56 +00:00
|
|
|
this.list[key] = data;
|
|
|
|
|
|
|
|
// If there is a 'after' callback, then check it for a result
|
|
|
|
if (this._afterCallbacks.hasOwnProperty(key))
|
|
|
|
{
|
|
|
|
listener = this._afterCallbacks[key];
|
|
|
|
|
|
|
|
result = listener.callback.call(listener.scope, this.parent, key, data);
|
|
|
|
|
|
|
|
if (result !== undefined)
|
|
|
|
{
|
|
|
|
this.list[key] = result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
before: function (key, callback, scope)
|
|
|
|
{
|
|
|
|
if (callback === undefined)
|
|
|
|
{
|
|
|
|
// Remove entry
|
|
|
|
delete this._beforeCallbacks[key];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this._beforeCallbacks[key] = { callback: callback, scope: scope };
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
after: function (key, callback, scope)
|
|
|
|
{
|
|
|
|
if (callback === undefined)
|
|
|
|
{
|
|
|
|
// Remove entry
|
|
|
|
delete this._afterCallbacks[key];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this._afterCallbacks[key] = { callback: callback, scope: scope };
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Passes all data entries to the given callback. Stores the result of the callback.
|
|
|
|
*
|
|
|
|
* @method each
|
|
|
|
* @param {function} callback - The function to call.
|
|
|
|
* @param {object} [scope] - Value to use as `this` when executing callback.
|
|
|
|
* @param {...*} [arguments] - Additional arguments that will be passed to the callback, after the game object, key, and data.
|
|
|
|
*/
|
|
|
|
each: function (callback, scope)
|
|
|
|
{
|
|
|
|
var args = [ this.parent, null, undefined ];
|
|
|
|
|
|
|
|
for (var i = 1; i < arguments.length; i++)
|
|
|
|
{
|
|
|
|
args.push(arguments[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var key in this.list)
|
|
|
|
{
|
|
|
|
args[1] = key;
|
|
|
|
args[2] = this.list[key];
|
|
|
|
|
|
|
|
callback.apply(scope, args);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
merge: function (data, overwrite)
|
|
|
|
{
|
|
|
|
if (overwrite === undefined) { overwrite = true; }
|
|
|
|
|
|
|
|
// Merge data from another component into this one
|
|
|
|
for (var key in data)
|
|
|
|
{
|
|
|
|
if (overwrite || (!overwrite && !this.has(key)))
|
|
|
|
{
|
|
|
|
this.list[key] = data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
remove: function (key)
|
|
|
|
{
|
|
|
|
if (!this._frozen && this.has(key))
|
|
|
|
{
|
|
|
|
delete this.list[key];
|
|
|
|
|
|
|
|
this.removeListeners(key);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
removeListeners: function (key)
|
|
|
|
{
|
|
|
|
if (this._beforeCallbacks.hasOwnProperty(key))
|
|
|
|
{
|
|
|
|
delete this._beforeCallbacks[key];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._afterCallbacks.hasOwnProperty(key))
|
|
|
|
{
|
|
|
|
delete this._afterCallbacks[key];
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
// Gets the data associated with the given 'key', deletes it from this Data store, then returns it.
|
|
|
|
pop: function (key)
|
|
|
|
{
|
|
|
|
var data = undefined;
|
|
|
|
|
|
|
|
if (!this._frozen && this.has(key))
|
|
|
|
{
|
|
|
|
data = this.list[key];
|
|
|
|
|
|
|
|
delete this.list[key];
|
|
|
|
|
|
|
|
this.removeListeners(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
return data;
|
|
|
|
},
|
|
|
|
|
|
|
|
has: function (key)
|
|
|
|
{
|
|
|
|
return this.list.hasOwnProperty(key);
|
|
|
|
},
|
|
|
|
|
|
|
|
reset: function ()
|
|
|
|
{
|
|
|
|
for (var key in this.list)
|
|
|
|
{
|
|
|
|
delete this.list[key];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (key in this._beforeCallbacks)
|
|
|
|
{
|
|
|
|
delete this._beforeCallbacks[key];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (key in this._afterCallbacks)
|
|
|
|
{
|
|
|
|
delete this._afterCallbacks[key];
|
|
|
|
}
|
|
|
|
|
|
|
|
this._frozen = false;
|
2017-06-30 14:47:51 +00:00
|
|
|
},
|
2016-12-07 01:40:56 +00:00
|
|
|
|
2017-09-08 00:59:53 +00:00
|
|
|
destroy: function ()
|
|
|
|
{
|
|
|
|
this.reset();
|
|
|
|
|
|
|
|
this.parent = null;
|
|
|
|
|
|
|
|
this.events = null;
|
|
|
|
},
|
|
|
|
|
2016-12-07 01:40:56 +00:00
|
|
|
/**
|
|
|
|
* Freeze this Data component, so no changes can be written to it.
|
|
|
|
*
|
|
|
|
* @name freeze
|
|
|
|
* @property {boolean} freeze
|
|
|
|
*/
|
|
|
|
freeze: {
|
|
|
|
|
|
|
|
get: function ()
|
|
|
|
{
|
|
|
|
return this._frozen;
|
|
|
|
},
|
|
|
|
|
|
|
|
set: function (value)
|
|
|
|
{
|
|
|
|
this._frozen = (value) ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
count: {
|
|
|
|
|
|
|
|
get: function ()
|
|
|
|
{
|
|
|
|
var i = 0;
|
|
|
|
|
|
|
|
for (var key in this.list)
|
|
|
|
{
|
|
|
|
if (this.list[key] !== undefined)
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
module.exports = Data;
|