|
|
|
@ -1,5 +1,5 @@ |
|
|
|
|
/* |
|
|
|
|
* Copyright (c) 2009-2012 jMonkeyEngine |
|
|
|
|
* Copyright (c) 2009-2017 jMonkeyEngine |
|
|
|
|
* All rights reserved. |
|
|
|
|
* |
|
|
|
|
* Redistribution and use in source and binary forms, with or without |
|
|
|
@ -32,7 +32,11 @@ |
|
|
|
|
package com.jme3.input; |
|
|
|
|
|
|
|
|
|
import com.jme3.collision.MotionAllowedListener; |
|
|
|
|
import com.jme3.input.controls.*; |
|
|
|
|
import com.jme3.input.controls.ActionListener; |
|
|
|
|
import com.jme3.input.controls.AnalogListener; |
|
|
|
|
import com.jme3.input.controls.KeyTrigger; |
|
|
|
|
import com.jme3.input.controls.MouseAxisTrigger; |
|
|
|
|
import com.jme3.input.controls.MouseButtonTrigger; |
|
|
|
|
import com.jme3.math.FastMath; |
|
|
|
|
import com.jme3.math.Matrix3f; |
|
|
|
|
import com.jme3.math.Quaternion; |
|
|
|
@ -40,12 +44,13 @@ import com.jme3.math.Vector3f; |
|
|
|
|
import com.jme3.renderer.Camera; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* A first person view camera controller. |
|
|
|
|
* After creation, you must register the camera controller with the |
|
|
|
|
* dispatcher using #registerWithDispatcher(). |
|
|
|
|
* A first-person camera controller. |
|
|
|
|
* |
|
|
|
|
* After creation, you (or FlyCamAppState) must register the controller using |
|
|
|
|
* {@link #registerWithInput(com.jme3.input.InputManager)}. |
|
|
|
|
* |
|
|
|
|
* Controls: |
|
|
|
|
* - Move the mouse to rotate the camera |
|
|
|
|
* - Move (or, in drag-to-rotate mode, drag) the mouse to rotate the camera |
|
|
|
|
* - Mouse wheel for zooming in or out |
|
|
|
|
* - WASD keys for moving forward/backward and strafing |
|
|
|
|
* - QZ keys raise or lower the camera |
|
|
|
@ -53,41 +58,62 @@ import com.jme3.renderer.Camera; |
|
|
|
|
public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
|
|
|
|
|
private static String[] mappings = new String[]{ |
|
|
|
|
CameraInput.FLYCAM_LEFT, |
|
|
|
|
CameraInput.FLYCAM_RIGHT, |
|
|
|
|
CameraInput.FLYCAM_UP, |
|
|
|
|
CameraInput.FLYCAM_DOWN, |
|
|
|
|
|
|
|
|
|
CameraInput.FLYCAM_STRAFELEFT, |
|
|
|
|
CameraInput.FLYCAM_STRAFERIGHT, |
|
|
|
|
CameraInput.FLYCAM_FORWARD, |
|
|
|
|
CameraInput.FLYCAM_BACKWARD, |
|
|
|
|
CameraInput.FLYCAM_LEFT, |
|
|
|
|
CameraInput.FLYCAM_RIGHT, |
|
|
|
|
CameraInput.FLYCAM_UP, |
|
|
|
|
CameraInput.FLYCAM_DOWN, |
|
|
|
|
|
|
|
|
|
CameraInput.FLYCAM_ZOOMIN, |
|
|
|
|
CameraInput.FLYCAM_ZOOMOUT, |
|
|
|
|
CameraInput.FLYCAM_ROTATEDRAG, |
|
|
|
|
CameraInput.FLYCAM_STRAFELEFT, |
|
|
|
|
CameraInput.FLYCAM_STRAFERIGHT, |
|
|
|
|
CameraInput.FLYCAM_FORWARD, |
|
|
|
|
CameraInput.FLYCAM_BACKWARD, |
|
|
|
|
|
|
|
|
|
CameraInput.FLYCAM_RISE, |
|
|
|
|
CameraInput.FLYCAM_LOWER, |
|
|
|
|
CameraInput.FLYCAM_ZOOMIN, |
|
|
|
|
CameraInput.FLYCAM_ZOOMOUT, |
|
|
|
|
CameraInput.FLYCAM_ROTATEDRAG, |
|
|
|
|
|
|
|
|
|
CameraInput.FLYCAM_INVERTY |
|
|
|
|
}; |
|
|
|
|
CameraInput.FLYCAM_RISE, |
|
|
|
|
CameraInput.FLYCAM_LOWER, |
|
|
|
|
|
|
|
|
|
CameraInput.FLYCAM_INVERTY |
|
|
|
|
}; |
|
|
|
|
/** |
|
|
|
|
* camera controlled by this controller (not null) |
|
|
|
|
*/ |
|
|
|
|
protected Camera cam; |
|
|
|
|
/** |
|
|
|
|
* normalized "up" direction (a unit vector) |
|
|
|
|
*/ |
|
|
|
|
protected Vector3f initialUpVec; |
|
|
|
|
/** |
|
|
|
|
* rotation-rate multiplier (1=default) |
|
|
|
|
*/ |
|
|
|
|
protected float rotationSpeed = 1f; |
|
|
|
|
/** |
|
|
|
|
* translation speed (in world units per second) |
|
|
|
|
*/ |
|
|
|
|
protected float moveSpeed = 3f; |
|
|
|
|
/** |
|
|
|
|
* zoom-rate multiplier (1=default) |
|
|
|
|
*/ |
|
|
|
|
protected float zoomSpeed = 1f; |
|
|
|
|
protected MotionAllowedListener motionAllowed = null; |
|
|
|
|
/** |
|
|
|
|
* enable flag for controller (false→ignoring input) |
|
|
|
|
*/ |
|
|
|
|
protected boolean enabled = true; |
|
|
|
|
/** |
|
|
|
|
* drag-to-rotate mode flag |
|
|
|
|
*/ |
|
|
|
|
protected boolean dragToRotate = false; |
|
|
|
|
protected boolean canRotate = false; |
|
|
|
|
protected boolean invertY = false; |
|
|
|
|
protected InputManager inputManager; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Creates a new FlyByCamera to control the given Camera object. |
|
|
|
|
* @param cam |
|
|
|
|
* Creates a new FlyByCamera to control the specified camera. |
|
|
|
|
* |
|
|
|
|
* @param cam camera to be controlled (not null) |
|
|
|
|
*/ |
|
|
|
|
public FlyByCamera(Camera cam){ |
|
|
|
|
this.cam = cam; |
|
|
|
@ -96,10 +122,11 @@ public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Sets the up vector that should be used for the camera. |
|
|
|
|
* |
|
|
|
|
* @param upVec |
|
|
|
|
*/ |
|
|
|
|
public void setUpVector(Vector3f upVec) { |
|
|
|
|
initialUpVec.set(upVec); |
|
|
|
|
initialUpVec.set(upVec); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setMotionAllowedListener(MotionAllowedListener listener){ |
|
|
|
@ -107,56 +134,68 @@ public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Sets the move speed. The speed is given in world units per second. |
|
|
|
|
* @param moveSpeed |
|
|
|
|
* Set the translation speed. |
|
|
|
|
* |
|
|
|
|
* @param moveSpeed new speed (in world units per second) |
|
|
|
|
*/ |
|
|
|
|
public void setMoveSpeed(float moveSpeed){ |
|
|
|
|
this.moveSpeed = moveSpeed; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Gets the move speed. The speed is given in world units per second. |
|
|
|
|
* @return moveSpeed |
|
|
|
|
* Read the translation speed. |
|
|
|
|
* |
|
|
|
|
* @return current speed (in world units per second) |
|
|
|
|
*/ |
|
|
|
|
public float getMoveSpeed(){ |
|
|
|
|
return moveSpeed; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Sets the rotation speed. |
|
|
|
|
* @param rotationSpeed |
|
|
|
|
* Set the rotation-rate multiplier. The bigger the multiplier, the more |
|
|
|
|
* rotation for a given movement of the mouse. |
|
|
|
|
* |
|
|
|
|
* @param rotationSpeed new rate multiplier (1=default) |
|
|
|
|
*/ |
|
|
|
|
public void setRotationSpeed(float rotationSpeed){ |
|
|
|
|
this.rotationSpeed = rotationSpeed; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Gets the move speed. The speed is given in world units per second. |
|
|
|
|
* @return rotationSpeed |
|
|
|
|
* Read the rotation-rate multiplier. The bigger the multiplier, the more |
|
|
|
|
* rotation for a given movement of the mouse. |
|
|
|
|
* |
|
|
|
|
* @return current rate multiplier (1=default) |
|
|
|
|
*/ |
|
|
|
|
public float getRotationSpeed(){ |
|
|
|
|
return rotationSpeed; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Sets the zoom speed. |
|
|
|
|
* @param zoomSpeed |
|
|
|
|
* Set the zoom-rate multiplier. The bigger the multiplier, the more zoom |
|
|
|
|
* for a given movement of the mouse wheel. |
|
|
|
|
* |
|
|
|
|
* @param zoomSpeed new rate multiplier (1=default) |
|
|
|
|
*/ |
|
|
|
|
public void setZoomSpeed(float zoomSpeed) { |
|
|
|
|
this.zoomSpeed = zoomSpeed; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Gets the zoom speed. The speed is a multiplier to increase/decrease |
|
|
|
|
* the zoom rate. |
|
|
|
|
* @return zoomSpeed |
|
|
|
|
* Read the zoom-rate multiplier. The bigger the multiplier, the more zoom |
|
|
|
|
* for a given movement of the mouse wheel. |
|
|
|
|
* |
|
|
|
|
* @return current rate multiplier (1=default) |
|
|
|
|
*/ |
|
|
|
|
public float getZoomSpeed() { |
|
|
|
|
return zoomSpeed; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @param enable If false, the camera will ignore input. |
|
|
|
|
* Enable or disable this controller. When disabled, the controller ignored |
|
|
|
|
* input. |
|
|
|
|
* |
|
|
|
|
* @param enable true to enable, false to disable |
|
|
|
|
*/ |
|
|
|
|
public void setEnabled(boolean enable){ |
|
|
|
|
if (enabled && !enable){ |
|
|
|
@ -168,32 +207,36 @@ public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @return If enabled |
|
|
|
|
* @see FlyByCamera#setEnabled(boolean) |
|
|
|
|
* Test whether this controller is enabled. |
|
|
|
|
* |
|
|
|
|
* @return true if enabled, otherwise false |
|
|
|
|
* @see #setEnabled(boolean) |
|
|
|
|
*/ |
|
|
|
|
public boolean isEnabled(){ |
|
|
|
|
return enabled; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Test whether drag-to-rotate mode is enabled. |
|
|
|
|
* |
|
|
|
|
* @return If drag to rotate feature is enabled. |
|
|
|
|
* |
|
|
|
|
* @see FlyByCamera#setDragToRotate(boolean) |
|
|
|
|
* @see #setDragToRotate(boolean) |
|
|
|
|
*/ |
|
|
|
|
public boolean isDragToRotate() { |
|
|
|
|
return dragToRotate; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Set if drag to rotate mode is enabled. |
|
|
|
|
* Enable or disable drag-to-rotate mode. |
|
|
|
|
* |
|
|
|
|
* When true, the user must hold the mouse button |
|
|
|
|
* and drag over the screen to rotate the camera, and the cursor is |
|
|
|
|
* visible until dragged. Otherwise, the cursor is invisible at all times |
|
|
|
|
* and holding the mouse button is not needed to rotate the camera. |
|
|
|
|
* This feature is disabled by default. |
|
|
|
|
* When drag-to-rotate mode is enabled, the user must hold the mouse button |
|
|
|
|
* and drag over the screen to rotate the camera, and the cursor is visible |
|
|
|
|
* until dragged. When drag-to-rotate mode is disabled, the cursor is |
|
|
|
|
* invisible at all times and holding the mouse button is not needed to |
|
|
|
|
* rotate the camera. This mode is disabled by default. |
|
|
|
|
* |
|
|
|
|
* @param dragToRotate True if drag to rotate mode is enabled. |
|
|
|
|
* @param dragToRotate true to enable, false to disable |
|
|
|
|
*/ |
|
|
|
|
public void setDragToRotate(boolean dragToRotate) { |
|
|
|
|
this.dragToRotate = dragToRotate; |
|
|
|
@ -203,8 +246,9 @@ public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Registers the FlyByCamera to receive input events from the provided |
|
|
|
|
* Dispatcher. |
|
|
|
|
* Register this controller to receive input events from the specified input |
|
|
|
|
* manager. |
|
|
|
|
* |
|
|
|
|
* @param inputManager |
|
|
|
|
*/ |
|
|
|
|
public void registerWithInput(InputManager inputManager){ |
|
|
|
@ -212,16 +256,16 @@ public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
|
|
|
|
|
// both mouse and button - rotation of cam
|
|
|
|
|
inputManager.addMapping(CameraInput.FLYCAM_LEFT, new MouseAxisTrigger(MouseInput.AXIS_X, true), |
|
|
|
|
new KeyTrigger(KeyInput.KEY_LEFT)); |
|
|
|
|
new KeyTrigger(KeyInput.KEY_LEFT)); |
|
|
|
|
|
|
|
|
|
inputManager.addMapping(CameraInput.FLYCAM_RIGHT, new MouseAxisTrigger(MouseInput.AXIS_X, false), |
|
|
|
|
new KeyTrigger(KeyInput.KEY_RIGHT)); |
|
|
|
|
new KeyTrigger(KeyInput.KEY_RIGHT)); |
|
|
|
|
|
|
|
|
|
inputManager.addMapping(CameraInput.FLYCAM_UP, new MouseAxisTrigger(MouseInput.AXIS_Y, false), |
|
|
|
|
new KeyTrigger(KeyInput.KEY_UP)); |
|
|
|
|
new KeyTrigger(KeyInput.KEY_UP)); |
|
|
|
|
|
|
|
|
|
inputManager.addMapping(CameraInput.FLYCAM_DOWN, new MouseAxisTrigger(MouseInput.AXIS_Y, true), |
|
|
|
|
new KeyTrigger(KeyInput.KEY_DOWN)); |
|
|
|
|
new KeyTrigger(KeyInput.KEY_DOWN)); |
|
|
|
|
|
|
|
|
|
// mouse only - zoom in/out with wheel, and rotate drag
|
|
|
|
|
inputManager.addMapping(CameraInput.FLYCAM_ZOOMIN, new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false)); |
|
|
|
@ -277,10 +321,9 @@ public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Unregisters the FlyByCamera from the event Dispatcher. |
|
|
|
|
* Unregister this controller from its input manager. |
|
|
|
|
*/ |
|
|
|
|
public void unregisterInput(){ |
|
|
|
|
|
|
|
|
|
if (inputManager == null) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -296,12 +339,16 @@ public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
|
|
|
|
|
Joystick[] joysticks = inputManager.getJoysticks(); |
|
|
|
|
if (joysticks != null && joysticks.length > 0){ |
|
|
|
|
Joystick joystick = joysticks[0]; |
|
|
|
|
|
|
|
|
|
// No way to unassing axis
|
|
|
|
|
// No way to unassign axis
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Rotate the camera by the specified amount around the specified axis. |
|
|
|
|
* |
|
|
|
|
* @param value rotation amount |
|
|
|
|
* @param axis direction of rotation (a unit vector) |
|
|
|
|
*/ |
|
|
|
|
protected void rotateCamera(float value, Vector3f axis){ |
|
|
|
|
if (dragToRotate){ |
|
|
|
|
if (canRotate){ |
|
|
|
@ -329,6 +376,11 @@ public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
cam.setAxes(q); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Zoom the camera by the specified amount. |
|
|
|
|
* |
|
|
|
|
* @param value zoom amount |
|
|
|
|
*/ |
|
|
|
|
protected void zoomCamera(float value){ |
|
|
|
|
// derive fovY value
|
|
|
|
|
float h = cam.getFrustumTop(); |
|
|
|
@ -338,7 +390,7 @@ public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
float near = cam.getFrustumNear(); |
|
|
|
|
|
|
|
|
|
float fovY = FastMath.atan(h / near) |
|
|
|
|
/ (FastMath.DEG_TO_RAD * .5f); |
|
|
|
|
/ (FastMath.DEG_TO_RAD * .5f); |
|
|
|
|
float newFovY = fovY + value * 0.1f * zoomSpeed; |
|
|
|
|
if (newFovY > 0f) { |
|
|
|
|
// Don't let the FOV go zero or negative.
|
|
|
|
@ -354,6 +406,11 @@ public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
cam.setFrustumRight(w); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Translate the camera upward by the specified amount. |
|
|
|
|
* |
|
|
|
|
* @param value translation amount |
|
|
|
|
*/ |
|
|
|
|
protected void riseCamera(float value){ |
|
|
|
|
Vector3f vel = new Vector3f(0, value * moveSpeed, 0); |
|
|
|
|
Vector3f pos = cam.getLocation().clone(); |
|
|
|
@ -366,6 +423,12 @@ public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
cam.setLocation(pos); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Translate the camera left or forward by the specified amount. |
|
|
|
|
* |
|
|
|
|
* @param value translation amount |
|
|
|
|
* @param sideways true→left, false→forward |
|
|
|
|
*/ |
|
|
|
|
protected void moveCamera(float value, boolean sideways){ |
|
|
|
|
Vector3f vel = new Vector3f(); |
|
|
|
|
Vector3f pos = cam.getLocation().clone(); |
|
|
|
@ -385,6 +448,14 @@ public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
cam.setLocation(pos); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Callback to notify this controller of an analog input event. |
|
|
|
|
* |
|
|
|
|
* @param name name of the input event |
|
|
|
|
* @param value value of the axis (from 0 to 1) |
|
|
|
|
* @param tpf time per frame (in seconds) |
|
|
|
|
*/ |
|
|
|
|
@Override |
|
|
|
|
public void onAnalog(String name, float value, float tpf) { |
|
|
|
|
if (!enabled) |
|
|
|
|
return; |
|
|
|
@ -416,6 +487,14 @@ public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Callback to notify this controller of an action input event. |
|
|
|
|
* |
|
|
|
|
* @param name name of the input event |
|
|
|
|
* @param value true if the action is "pressed", false otherwise |
|
|
|
|
* @param tpf time per frame (in seconds) |
|
|
|
|
*/ |
|
|
|
|
@Override |
|
|
|
|
public void onAction(String name, boolean value, float tpf) { |
|
|
|
|
if (!enabled) |
|
|
|
|
return; |
|
|
|
@ -424,11 +503,10 @@ public class FlyByCamera implements AnalogListener, ActionListener { |
|
|
|
|
canRotate = value; |
|
|
|
|
inputManager.setCursorVisible(!value); |
|
|
|
|
} else if (name.equals(CameraInput.FLYCAM_INVERTY)) { |
|
|
|
|
// Toggle on the up.
|
|
|
|
|
// Invert the "up" direction.
|
|
|
|
|
if( !value ) { |
|
|
|
|
invertY = !invertY; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|