goog.provide('entitas.Group');
goog.require('entitas.utils.Signal');
goog.require('entitas.GroupEventType');
goog.require('entitas.exceptions.SingleEntityException');
/**
* @constructor
* @param matcher
*/
entitas.Group = function(matcher) {
/**
* Subscribe to Entity Addded events
* @type {entitas.utils.ISignal} */
this.onEntityAdded = null;
/**
* Subscribe to Entity Removed events
* @type {entitas.utils.ISignal} */
this.onEntityRemoved = null;
/**
* Subscribe to Entity Updated events
* @type {entitas.utils.ISignal} */
this.onEntityUpdated = null;
this._entities = {};
this._matcher = null;
this._entitiesCache = null;
this._singleEntityCache = null;
this._toStringCache = '';
this._entities = {};
this.onEntityAdded = new entitas.utils.Signal(this);
this.onEntityRemoved = new entitas.utils.Signal(this);
this.onEntityUpdated = new entitas.utils.Signal(this);
this._matcher = matcher;
}
Object.defineProperty(entitas.Group.prototype, "count", {
/**
* Count the number of entities in this group
* @type {number}
* @name entitas.Group#count */
get: function () { return Object.keys(this._entities).length; },
enumerable: true,
configurable: true
});
Object.defineProperty(entitas.Group.prototype, "matcher", {
/**
* Get the Matcher for this group
* @type {entitas.IMatcher}
* @name entitas.Group#matcher */
get: function () { return this._matcher; },
enumerable: true,
configurable: true
});
/**
* Create an Observer for the event type on this group
* @param eventType
*/
entitas.Group.prototype.createObserver = function (eventType) {
if (eventType === undefined)
eventType = GroupEventType.OnEntityAdded;
return new entitas.GroupObserver(this, eventType);
};
/**
* Handle adding and removing component from the entity without raising events
* @param entity
*/
entitas.Group.prototype.handleEntitySilently = function (entity) {
if (this._matcher.matches(entity)) {
this.addEntitySilently(entity);
}
else {
this.removeEntitySilently(entity);
}
};
/**
* Handle adding and removing component from the entity and raisieevents
* @param entity
* @param index
* @param component
*/
entitas.Group.prototype.handleEntity = function (entity, index, component) {
if (this._matcher.matches(entity)) {
this.addEntity(entity, index, component);
}
else {
this.removeEntity(entity, index, component);
}
};
/**
* Update entity and raise events
* @param entity
* @param index
* @param previousComponent
* @param newComponent
*/
entitas.Group.prototype.updateEntity = function (entity, index, previousComponent, newComponent) {
if (entity.id in this._entities) {
var onEntityRemoved = this.onEntityRemoved;
if (onEntityRemoved.active)
onEntityRemoved.dispatch(this, entity, index, previousComponent);
var onEntityAdded = this.onEntityAdded;
if (onEntityAdded.active)
onEntityAdded.dispatch(this, entity, index, newComponent);
var onEntityUpdated = this.onEntityUpdated;
if (onEntityUpdated.active)
onEntityUpdated.dispatch(this, entity, index, previousComponent, newComponent);
}
};
/**
* Add entity without raising events
* @param entity
*/
entitas.Group.prototype.addEntitySilently = function (entity) {
if (!(entity.id in this._entities)) {
this._entities[entity.id] = entity;
this._entitiesCache = null;
this._singleEntityCache = null;
entity.addRef();
}
};
/**
* Add entity and raise events
* @param entity
* @param index
* @param component
*/
entitas.Group.prototype.addEntity = function (entity, index, component) {
if (!(entity.id in this._entities)) {
this._entities[entity.id] = entity;
this._entitiesCache = null;
this._singleEntityCache = null;
entity.addRef();
var onEntityAdded = this.onEntityAdded;
if (onEntityAdded.active)
onEntityAdded.dispatch(this, entity, index, component);
}
};
/**
* Remove entity without raising events
* @param entity
*/
entitas.Group.prototype.removeEntitySilently = function (entity) {
if (entity.id in this._entities) {
delete this._entities[entity.id];
this._entitiesCache = null;
this._singleEntityCache = null;
entity.release();
}
};
/**
* Remove entity and raise events
* @param entity
* @param index
* @param component
*/
entitas.Group.prototype.removeEntity = function (entity, index, component) {
if (entity.id in this._entities) {
delete this._entities[entity.id];
this._entitiesCache = null;
this._singleEntityCache = null;
var onEntityRemoved = this.onEntityRemoved;
if (onEntityRemoved.active)
onEntityRemoved.dispatch(this, entity, index, component);
entity.release();
}
};
/**
* Check if group has this entity
*
* @param entity
* @returns boolean
*/
entitas.Group.prototype.containsEntity = function (entity) {
return entity.id in this._entities;
};
/**
* Get a list of the entities in this group
*
* @returns Array<entitas.Entity>
*/
entitas.Group.prototype.getEntities = function () {
if (this._entitiesCache == null) {
var entities = this._entities;
var keys = Object.keys(entities);
var length = keys.length;
var entitiesCache = this._entitiesCache = new Array(length);
for (var i = 0; i < length; i++) {
entitiesCache[i] = entities[keys[i]];
}
}
return this._entitiesCache;
};
/**
* Gets an entity singleton.
* If a group has more than 1 entity, this is an error condition.
*
* @returns entitas.Entity
*/
entitas.Group.prototype.getSingleEntity = function () {
if (this._singleEntityCache == null) {
var enumerator = Object.keys(this._entities);
var c = enumerator.length;
if (c === 1) {
this._singleEntityCache = this._entities[enumerator[0]];
}
else if (c === 0) {
return null;
}
else {
throw new entitas.exceptions.SingleEntityException(this._matcher);
}
}
return this._singleEntityCache;
};
/**
* Create a string representation for this group:
*
* ex: 'Group(Position)'
*
* @returns string
*/
entitas.Group.prototype.toString = function () {
if (this._toStringCache == null) {
this._toStringCache = "Group(" + this._matcher + ")";
}
return this._toStringCache;
};