package com.artemis;
import java.util.BitSet;
/**
* 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)
*
* @author Arni Arent
*
*/
public class Aspect {
private BitSet allSet;
private BitSet exclusionSet;
private BitSet oneSet;
private Aspect() {
this.allSet = new BitSet();
this.exclusionSet = new BitSet();
this.oneSet = new BitSet();
}
protected BitSet getAllSet() {
return allSet;
}
protected BitSet getExclusionSet() {
return exclusionSet;
}
protected BitSet getOneSet() {
return oneSet;
}
/**
* Returns an aspect where an entity must possess all of the specified component types.
* @param type a required component type
* @param types a required component type
* @return an aspect that can be matched against entities
*/
public Aspect all(Class<? extends Component> type, Class<? extends Component>... types) {
allSet.set(ComponentType.getIndexFor(type));
for (Class<? extends Component> t : types) {
allSet.set(ComponentType.getIndexFor(t));
}
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.
*
* @param type component type to exclude
* @param types component type to exclude
* @return an aspect that can be matched against entities
*/
public Aspect exclude(Class<? extends Component> type, Class<? extends Component>... types) {
exclusionSet.set(ComponentType.getIndexFor(type));
for (Class<? extends Component> t : types) {
exclusionSet.set(ComponentType.getIndexFor(t));
}
return this;
}
/**
* Returns an aspect where an entity must possess one of the specified component types.
* @param type one of the types the entity must possess
* @param types one of the types the entity must possess
* @return an aspect that can be matched against entities
*/
public Aspect one(Class<? extends Component> type, Class<? extends Component>... types) {
oneSet.set(ComponentType.getIndexFor(type));
for (Class<? extends Component> t : types) {
oneSet.set(ComponentType.getIndexFor(t));
}
return this;
}
/**
* Creates an aspect where an entity must possess all of the specified component types.
*
* @param type the type the entity must possess
* @param types the type the entity must possess
* @return an aspect that can be matched against entities
*
* @deprecated
* @see getAspectForAll
*/
public static Aspect getAspectFor(Class<? extends Component> type, Class<? extends Component>... types) {
return getAspectForAll(type, types);
}
/**
* Creates an aspect where an entity must possess all of the specified component types.
*
* @param type a required component type
* @param types a required component type
* @return an aspect that can be matched against entities
*/
public static Aspect getAspectForAll(Class<? extends Component> type, Class<? extends Component>... types) {
Aspect aspect = new Aspect();
aspect.all(type, types);
return aspect;
}
/**
* Creates an aspect where an entity must possess one of the specified component types.
*
* @param type one of the types the entity must possess
* @param types one of the types the entity must possess
* @return an aspect that can be matched against entities
*/
public static Aspect getAspectForOne(Class<? extends Component> type, Class<? extends Component>... types) {
Aspect aspect = new Aspect();
aspect.one(type, types);
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);
*
* @return an empty Aspect that will reject all entities.
*/
public static Aspect getEmpty() {
return new Aspect();
}
}