com.badlogic.ashley.core.FamilyManager Maven / Gradle / Ivy
package com.badlogic.ashley.core;
import com.badlogic.ashley.utils.ImmutableArray;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Bits;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.Pool;
import com.badlogic.gdx.utils.SnapshotArray;
class FamilyManager {
ImmutableArray entities;
private ObjectMap> families = new ObjectMap>();
private ObjectMap> immutableFamilies = new ObjectMap>();
private SnapshotArray entityListeners = new SnapshotArray(true, 16);
private ObjectMap entityListenerMasks = new ObjectMap();
private BitsPool bitsPool = new BitsPool();
private boolean notifying = false;
public FamilyManager(ImmutableArray entities) {
this.entities = entities;
}
public ImmutableArray getEntitiesFor(Family family) {
return registerFamily(family);
}
public boolean notifying() {
return notifying;
}
public void addEntityListener (Family family, int priority, EntityListener listener) {
registerFamily(family);
int insertionIndex = 0;
while (insertionIndex < entityListeners.size) {
if (entityListeners.get(insertionIndex).priority <= priority) {
insertionIndex++;
} else {
break;
}
}
// Shift up bitmasks by one step
for (Bits mask : entityListenerMasks.values()) {
for (int k = mask.length(); k > insertionIndex; k--) {
if (mask.get(k - 1)) {
mask.set(k);
} else {
mask.clear(k);
}
}
mask.clear(insertionIndex);
}
entityListenerMasks.get(family).set(insertionIndex);
EntityListenerData entityListenerData = new EntityListenerData();
entityListenerData.listener = listener;
entityListenerData.priority = priority;
entityListeners.insert(insertionIndex, entityListenerData);
}
public void removeEntityListener (EntityListener listener) {
for (int i = 0; i < entityListeners.size; i++) {
EntityListenerData entityListenerData = entityListeners.get(i);
if (entityListenerData.listener == listener) {
// Shift down bitmasks by one step
for (Bits mask : entityListenerMasks.values()) {
for (int k = i, n = mask.length(); k < n; k++) {
if (mask.get(k + 1)) {
mask.set(k);
} else {
mask.clear(k);
}
}
}
entityListeners.removeIndex(i--);
}
}
}
public void updateFamilyMembership (Entity entity) {
// Find families that the entity was added to/removed from, and fill
// the bitmasks with corresponding listener bits.
Bits addListenerBits = bitsPool.obtain();
Bits removeListenerBits = bitsPool.obtain();
for (Family family : entityListenerMasks.keys()) {
final int familyIndex = family.getIndex();
final Bits entityFamilyBits = entity.getFamilyBits();
boolean belongsToFamily = entityFamilyBits.get(familyIndex);
boolean matches = family.matches(entity) && !entity.removing;
if (belongsToFamily != matches) {
final Bits listenersMask = entityListenerMasks.get(family);
final Array familyEntities = families.get(family);
if (matches) {
addListenerBits.or(listenersMask);
familyEntities.add(entity);
entityFamilyBits.set(familyIndex);
} else {
removeListenerBits.or(listenersMask);
familyEntities.removeValue(entity, true);
entityFamilyBits.clear(familyIndex);
}
}
}
// Notify listeners; set bits match indices of listeners
notifying = true;
Object[] items = entityListeners.begin();
try {
for (int i = removeListenerBits.nextSetBit(0); i >= 0; i = removeListenerBits.nextSetBit(i + 1)) {
((EntityListenerData)items[i]).listener.entityRemoved(entity);
}
for (int i = addListenerBits.nextSetBit(0); i >= 0; i = addListenerBits.nextSetBit(i + 1)) {
((EntityListenerData)items[i]).listener.entityAdded(entity);
}
}
finally {
addListenerBits.clear();
removeListenerBits.clear();
bitsPool.free(addListenerBits);
bitsPool.free(removeListenerBits);
entityListeners.end();
notifying = false;
}
}
private ImmutableArray registerFamily(Family family) {
ImmutableArray entitiesInFamily = immutableFamilies.get(family);
if (entitiesInFamily == null) {
Array familyEntities = new Array(false, 16);
entitiesInFamily = new ImmutableArray(familyEntities);
families.put(family, familyEntities);
immutableFamilies.put(family, entitiesInFamily);
entityListenerMasks.put(family, new Bits());
for (Entity entity : entities){
updateFamilyMembership(entity);
}
}
return entitiesInFamily;
}
private static class EntityListenerData {
public EntityListener listener;
public int priority;
}
private static class BitsPool extends Pool {
@Override
protected Bits newObject () {
return new Bits();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy