package com.indignado.logicbricks.systems.sensors; import com.badlogic.ashley.core.Entity; import com.badlogic.ashley.core.EntityListener; import com.badlogic.gdx.physics.box2d.*; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.ObjectSet; import com.indignado.logicbricks.components.IdentityComponent; import com.indignado.logicbricks.components.RigidBodiesComponents; import com.indignado.logicbricks.components.sensors.CollisionSensorComponent; import com.indignado.logicbricks.core.LogicBricksException; import com.indignado.logicbricks.core.sensors.CollisionSensor; import com.indignado.logicbricks.utils.Log; /** * @author Rubentxu */ public class CollisionSensorSystem extends SensorSystem<CollisionSensor, CollisionSensorComponent> implements ContactListener, EntityListener { private Array<ContactListener> collisionsRules = new Array<>(); public CollisionSensorSystem() { super(CollisionSensorComponent.class); } public void addCollisionRule(ContactListener collisionRule) { this.collisionsRules.add(collisionRule); } @Override public boolean query(CollisionSensor sensor, float deltaTime) { for (Contact contact : sensor.contactList) { Log.debug(tag, "sensor contact %b", contact.isTouching()); if (contact.isTouching()) return true; } return false; } @Override public void beginContact(Contact contact) { if (collisionsRules != null) { for (ContactListener rule : collisionsRules) { rule.beginContact(contact); } } Object sensorA = contact.getFixtureA().getUserData(); Object sensorB = contact.getFixtureB().getUserData(); if (sensorA != null && sensorA instanceof CollisionSensor) { Entity entityB = (Entity) contact.getFixtureB().getBody().getUserData(); processContactCollisionSensors(entityB, contact, (CollisionSensor) sensorA, true); } else if (sensorB != null && sensorB instanceof CollisionSensor) { Entity entityA = (Entity) contact.getFixtureA().getBody().getUserData(); processContactCollisionSensors(entityA, contact, (CollisionSensor) sensorB, true); } } @Override public void endContact(Contact contact) { if (collisionsRules != null) { for (ContactListener rule : collisionsRules) { rule.endContact(contact); } } Object sensorA = contact.getFixtureA().getUserData(); Object sensorB = contact.getFixtureB().getUserData(); if (sensorA != null && sensorA instanceof CollisionSensor) { Entity entityB = (Entity) contact.getFixtureB().getBody().getUserData(); processContactCollisionSensors(entityB, contact, (CollisionSensor) sensorA, false); } else if (sensorB != null && sensorB instanceof CollisionSensor) { Entity entityA = (Entity) contact.getFixtureA().getBody().getUserData(); processContactCollisionSensors(entityA, contact, (CollisionSensor) sensorB, false); } } @Override public void preSolve(Contact contact, Manifold oldManifold) { if (collisionsRules != null) { for (ContactListener rule : collisionsRules) { rule.preSolve(contact, oldManifold); } } } @Override public void postSolve(Contact contact, ContactImpulse impulse) { if (collisionsRules != null) { for (ContactListener rule : collisionsRules) { rule.postSolve(contact, impulse); } } } private void processContactCollisionSensors(Entity entity, Contact contact, CollisionSensor collisionSensor, boolean addMode) { IdentityComponent identity = entity.getComponent(IdentityComponent.class); if (collisionSensor.targetTag != null && identity.tag.equals(collisionSensor.targetTag)) { if (addMode) collisionSensor.contactList.add(contact); else collisionSensor.contactList.remove(contact); } } @Override public void entityAdded(Entity entity) { Log.debug(tag, "EntityAdded add collisionSensors"); Array<CollisionSensor> collisionSensors = filterCollisionSensors(entity); if (collisionSensors.size > 0) { RigidBodiesComponents rigidBodiesComponent = entity.getComponent(RigidBodiesComponents.class); if (rigidBodiesComponent == null) throw new LogicBricksException(tag, "Failed to create collision sensor, there is no rigidBody"); Body body = rigidBodiesComponent.rigidBodies.first(); if (body == null) throw new LogicBricksException(tag, "Failed to create collision sensor, there is no rigidBody"); for (CollisionSensor sensor : collisionSensors) { for (Fixture fixture : body.getFixtureList()) { fixture.setUserData(sensor); } } } } @Override public void entityRemoved(Entity entity) { } private Array<CollisionSensor> filterCollisionSensors(Entity entity) { Array<CollisionSensor> collisionSensors = new Array<CollisionSensor>(); CollisionSensorComponent collisionSensorComponent = entity.getComponent(CollisionSensorComponent.class); if (collisionSensorComponent != null) { IntMap.Values<ObjectSet<CollisionSensor>> values = collisionSensorComponent.sensors.values(); while (values.hasNext()) { for (CollisionSensor sensor : values.next()) { if (sensor.targetTag != null) { collisionSensors.add(sensor); } } } } return collisionSensors; } }