package com.indignado.logicbricks.systems.sensors;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.EntityListener;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.*;
import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.ObjectSet;
import com.indignado.logicbricks.components.BlackBoardComponent;
import com.indignado.logicbricks.components.IdentityComponent;
import com.indignado.logicbricks.components.RigidBodiesComponents;
import com.indignado.logicbricks.components.sensors.RadarSensorComponent;
import com.indignado.logicbricks.core.LogicBricksException;
import com.indignado.logicbricks.core.sensors.RadarSensor;
import com.indignado.logicbricks.utils.Log;
import com.indignado.logicbricks.utils.builders.FixtureDefBuilder;
/**
* @author Rubentxu
*/
public class RadarSensorSystem extends SensorSystem<RadarSensor, RadarSensorComponent> implements ContactListener, EntityListener {
public RadarSensorSystem() {
super(RadarSensorComponent.class);
}
@Override
public boolean query(RadarSensor 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) {
Object sensorA = contact.getFixtureA().getUserData();
Object sensorB = contact.getFixtureB().getUserData();
Log.debug(tag, "Begin contact %b A %s B %s Apos %s Bpos %s", contact.isTouching(), sensorA, sensorB,
contact.getFixtureA().getBody().getPosition(), contact.getFixtureB().getBody().getPosition());
if (sensorA != null && sensorA instanceof RadarSensor) {
Entity entityB = (Entity) contact.getFixtureB().getBody().getUserData();
processRadarSensors(entityB, contact, (RadarSensor) sensorA, true);
} else if (sensorB != null && sensorB instanceof RadarSensor) {
Entity entityA = (Entity) contact.getFixtureA().getBody().getUserData();
processRadarSensors(entityA, contact, (RadarSensor) sensorB, true);
}
}
@Override
public void endContact(Contact contact) {
Object sensorA = contact.getFixtureA().getUserData();
Object sensorB = contact.getFixtureB().getUserData();
Log.debug(tag, "End contact %b A %s B %s Apos %s Bpos %s", contact.isTouching(), sensorA, sensorB,
contact.getFixtureA().getBody().getPosition(), contact.getFixtureB().getBody().getPosition());
if (sensorA != null && sensorA instanceof RadarSensor) {
Entity entityB = (Entity) contact.getFixtureB().getBody().getUserData();
processRadarSensors(entityB, contact, (RadarSensor) sensorA, false);
} else if (sensorB != null && sensorB instanceof RadarSensor) {
Entity entityA = (Entity) contact.getFixtureA().getBody().getUserData();
processRadarSensors(entityA, contact, (RadarSensor) sensorB, false);
}
}
@Override
public void preSolve(Contact contact, Manifold oldManifold) {
}
@Override
public void postSolve(Contact contact, ContactImpulse impulse) {
}
private void processRadarSensors(Entity entity, Contact contact, RadarSensor radarSensor, boolean addMode) {
BlackBoardComponent blackBoard = entity.getComponent(BlackBoardComponent.class);
IdentityComponent identity = entity.getComponent(IdentityComponent.class);
if (blackBoard != null && radarSensor.targetPropertyName != null && blackBoard.hasProperty(radarSensor.targetPropertyName)) {
Log.debug(tag, "AddMode %b targetPropertyName", addMode);
if (addMode) radarSensor.contactList.add(contact);
else radarSensor.contactList.remove(contact);
} else if (radarSensor.targetTag != null && identity.tag.equals(radarSensor.targetTag)) {
Log.debug(tag, "AddMode %b targetTag", addMode);
if (addMode) radarSensor.contactList.add(contact);
else radarSensor.contactList.remove(contact);
} else if (radarSensor.targetTag == null && radarSensor.targetPropertyName == null) {
Log.debug(tag, "AddMode %b null targets", addMode);
if (addMode) radarSensor.contactList.add(contact);
else radarSensor.contactList.remove(contact);
}
Log.debug(tag, "ContactList size %d", radarSensor.contactList.size);
}
@Override
public void entityAdded(Entity entity) {
Log.debug(tag, "EntityAdded add radarSensors");
ObjectSet<RadarSensor> radarSensors = filterRadarSensors(entity);
if (radarSensors.size > 0) {
RigidBodiesComponents rigidBodiesComponent = entity.getComponent(RigidBodiesComponents.class);
if (rigidBodiesComponent == null)
throw new LogicBricksException(tag, "Failed to create radar sensor, there is no rigidBody");
Body body = rigidBodiesComponent.rigidBodies.first();
Log.debug(tag, "Create Radar");
createRadar(body, radarSensors);
}
}
@Override
public void entityRemoved(Entity entity) {
}
private void createRadar(Body body, ObjectSet<RadarSensor> radarSensors) {
FixtureDefBuilder fixtureBuilder = new FixtureDefBuilder();
Vector2[] vertices = new Vector2[8];
vertices[0] = new Vector2();
for (RadarSensor sensor : radarSensors) {
if (sensor.angle > 180)
throw new LogicBricksException(tag, "The angle of the radar can not be greater than 180");
for (int i = 0; i < 7; i++) {
float angle = (float) (i / 6.0 * sensor.angle) - (sensor.angle / 2) + (sensor.axis2D.ordinal() * 90);
vertices[i + 1] = new Vector2(sensor.distance * MathUtils.cosDeg(angle), sensor.distance * MathUtils.sinDeg(angle));
}
FixtureDef radarFixture = fixtureBuilder
.polygonShape(vertices)
.sensor()
.build();
body.createFixture(radarFixture).setUserData(sensor);
Log.debug(tag, "Create Fixture radarSensor");
}
}
private ObjectSet<RadarSensor> filterRadarSensors(Entity entity) {
ObjectSet<RadarSensor> radarSensors = new ObjectSet<RadarSensor>();
RadarSensorComponent radarSensorComponent = entity.getComponent(RadarSensorComponent.class);
if (radarSensorComponent != null) {
IntMap.Values<ObjectSet<RadarSensor>> values = radarSensorComponent.sensors.values();
while (values.hasNext()) {
for (RadarSensor sensor : values.next()) {
radarSensors.add(sensor);
}
}
}
return radarSensors;
}
}