package fr.lyrgard.hexScape.control;
import com.jme3.app.Application;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.collision.CollisionResults;
import com.jme3.input.InputManager;
import com.jme3.math.Ray;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import fr.lyrgard.hexScape.HexScapeCore;
import fr.lyrgard.hexScape.HexScapeJme3Application;
import fr.lyrgard.hexScape.io.virtualScape.bean.Vector3i;
import fr.lyrgard.hexScape.model.map.Tile;
import fr.lyrgard.hexScape.model.model3d.TileMesh;
import fr.lyrgard.hexScape.service.PieceManager;
import fr.lyrgard.hexScape.utils.CoordinateUtils;
public class PlacePieceByMouseAppState extends AbstractAppState {
private static final float MINIMAL_MOUSE_MOVE_TO_MOVE_PIECE = 0.1f;
private PieceManager pieceToPlace;
private InputManager inputManager;
private Camera cam;
private Node rootNode;
private boolean movedEnoughToInitMove;
private Vector2f initialMousePosition;
@Override
public void initialize(AppStateManager stateManager, Application app) {
super.initialize(stateManager, app);
this.inputManager = app.getInputManager();
this.cam = app.getCamera();
this.rootNode = ((HexScapeJme3Application)app).getRootNode();
}
@Override
public void cleanup() {
super.cleanup();
}
public PieceManager getPieceToPlace() {
return pieceToPlace;
}
public void setPieceToPlace(PieceManager newPieceToPlace) {
if (this.pieceToPlace != null) {
rootNode.detachChild(this.pieceToPlace.getSpatial());
if (HexScapeCore.getInstance().getHexScapeJme3Application().getScene().contains(pieceToPlace)) {
HexScapeCore.getInstance().getMapManager().placePiece(pieceToPlace, pieceToPlace.getPiece().getX(), pieceToPlace.getPiece().getY(), pieceToPlace.getPiece().getZ(), pieceToPlace.getPiece().getDirection());
}
}
this.pieceToPlace = newPieceToPlace;
}
@Override
public void update(float tpf) {
super.update(tpf);
Vector2f mousePosition = inputManager.getCursorPosition();
if (!movedEnoughToInitMove) {
float move = initialMousePosition.distance(mousePosition);
if (move > MINIMAL_MOUSE_MOVE_TO_MOVE_PIECE) {
movedEnoughToInitMove = true;
} else {
return;
}
}
Vector3f collision = getMapCollisionPoint(mousePosition);
if (collision != null) {
if (HexScapeCore.getInstance().getMapManager() != null) {
Vector3i mapPos = CoordinateUtils.toMapCoordinate(collision.x, collision.y, collision.z);
Tile nearestTile = HexScapeCore.getInstance().getMapManager().getNearestTile(mapPos.x, mapPos.y, mapPos.z);
if (nearestTile != null) {
Vector3f spacePos = CoordinateUtils.toSpaceCoordinate(nearestTile.getX(), nearestTile.getY(), nearestTile.getZ());
if (nearestTile.isHalfSize()) {
spacePos.y += TileMesh.HEX_SIZE_Y / 2;
} else {
spacePos.y += TileMesh.HEX_SIZE_Y;
}
pieceToPlace.getSpatial().setLocalTranslation(spacePos);
}
}
}
}
public boolean placePiece() {
boolean success = false;
Vector3f collision = getMapCollisionPoint(inputManager.getCursorPosition());
if (collision != null) {
Vector3i mapPos = CoordinateUtils.toMapCoordinate(collision.x, collision.y, collision.z);
success = HexScapeCore.getInstance().getMapManager().placePiece(pieceToPlace, mapPos.x, mapPos.y, mapPos.z, pieceToPlace.getPiece().getDirection());
if (success) {
pieceToPlace = null;//setPieceToPlace(null);
}
}
return success;
}
public boolean hasMovedEnoughToInitMove() {
return movedEnoughToInitMove;
}
public void cancelPlacement() {
setPieceToPlace(null);
}
private Vector3f getMapCollisionPoint(Vector2f click2d) {
Vector3f collision = null;
// Reset results list.
CollisionResults results = new CollisionResults();
// Convert screen click to 3d position
Vector3f click3d = cam.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 0f).clone();
Vector3f dir = cam.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 1f).subtractLocal(click3d).normalizeLocal();
// Aim the ray from the clicked spot forwards.
Ray ray = new Ray(click3d, dir);
// Collect intersections between ray and all nodes in results list.
Spatial mapSpatial = HexScapeCore.getInstance().getMapManager().getMapWithoutDecorsNode();
if (mapSpatial != null) {
mapSpatial.collideWith(ray, results);
}
// 5. Use the results
if (results.size() > 0) {
// The closest result is the target that the player picked:
//Geometry target = results.getClosestCollision().getGeometry();
collision = results.getClosestCollision().getContactPoint();
CoordinateUtils.centerPosOnHex(collision);
}
return collision;
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
if (enabled) {
initialMousePosition = new Vector2f(inputManager.getCursorPosition());
movedEnoughToInitMove = false;
if (pieceToPlace != null) {
rootNode.attachChild(pieceToPlace.getSpatial());
}
} else {
setPieceToPlace(null);
}
}
}