package com.indignado.logicbricks.systems.sensors;
import com.badlogic.ashley.core.Engine;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.EntityListener;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.ObjectSet;
import com.indignado.logicbricks.components.ViewsComponent;
import com.indignado.logicbricks.components.sensors.MouseSensorComponent;
import com.indignado.logicbricks.core.data.TextureView;
import com.indignado.logicbricks.core.sensors.MouseSensor;
import com.indignado.logicbricks.core.sensors.MouseSensor.MouseEvent;
/**
* @author Rubentxu
*/
public class MouseSensorSystem extends SensorSystem<MouseSensor, MouseSensorComponent> implements InputProcessor, EntityListener {
private ObjectMap<MouseEvent, ObjectSet<MouseSensor>> mouseSensors;
private Camera camera;
public MouseSensorSystem() {
super(MouseSensorComponent.class);
mouseSensors = new ObjectMap<MouseEvent, ObjectSet<MouseSensor>>();
}
@Override
public void addedToEngine(Engine engine) {
super.addedToEngine(engine);
this.camera = context.get(Camera.class);
}
@Override
public boolean query(MouseSensor sensor, float deltaTime) {
boolean isActive = false;
if (sensor.mouseEventSignal != null && sensor.mouseEvent.equals(sensor.mouseEventSignal)) {
isActive = true;
}
if (sensor.mouseEvent.equals(MouseEvent.MOUSE_OVER)) {
isActive = isMouseOver(sensor.target, (int) sensor.positionSignal.x, (int) sensor.positionSignal.y);
}
if (!sensor.mouseEvent.equals(MouseEvent.RIGHT_BUTTON_DOWN) && !sensor.mouseEvent.equals(MouseEvent.MIDDLE_BUTTON_DOWN)
&& !sensor.mouseEvent.equals(MouseEvent.LEFT_BUTTON_DOWN)) {
sensor.mouseEventSignal = null;
}
return isActive;
}
public boolean isMouseOver(Entity target, int posX, int posY) {
if (target == null) return false;
ViewsComponent viewsComponent = target.getComponent(ViewsComponent.class);
if (viewsComponent == null) return false;
Rectangle rectangle = new Rectangle();
for (Object view : viewsComponent.views) {
if (TextureView.class.isAssignableFrom(view.getClass())) {
TextureView textureView = (TextureView) view;
rectangle.set(textureView.attachedTransform.getPosition().x - textureView.width / 2,
textureView.attachedTransform.getPosition().y - textureView.height / 2, textureView.width, textureView.height);
if (rectangle.contains(posX, posY)) return true;
}
}
return false;
}
@Override
public boolean keyDown(int keycode) {
return false;
}
@Override
public boolean keyUp(int keycode) {
return false;
}
@Override
public boolean keyTyped(char character) {
return false;
}
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
Vector3 worldCoordinates = new Vector3(screenX, screenY, 0);
camera.unproject(worldCoordinates);
switch (button) {
case Input.Buttons.LEFT:
changeSensors(MouseEvent.LEFT_BUTTON_DOWN, worldCoordinates);
break;
case Input.Buttons.MIDDLE:
changeSensors(MouseEvent.MIDDLE_BUTTON_DOWN, worldCoordinates);
break;
case Input.Buttons.RIGHT:
changeSensors(MouseEvent.RIGHT_BUTTON_DOWN, worldCoordinates);
break;
}
return false;
}
@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
Vector3 worldCoordinates = new Vector3(screenX, screenY, 0);
camera.unproject(worldCoordinates);
switch (button) {
case Input.Buttons.LEFT:
changeSensors(MouseEvent.LEFT_BUTTON_UP, worldCoordinates);
changeSensors(MouseEvent.LEFT_BUTTON_DOWN, worldCoordinates, false);
break;
case Input.Buttons.MIDDLE:
changeSensors(MouseEvent.MIDDLE_BUTTON_UP, worldCoordinates);
changeSensors(MouseEvent.MIDDLE_BUTTON_DOWN, worldCoordinates, false);
break;
case Input.Buttons.RIGHT:
changeSensors(MouseEvent.RIGHT_BUTTON_UP, worldCoordinates);
changeSensors(MouseEvent.RIGHT_BUTTON_DOWN, worldCoordinates, false);
break;
}
return false;
}
private void changeSensors(MouseEvent event, Vector3 coordinates) {
changeSensors(event, coordinates, true);
}
private void changeSensors(MouseEvent event, Vector3 coordinates, boolean active) {
if (mouseSensors.containsKey(event)) {
for (MouseSensor sensor : mouseSensors.get(event)) {
if (active) sensor.mouseEventSignal = event;
else sensor.mouseEventSignal = null;
sensor.positionSignal.set(coordinates.x, coordinates.y);
}
}
}
@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
return false;
}
@Override
public boolean mouseMoved(int screenX, int screenY) {
Vector3 worldCoordinates = new Vector3(screenX, screenY, 0);
camera.unproject(worldCoordinates);
changeSensors(MouseEvent.MOVEMENT, worldCoordinates);
changeSensors(MouseEvent.MOUSE_OVER, worldCoordinates);
return false;
}
@Override
public boolean scrolled(int amount) {
if (amount < 0) {
if (mouseSensors.containsKey(MouseEvent.WHEEL_DOWN)) {
for (MouseSensor sensor : mouseSensors.get(MouseEvent.WHEEL_DOWN)) {
sensor.mouseEventSignal = MouseEvent.WHEEL_DOWN;
sensor.amountScrollSignal = amount;
}
}
}
if (amount > 0) {
if (mouseSensors.containsKey(MouseEvent.WHEEL_UP)) {
for (MouseSensor sensor : mouseSensors.get(MouseEvent.WHEEL_UP)) {
sensor.mouseEventSignal = MouseEvent.WHEEL_UP;
sensor.amountScrollSignal = amount;
}
}
}
return false;
}
@Override
public void entityAdded(Entity entity) {
MouseSensorComponent mouseComponent = entity.getComponent(MouseSensorComponent.class);
if (mouseComponent != null) {
IntMap.Values<ObjectSet<MouseSensor>> values = mouseComponent.sensors.values();
while (values.hasNext()) {
for (MouseSensor sensor : values.next()) {
ObjectSet eventSensors;
if (mouseSensors.containsKey(sensor.mouseEvent)) {
eventSensors = mouseSensors.get(sensor.mouseEvent);
} else {
eventSensors = new ObjectSet<MouseSensor>();
mouseSensors.put(sensor.mouseEvent, eventSensors);
}
eventSensors.add(sensor);
}
}
}
}
@Override
public void entityRemoved(Entity entity) {
MouseSensorComponent mouseComponent = entity.getComponent(MouseSensorComponent.class);
if (mouseComponent != null) {
IntMap.Values<ObjectSet<MouseSensor>> values = mouseComponent.sensors.values();
while (values.hasNext()) {
for (MouseSensor sensor : values.next()) {
if (mouseSensors.containsKey(sensor.mouseEvent)) {
mouseSensors.get(sensor.mouseEvent).remove(sensor);
}
}
}
}
}
}