sam-ecs
Version:
A specialized entity component system
272 lines (224 loc) • 8.77 kB
JavaScript
'use strict';
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
//ProcessorManager.js//
/**
* @description - Manages the processors in the ECS
* @author - Sam Faulkner
*/
var Dict = require('collections/dict.js'),
Set = require('collections/set.js'),
SortedSet = require('collections/sorted-set.js');
var ProcessorManager = function () {
function ProcessorManager(stateManager) {
_classCallCheck(this, ProcessorManager);
if (!stateManager) throw new TypeError("StateManager must be defined!");
this._stateManager = stateManager;
var _this = this;
this._processorsOrder = new SortedSet([], function (first, second) {
return first.order == second.order;
}, function (first, second) {
return first.order - second.order;
});
this._processors = new Dict();
this._processorOrder = 0;
this._stateManager._entities.addMapChangeListener(function (value, key, map) {
// entity was removed was deleted
if (!value) {
_this._processors.forEach(function (processorValue, processorKey) {
if (processorValue.get('cachedEntityList').has(key)) {
_this.fetchCachedList(processorValue.get('name'));
}
});
}
// entity was added
else {
_this._processors.forEach(function (processorValue, processorKey) {
if (processorValue.get('object').getComponentNames().testEntity(value.get('object')) ||
//the entity removed one of its components
processorValue.get('cachedEntityList').has(key)) {
_this.fetchCachedList(processorValue.get('name'));
}
});
}
}, 'entities', false);
}
/**
* @description - Gets the processor set
* @returns {Set} the set of processors
*/
_createClass(ProcessorManager, [{
key: 'getProcessors',
value: function getProcessors() {
return this._processors;
}
/**
* @description - Gets the processor order set
* @returns {Set} the sorted set of processor objects that
* are used to determine the processor order
*/
}, {
key: 'getProcessorOrder',
value: function getProcessorOrder() {
return this._processorsOrder;
}
/**
* @description - Adds a processor to the processor manager
* @param {Processor} processor - the processor to be added
*/
}, {
key: 'addProcessor',
value: function addProcessor(processor) {
var addToOrder = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
this._processors.set(processor.getName(), new Dict({
'name': processor.getName(),
'order': ++this._processorOrder,
'object': processor,
'cachedEntityList': new Set()
}));
/* in case we would want a processor to be updated seperately
* (like a RenderProcessor) we don't always add it to the update order
*/
if (addToOrder) {
this._processorsOrder.add({
'name': processor.getName(),
'order': this._processorOrder
});
}
this.fetchCachedList(processor.getName());
}
/**
* @description - Gets the entities that belong to the family of entites
* the processor has defined
* @param {String} processorName - the name of the processor to fetch entites
* for
*/
}, {
key: 'fetchCachedList',
value: function fetchCachedList(processorName) {
if (!this._processors.has(processorName)) {
throw new TypeError("Can't fetch an entity list for an untracked processor: '" + processorName + "'!");
}
var _this = this,
processorObject = this._processors.get(processorName),
list = new Set(this._stateManager.getEntitySet().toArray()),
sorted = false;
if (processorObject.has('sorter')) {
sorted = true;
list = new SortedSet(list.toArray(), function (first, second) {
return first === second;
}, function (first, second) {
return processorObject.get('sorter')(first, second, _this._stateManager);
});
}
var family = processorObject.get('object').getComponentNames();
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = family.getHaves().toArray()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var component = _step.value;
if (!this._stateManager.hasComponent(component)) {
processorObject.set('cachedEntityList', new Set());
return;
}
list = list.intersection(this._stateManager.getEntitiesByComponent(component));
if (list.length <= 0) break;
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
if (list.length > 0) {
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = family.getCannotHaves().toArray()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var component = _step2.value;
if (this._stateManager.hasComponent(component)) {
list = list.difference(this._stateManager.getEntitiesByComponent(component));
}
if (list.length <= 0) break;
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
}
processorObject.set('cachedEntityList', list);
}
/**
* @description - Removes a processor from the processor manager
* @param {Processor} processor - the processor to be removed
*/
}, {
key: 'removeProcessor',
value: function removeProcessor(processor) {
if (this._processors.has(processor.getName())) {
this._processorsOrder.remove({
'name': processor.getName(),
'order': this._processors.get(processor.getName()).get('order')
});
this._processors.delete(processor.getName());
}
}
/**
* @description - Updates all the processors this manager has
*/
}, {
key: 'update',
value: function update() {
var _this = this;
this._processorsOrder.forEach(function (value, index) {
_this.updateProcessor(value.name);
});
}
/**
* @description - Updates a single processor
* @param {String} processorName - the name of the processor to update
*/
}, {
key: 'updateProcessor',
value: function updateProcessor(processorName) {
var processorObject = this._processors.get(processorName);
processorObject.get('object').update(processorObject.get('cachedEntityList'));
}
/**
* @description - Adds a sorter for the entities to be processed
* by a given processor
*/
}, {
key: 'addSorterForProcessor',
value: function addSorterForProcessor(sorter, processorName) {
if (!this._processors.has(processorName)) {
throw new TypeError("Can't add a sorting function for processor: '" + processorName + "'!");
}
var processorObject = this._processors.get(processorName);
processorObject.set('sorter', sorter);
this.fetchCachedList(processorName);
}
}]);
return ProcessorManager;
}();
module.exports = ProcessorManager;