package fr.lyrgard.hexScape.camera;
import com.jme3.bounding.BoundingBox;
import com.jme3.input.InputManager;
import com.jme3.input.awt.AwtKeyInput;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Spatial;
public class RotatingAroundCamera implements AnalogListener {
public static final String ROTATINGCAM_Left = "ROTATINGCAM_Left";
public static final String ROTATINGCAM_Right = "ROTATINGCAM_Right";
public static final String ROTATINGCAM_Up = "ROTATINGCAM_Up";
public static final String ROTATINGCAM_Down = "ROTATINGCAM_Down";
public static final String ROTATINGCAM_ZoomIn = "ROTATINGCAM_ZoomIn";
public static final String ROTATINGCAM_ZoomOut = "ROTATINGCAM_ZoomOut";
protected Camera cam;
protected Vector3f initialUpVec;
protected Vector3f centerPos = Vector3f.ZERO;
protected float distance;
private Quaternion rot = new Quaternion();
protected InputManager inputManager;
protected float rotationSpeed = 1.0F;
protected float zoomSpeed = 20F;
public RotatingAroundCamera(Camera cam) {
this.cam = cam;
this.initialUpVec = cam.getUp().clone();
}
/**
* Registers the FlyByCamera to recieve input events from the provided
* Dispatcher.
* @param dispacher
*/
public void registerWithInput(InputManager inputManager){
this.inputManager = inputManager;
String[] mappings = new String[]{
ROTATINGCAM_Left,
ROTATINGCAM_Right,
ROTATINGCAM_Up,
ROTATINGCAM_Down,
ROTATINGCAM_ZoomIn,
ROTATINGCAM_ZoomOut,
};
// both mouse and button - rotation of cam
inputManager.addMapping(ROTATINGCAM_Left, new KeyTrigger(AwtKeyInput.KEY_LEFT));
inputManager.addMapping(ROTATINGCAM_Right, new KeyTrigger(AwtKeyInput.KEY_RIGHT));
inputManager.addMapping(ROTATINGCAM_Up, new KeyTrigger(AwtKeyInput.KEY_UP));
inputManager.addMapping(ROTATINGCAM_Down, new KeyTrigger(AwtKeyInput.KEY_DOWN));
inputManager.addMapping(ROTATINGCAM_ZoomIn, new KeyTrigger(AwtKeyInput.KEY_ADD));
inputManager.addMapping(ROTATINGCAM_ZoomOut, new KeyTrigger(AwtKeyInput.KEY_SUBTRACT));
inputManager.addListener(this, mappings);
inputManager.setCursorVisible(true);
}
public void unregisterInput()
{
if (this.inputManager == null) {
return;
}
String[] mappings = {ROTATINGCAM_Left, ROTATINGCAM_Right, ROTATINGCAM_Up, ROTATINGCAM_Down, ROTATINGCAM_ZoomIn, ROTATINGCAM_ZoomOut};
for (String s : mappings) {
if (this.inputManager.hasMapping(s)) {
this.inputManager.deleteMapping(s);
}
}
this.inputManager.removeListener(this);
}
public void onAnalog(String name, float value, float tpf) {
if (name.equals(ROTATINGCAM_Left)){
rotateCamera(-value, true);
}else if (name.equals(ROTATINGCAM_Right)){
rotateCamera(value, true);
}else if (name.equals(ROTATINGCAM_Up)){
rotateCamera(value, false);
}else if (name.equals(ROTATINGCAM_Down)){
rotateCamera(-value, false);
}else if (name.equals(ROTATINGCAM_ZoomIn)){
zoomCamera(-value);
}else if (name.equals(ROTATINGCAM_ZoomOut)){
zoomCamera(value);
}
}
private void rotateCamera(float value, boolean sideways) {
if (sideways) {
Vector3f camPos = cam.getLocation(); // So now we have current position and center
rot.fromAngles(0,value * rotationSpeed, 0);
Vector3f difference = camPos.subtract(centerPos);
rot.multLocal(difference);
cam.setLocation(centerPos.add(difference));
cam.lookAt(centerPos, Vector3f.UNIT_Y);
} else {
Vector3f v = new Vector3f();
cam.getUp(v);
Vector3f pos = cam.getLocation();
Vector3f newPos = pos.add(v.mult(distance * value * 1f));
boolean goOverVertical = ((pos.x - centerPos.x) * (newPos.x - centerPos.x) < 0) || ((pos.z - centerPos.z) * (newPos.z - centerPos.z) < 0);
//float distanceToVertical = Math.abs(newPos.x - centerPos.x) + Math.abs(newPos.z - centerPos.z);
if (newPos.y > centerPos.y && !goOverVertical ) {
newPos = centerPos.add(newPos.subtract(centerPos).normalize().mult(distance));
cam.setLocation(newPos);
cam.lookAt(centerPos, Vector3f.UNIT_Y);
}
}
}
private void zoomCamera(float value){
float newDistance = distance + value * zoomSpeed;
if (newDistance > 1) {
distance = newDistance;
cam.setLocation(centerPos.add(cam.getLocation().subtract(centerPos).normalize().mult(distance)));
cam.lookAt(centerPos, Vector3f.UNIT_Y);
}
}
public Vector3f getCenterPos() {
return centerPos;
}
public void setRotateAroundNode(Spatial rotateAroundNode) {
if (rotateAroundNode != null) {
BoundingBox volume = (BoundingBox)rotateAroundNode.getWorldBound();
centerPos = volume.getCenter();
distance = (float)(Math.sqrt(4 * volume.getXExtent() * volume.getXExtent() + 4 * volume.getYExtent() * volume.getYExtent()));
} else {
centerPos = Vector3f.ZERO;
distance = 20f;
}
cam.setLocation(centerPos.add(new Vector3f(1, 1, 0).normalize().mult(distance)));
cam.lookAt(centerPos, Vector3f.UNIT_Y);
}
}