package com.indignado.logicbricks.utils.builders; import com.badlogic.ashley.core.Component; import com.badlogic.ashley.core.Entity; import com.badlogic.ashley.core.EntitySystem; import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.physics.box2d.Body; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.ObjectSet; import com.badlogic.gdx.utils.reflect.ClassReflection; import com.badlogic.gdx.utils.reflect.Constructor; import com.badlogic.gdx.utils.reflect.ReflectionException; import com.indignado.logicbricks.components.*; import com.indignado.logicbricks.components.actuators.ActuatorComponent; import com.indignado.logicbricks.components.controllers.ControllerComponent; import com.indignado.logicbricks.components.sensors.SensorComponent; import com.indignado.logicbricks.core.BricksClasses; import com.indignado.logicbricks.core.LogicBricksEngine; import com.indignado.logicbricks.core.LogicBricksException; import com.indignado.logicbricks.core.actuators.Actuator; import com.indignado.logicbricks.core.controllers.Controller; import com.indignado.logicbricks.core.data.LogicBrick; import com.indignado.logicbricks.core.data.Property; import com.indignado.logicbricks.core.data.View; import com.indignado.logicbricks.core.sensors.Sensor; import com.indignado.logicbricks.systems.LogicBrickSystem; import com.indignado.logicbricks.utils.Log; /** * @author Rubentxu. */ public class EntityBuilder { private static String tag = "EntityBuilder"; private LogicBricksEngine engine; private Entity entity; private Controller controller; private Array<String> controllerStates; public EntityBuilder(LogicBricksEngine engine) { this.controllerStates = new Array(); this.engine = engine; } private static Constructor findConstructor(Class type) { try { return ClassReflection.getConstructor(type, (Class[]) null); } catch (Exception ex1) { try { Constructor constructor = ClassReflection.getDeclaredConstructor(type, (Class[]) null); constructor.setAccessible(true); return constructor; } catch (ReflectionException ex2) { Log.debug(tag, "Error instance entitySystem %s", ex2.getMessage()); return null; } } } public EntityBuilder initialize() { entity = engine.createEntity(); return this; } public EntityBuilder initialize(Entity entity) { this.entity = entity; return this; } private int getKeyState(String state) { StateComponent stateComponent = getComponent(StateComponent.class); int keyState = stateComponent.getState(state); if (keyState == -1) { keyState = stateComponent.createState(state); } return keyState; } private <S extends Sensor> EntityBuilder addSensor(Sensor sensor, Array<String> nameStates) { for (String s : nameStates) { addSensor(sensor, s); } return this; } private <S extends Sensor, SC extends SensorComponent> EntityBuilder addSensor(S sensor, String nameState) { int state = getKeyState(nameState); sensor.state = state; ObjectSet<S> sensorsList = null; BricksClasses classes = engine.getBricksClasses(sensor.getClass()); if (classes != null) { getSystem(classes.system); SC sensorComponent = (SC) getComponent(classes.component); sensorsList = getSensorList(sensorComponent, sensor.state); } if (sensorsList != null && !sensorsList.contains(sensor)) sensorsList.add(sensor); return this; } private <ES extends EntitySystem> ES getSystem(Class<ES> clazz) { ES entitySystem = engine.getSystem(clazz); if (entitySystem == null) { try { Constructor constructor = findConstructor(clazz); entitySystem = (ES) constructor.newInstance((Object[]) null); } catch (Exception ex) { Log.debug(tag, "Error instance entitySystem %s", clazz.getSimpleName()); } if (entitySystem != null) { engine.addSystem(entitySystem); } else { Log.debug(tag, "Error instance entitySystem %s", clazz.getSimpleName()); } } return entitySystem; } public <C extends Component> C getComponent(Class<C> clazz) { C comp = null; if (entity.getComponent(clazz) != null) { comp = (C) entity.getComponent(clazz); } else { Class<? extends LogicBrickSystem>[] systems = engine.getSystemClass(clazz); if(systems != null) { for (Class<? extends LogicBrickSystem> system : systems) { if (system != null) getSystem(system); } } comp = engine.createComponent(clazz); entity.add(comp); } if(comp instanceof CameraComponent) ((CameraComponent) comp).camera = engine.getGameContext().get(Camera.class); return comp; } private <S extends Sensor> ObjectSet<S> getSensorList(SensorComponent sensorComponent, int state) { ObjectSet<S> sensorsList = (ObjectSet<S>) sensorComponent.sensors.get(state); if (sensorsList == null) { sensorsList = new ObjectSet<S>(); sensorComponent.sensors.put(state, sensorsList); } return sensorsList; } public <C extends Controller> EntityBuilder addController(C controller, String... nameStates) { controllerStates.clear(); for (String s : nameStates) { addToController(controller, s); } return this; } public <C extends Controller> EntityBuilder addController(C controller, Array<String> nameStates) { controllerStates.clear(); for (String s : nameStates) { addToController(controller, s); } return this; } private <C extends Controller, CC extends ControllerComponent> EntityBuilder addToController(C controller, String nameState) { this.controller = controller; controllerStates.add(nameState); int state = getKeyState(nameState); controller.state = state; ObjectSet<C> controllerList = null; BricksClasses classes = engine.getBricksClasses(controller.getClass()); if (classes != null) { getSystem(classes.system); CC controllerComponent = (CC) getComponent(classes.component); controllerList = getControllerList(controllerComponent, controller.state); } if (controllerList != null && !controllerList.contains(controller)) controllerList.add(controller); return this; } private <C extends Controller> ObjectSet<C> getControllerList(ControllerComponent controllerComponent, int state) { ObjectSet<C> controllersList = (ObjectSet<C>) controllerComponent.controllers.get(state); if (controllersList == null) { controllersList = new ObjectSet<C>(); controllerComponent.controllers.put(state, controllersList); } return controllersList; } public EntityBuilder connectToSensors(Sensor... sensors) { for (Sensor s : sensors) { connectToSensor(s); } return this; } public EntityBuilder connectToSensor(Sensor sensor) { addSensor(sensor, controllerStates); if (sensor.name == null) sensor.name = sensor.getClass().getSimpleName() + "_" + MathUtils.random(10000); controller.sensors.put(sensor.name, sensor); return this; } public EntityBuilder connectToActuators(Actuator... actuators) { for (Actuator a : actuators) { connectToActuator(a); } return this; } public EntityBuilder connectToActuator(Actuator actuator) { addActuators(actuator, controllerStates); if (actuator.name == null) actuator.name = actuator.getClass().getSimpleName() + "_" + MathUtils.random(10000); actuator.controllers.add(controller); controller.actuators.put(actuator.name, actuator); return this; } private <A extends Actuator> EntityBuilder addActuators(Actuator actuator, Array<String> nameStates) { for (String s : nameStates) { addActuator(actuator, s); } return this; } private <A extends Actuator, AC extends ActuatorComponent> EntityBuilder addActuator(A actuator, String nameState) { int state = getKeyState(nameState); actuator.state = state; ObjectSet<A> actuatorList = null; BricksClasses classes = engine.getBricksClasses(actuator.getClass()); if (classes != null) { getSystem(classes.system); AC actuatorComponent = (AC) getComponent(classes.component); actuatorList = getActuatorList(actuatorComponent, actuator.state); } if (actuatorList != null && !actuatorList.contains(actuator)) actuatorList.add(actuator); return this; } private <A extends Actuator> ObjectSet<A> getActuatorList(ActuatorComponent actuatorComponent, int state) { ObjectSet<A> actuatorList = (ObjectSet<A>) actuatorComponent.actuators.get(state); if (actuatorList == null) { actuatorList = new ObjectSet<A>(); actuatorComponent.actuators.put(state, actuatorList); } return actuatorList; } public <V extends View> EntityBuilder addView(V view) { getComponent(ViewsComponent.class).views.add(view); return this; } public EntityBuilder addRigidBody(Body rigidBody) { getComponent(RigidBodiesComponents.class).rigidBodies.add(rigidBody); return this; } public EntityBuilder addProperty(Property property) { getComponent(BlackBoardComponent.class).addProperty(property); return this; } private void config(IntMap<ObjectSet<LogicBrick>> bricks, Entity entity) { if (entity == null) throw new LogicBricksException(tag, "Error: Not owner entity exist"); for (ObjectSet<LogicBrick> bricksSet : bricks.values()) { for (LogicBrick brick : bricksSet) { brick.owner = entity; } } } public Entity getEntity() { for (Component c : entity.getComponents()) { if (c instanceof SensorComponent) { config(((SensorComponent) c).sensors, entity); } if (c instanceof ControllerComponent) { config(((ControllerComponent) c).controllers, entity); } if (c instanceof ActuatorComponent) { config(((ActuatorComponent) c).actuators, entity); } } controllerStates.clear(); return entity; } }