File: ../src/Aspect.js
(function(ArtemiJS) {
'use strict';
/**
* An Aspects is used by systems as a matcher against entities, to check if a system is
* interested in an entity. Aspects define what sort of component types an entity must
* possess, or not possess.
*
* This creates an aspect where an entity must possess A and B and C:
* Aspect.getAspectForAll(A.class, B.class, C.class)
*
* This creates an aspect where an entity must possess A and B and C, but must not possess U or V.
* Aspect.getAspectForAll(A.class, B.class, C.class).exclude(U.class, V.class)
*
* This creates an aspect where an entity must possess A and B and C, but must not possess U or V, but must possess one of X or Y or Z.
* Aspect.getAspectForAll(A.class, B.class, C.class).exclude(U.class, V.class).one(X.class, Y.class, Z.class)
*
* You can create and compose aspects in many ways:
* Aspect.getEmpty().one(X.class, Y.class, Z.class).all(A.class, B.class, C.class).exclude(U.class, V.class)
* is the same as:
* Aspect.getAspectForAll(A.class, B.class, C.class).exclude(U.class, V.class).one(X.class, Y.class, Z.class)
*
* @module ArtemiJS
* @class Aspect
* @constructor
*/
var Aspect = function() {
/**
* @private
* @property allSet
* @type {ArtemiJS.Utils.Bag}
*/
var allSet = new ArtemiJS.Utils.Bag(),
/**
* @private
* @property exclusionSet
* @type {ArtemiJS.Utils.Bag}
*/
exclusionSet = new ArtemiJS.Utils.Bag(),
/**
* @private
* @property exclusionSet
* @type {ArtemiJS.Utils.Bag}
*/
oneSet = new ArtemiJS.Utils.Bag();
/**
* @method getAllSet
* @return {ArtemiJS.Utils.Bag}
*/
this.getAllSet = function() {
return allSet;
};
/**
* @method getExclusionSet
* @return {ArtemiJS.Utils.Bag}
*/
this.getExclusionSet = function() {
return exclusionSet;
};
/**
* @method getOneSet
* @return {ArtemiJS.Utils.Bag}
*/
this.getOneSet = function() {
return oneSet;
};
/**
* Returns an aspect where an entity must possess all of the specified component types.
*
* @method all
* @chainable
* @param {String} type* a required component type
*/
this.all = function(type) {
allSet.set(ArtemiJS.ComponentType.getIndexFor(type));
var len = arguments.length;
while(len--) {
allSet.set(ArtemiJS.ComponentType.getIndexFor(arguments[len]));
}
return this;
};
/**
* Excludes all of the specified component types from the aspect. A system will not be
* interested in an entity that possesses one of the specified exclusion component types.
*
* @method exclude
* @chainable
* @param {String} type* component type to exclude
*/
this.exclude = function(type) {
exclusionSet.set(ArtemiJS.ComponentType.getIndexFor(type));
var len = arguments.length;
while(len--) {
exclusionSet.set(ArtemiJS.ComponentType.getIndexFor(arguments[len]));
}
return this;
};
/**
* Returns an aspect where an entity must possess one of the specified component types.
*
* @method one
* @chainable
* @param {String} type* one of the types the entity must possess
*/
this.one = function(type) {
oneSet.set(ArtemiJS.ComponentType.getIndexFor(type));
var len = arguments.length;
while(len--) {
oneSet.set(ArtemiJS.ComponentType.getIndexFor(arguments[len]));
}
return this;
};
/**
* Creates an aspect where an entity must possess all of the specified component types.
*
* @method getAspectForAll
* @param {String} type* a required component type
* @return {ArtemiJS.Aspect} an aspect that can be matched against entities
*/
this.getAspectForAll = function(type) {
var aspect = new Aspect();
aspect.all(type, arguments);
return aspect;
};
/**
* Creates an aspect where an entity must possess one of the specified component types.
*
* @method getAspectForOne
* @param {String} type* one of the types the entity must possess
* @return {ArtemiJS.Aspect} an aspect that can be matched against entities
*/
this.getAspectForOne = function(type) {
var aspect = new Aspect();
aspect.one(type, arguments);
return aspect;
};
/**
* Creates and returns an empty aspect. This can be used if you want a system that processes no entities, but
* still gets invoked. Typical usages is when you need to create special purpose systems for debug rendering,
* like rendering FPS, how many entities are active in the world, etc.
*
* You can also use the all, one and exclude methods on this aspect, so if you wanted to create a system that
* processes only entities possessing just one of the components A or B or C, then you can do:
* Aspect.getEmpty().one(A,B,C);
*
* @method getEmpty
* @return {ArtemiJS.Aspect} an empty Aspect that will reject all entities.
*/
this.getEmpty = function() {
return new Aspect();
};
};
ArtemiJS.Aspect = Aspect;
})(window.ArtemiJS || {});