All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.artemis.systems.EntitySystem Maven / Gradle / Ivy

package com.artemis.systems;

import com.artemis.Entity;
import com.artemis.EntityObserver;
import com.artemis.Filter;
import com.artemis.World;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Bits;
import com.badlogic.gdx.utils.ObjectIntMap;

/**
 * The most raw entity system. It should not typically be used, but you
 * can create your own entity system handling by extending this.
 * It is recommended that you use the other provided entity system
 * implementations.
 * 
 * @author Arni Arent
 *
 */
public abstract class EntitySystem implements EntityObserver {
    protected final int systemIndex;

    protected World world;

    protected Array actives;

    protected Filter filter;

    protected boolean passive;

    protected boolean dummySystem;

    /**
     * Creates an entity system that uses the specified filter
     * as a matcher against entities.
     * 
     * @param filter to match against entities
     */
    public EntitySystem(Filter filter) {
        actives = new Array();
        this.filter = filter;
        systemIndex = SystemIndexManager.getIndexFor(this.getClass());

        // This system can't possibly be interested in any entity,
        // so it must be "dummy system"
        dummySystem = filter.allSet.isEmpty() && filter.anySet.isEmpty();
    }

    /**
     * Called before processing of entities begins.
     */
    protected void begin() {
    }

    /**
     * Process all entities that are targeted by this system.
     */
    public final void process() {
        if(checkProcessing()) {
            begin();
            processEntities(actives);
            end();
        }
    }

    /**
     * Called after the processing of entities ends.
     */
    protected void end() {
    }

    /**
     * Any implementing entity system must implement this method and the logic
     * to process the given entities of the system.
     * 
     * @param entities the entities this system contains.
     */
    protected abstract void processEntities(Array entities);

    /**
     * 
     * @return true if the system should be processed, false if not.
     */
    protected boolean checkProcessing() {
        return true;
    }

    /**
     * Override to implement code that gets executed when systems are initialized.
     */
    public void initialize() {};

    /**
     * Called if the system has received a entity it is interested in,
     * e.g. created or a component was added to it.
     * 
     * @param e the entity that was added to this system.
     */
    protected void inserted(Entity e) {};

    /**
     * Called if a entity was removed from this system, e.g. deleted
     * or had one of it's components removed.
     * 
     * @param e the entity that was removed from this system.
     */
    protected void removed(Entity e) {};

    /**
     * Will check if the entity is of interest to this system.
     * @param e entity to check
     */
    protected final void check(Entity e) {
        if(dummySystem) {
            return;
        }

        boolean contains = e.getSystemBits().get(systemIndex);
        boolean interested = true; // possibly interested, let's try to prove it wrong.

        Bits componentBits = e.getComponentBits();

        // Check if the entity possesses ALL of the components defined in the filter.
        if(!filter.allSet.isEmpty()) {
            for (int i = filter.allSet.nextSetBit(0); i >= 0; i = filter.allSet.nextSetBit(i+1)) {
                if(!componentBits.get(i)) {
                    interested = false;
                    break;
                }
            }
        }

        // Check if the entity possesses ANY of the components in the anySet.
        // If so, the system is interested.
        if(interested && !filter.anySet.isEmpty()) {
            interested = filter.anySet.intersects(componentBits);
        }

        // Check if the entity possesses ANY of the exclusion components,
        // if it does then the system is not interested.
        if(interested && !filter.exclusionSet.isEmpty()) {
            interested = !filter.exclusionSet.intersects(componentBits);
        }

        if (interested && !contains) {
            insertToSystem(e);
        } else if (!interested && contains) {
            removeFromSystem(e);
        }
    }

    /**
     * Remove entity from the system.
     * 
     * @param e Entity to remove.
     */
    protected void removeFromSystem(Entity e) {
        actives.removeValue(e, true);
        e.getSystemBits().clear(systemIndex);
        removed(e);
    }

    /**
     * Inserts entity into the system.
     * 
     * @param e Entity to insert.
     */
    protected void insertToSystem(Entity e) {
        actives.add(e);
        e.getSystemBits().set(systemIndex);
        inserted(e);
    }


    @Override
    public final void added(Entity e) {
        check(e);
    }

    @Override
    public final void changed(Entity e) {
        check(e);
    }

    @Override
    public final void deleted(Entity e) {
        if(e.getSystemBits().get(systemIndex)) {
            removeFromSystem(e);
        }
    }

    @Override
    public final void disabled(Entity e) {
        if(e.getSystemBits().get(systemIndex)) {
            removeFromSystem(e);
        }
    }

    @Override
    public final void enabled(Entity e) {
        check(e);
    }


    public final void setWorld(World world) {
        this.world = world;
    }

    public boolean isPassive() {
        return passive;
    }

    public void setPassive(boolean passive) {
        this.passive = passive;
    }

    public Array getActives() {
        return actives;
    }



    /**
     * Used to generate a unique bit for each system.
     * Only used internally in EntitySystem.
     */
    protected static class SystemIndexManager {
        protected static int INDEX = 0;
        protected static ObjectIntMap> indices =
                new ObjectIntMap>();

        protected static int getIndexFor(Class es){
            int index;
            if (!indices.containsKey(es)) {
                index = INDEX++;
                indices.put(es, index);
            } else {
                index = indices.get(es, -1);
            }
            return index;
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy