Only Orientation is supported currently

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9781 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
iwg..ic 12 years ago
parent 810164da46
commit 56bf97a7e2
  1. 507
      engine/src/android/com/jme3/input/android/AndroidSensorJoyInput.java
  2. 39
      engine/src/core/com/jme3/input/SensorJoystickAxis.java

@ -42,11 +42,12 @@ import android.view.Display;
import android.view.Surface; import android.view.Surface;
import android.view.WindowManager; import android.view.WindowManager;
import com.jme3.input.AbstractJoystick; import com.jme3.input.AbstractJoystick;
import com.jme3.input.DefaultJoystickAxis;
import com.jme3.input.InputManager; import com.jme3.input.InputManager;
import com.jme3.input.JoyInput; import com.jme3.input.JoyInput;
import com.jme3.input.Joystick; import com.jme3.input.Joystick;
import com.jme3.input.JoystickAxis; import com.jme3.input.JoystickAxis;
import com.jme3.input.JoystickButton; import com.jme3.input.SensorJoystickAxis;
import com.jme3.input.RawInputListener; import com.jme3.input.RawInputListener;
import com.jme3.input.event.JoyAxisEvent; import com.jme3.input.event.JoyAxisEvent;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
@ -60,21 +61,22 @@ import java.util.logging.Logger;
/** /**
* AndroidSensorJoyInput converts the Android Sensor system into Joystick events. * AndroidSensorJoyInput converts the Android Sensor system into Joystick events.
* Each sensor type is a seperate joystick that can be used with RawInputListener * A single joystick is configured and includes data for all configured sensors
* or the onAnalog listener. * as seperate axes of the joystick.
* *
* Device Orientation is not a physicsal sensor, but rather a calculation based * Each axis is named accounting to the static strings in SensorJoystickAxis.
* on the current accelerometer and magnetic sensor. Orientation is configured * Refer to the strings defined in SensorJoystickAxis for a list of supported
* as joystick[0], while physical sensors are configured with the joyId set to * sensors and their axis data. Each sensor type defined in SensorJoystickAxis
* the Android constant for the sensor type. * will be attempted to be configured. If the device does not support a particular
* sensor, the axis will return null if joystick.getAxis(String name) is called.
* *
* Right now, only the Orientation is exposed as a Joystick. * The joystick.getXAxis and getYAxis methods of the joystick are configured to
* return the device orientation values in the device's X and Y directions.
* *
* MainActivity needs the following line to enable Joysticks * This joystick also supports the joystick.rumble(rumbleAmount) method. In this
* joystickEventsEnabled = true; * case, when joystick.rumble(rumbleAmount) is called, the Android device will vibrate
* if the device has a built in vibrate motor.
* *
* Rumble needs the following line in the Manifest File
* <uses-permission android:name="android.permission.VIBRATE"/>
* Because Andorid does not allow for the user to define the intensity of the * Because Andorid does not allow for the user to define the intensity of the
* vibration, the rumble amount (ie strength) is converted into vibration pulses * vibration, the rumble amount (ie strength) is converted into vibration pulses
* The stronger the strength amount, the shorter the delay between pulses. If * The stronger the strength amount, the shorter the delay between pulses. If
@ -82,6 +84,15 @@ import java.util.logging.Logger;
* the vibration will a pulse of equal parts vibration and delay. * the vibration will a pulse of equal parts vibration and delay.
* To turn off vibration, set rumble amount to 0. * To turn off vibration, set rumble amount to 0.
* *
* MainActivity needs the following line to enable Joysticks on Android platforms
* joystickEventsEnabled = true;
* This is done to allow for battery conservation when sensor data is not required
* by the application.
*
* To use the joystick rumble feature, the following line needs to be
* added to the Android Manifest File
* <uses-permission android:name="android.permission.VIBRATE"/>
*
* @author iwgeric * @author iwgeric
*/ */
public class AndroidSensorJoyInput implements JoyInput, SensorEventListener { public class AndroidSensorJoyInput implements JoyInput, SensorEventListener {
@ -94,13 +105,12 @@ public class AndroidSensorJoyInput implements JoyInput, SensorEventListener {
private long maxRumbleTime = 250; // 250ms private long maxRumbleTime = 250; // 250ms
private RawInputListener listener = null; private RawInputListener listener = null;
private IntMap<SensorData> sensors = new IntMap<SensorData>(); private IntMap<SensorData> sensors = new IntMap<SensorData>();
private Joystick[] joysticks; private AndroidJoystick[] joysticks;
private boolean initialized = false;
private WindowManager window; private WindowManager window;
private Display disp; private Display disp;
private int lastRotation = 0; private int lastRotation = 0;
private final float[] orientationLastValues = new float[3]; private boolean initialized = false;
private final float[] maxOrientationValues = new float[] {FastMath.HALF_PI, FastMath.HALF_PI, FastMath.HALF_PI}; private boolean loaded = false;
private final ArrayList<JoyAxisEvent> eventQueue = new ArrayList<JoyAxisEvent>(); private final ArrayList<JoyAxisEvent> eventQueue = new ArrayList<JoyAxisEvent>();
@ -111,15 +121,11 @@ public class AndroidSensorJoyInput implements JoyInput, SensorEventListener {
int androidSensorType = -1; int androidSensorType = -1;
int androidSensorSpeed = SensorManager.SENSOR_DELAY_GAME; int androidSensorSpeed = SensorManager.SENSOR_DELAY_GAME;
Sensor sensor = null; Sensor sensor = null;
float maxRange = 0f;
float resolution = 0f;
float[] lastValues; float[] lastValues;
final Object valuesLock = new Object(); final Object valuesLock = new Object();
int joyID = -1; ArrayList<AndroidJoystickAxis> axes = new ArrayList<AndroidJoystickAxis>();
String joyName = "";
boolean enabled = false; boolean enabled = false;
boolean haveData = false; boolean haveData = false;
boolean createJoystick = false;
public SensorData(int androidSensorType, Sensor sensor) { public SensorData(int androidSensorType, Sensor sensor) {
this.androidSensorType = androidSensorType; this.androidSensorType = androidSensorType;
@ -137,7 +143,6 @@ public class AndroidSensorJoyInput implements JoyInput, SensorEventListener {
if (vibrator == null) { if (vibrator == null) {
logger.log(Level.INFO, "Vibrator Service not found."); logger.log(Level.INFO, "Vibrator Service not found.");
} }
initSensors();
} }
/** /**
@ -149,87 +154,6 @@ public class AndroidSensorJoyInput implements JoyInput, SensorEventListener {
disp = window.getDefaultDisplay(); disp = window.getDefaultDisplay();
} }
private void initSensors() {
SensorData sensorData;
List<Sensor> availSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
for (Sensor sensor: availSensors) {
logger.log(Level.INFO, "{0} Sensor is available, Type: {1}, Vendor: {2}, Version: {3}",
new Object[]{sensor.getName(), sensor.getType(), sensor.getVendor(), sensor.getVersion()});
}
sensorData = initSensor(Sensor.TYPE_MAGNETIC_FIELD);
if (sensorData != null) {
sensorData.joyName = "Device Direction";
sensorData.lastValues = new float[3];
sensorData.createJoystick = false;
}
sensorData = initSensor(Sensor.TYPE_ACCELEROMETER);
if (sensorData != null) {
sensorData.joyName = "Device Acceleration";
sensorData.lastValues = new float[3];
sensorData.createJoystick = false;
}
// sensorData = initSensor(Sensor.TYPE_GYROSCOPE);
// if (sensorData != null) {
// sensorData.joyName = "Device Rotation";
// sensorData.lastValues = new float[3];
// sensorData.createJoystick = false;
// }
//
// sensorData = initSensor(Sensor.TYPE_GRAVITY);
// if (sensorData != null) {
// sensorData.joyName = "Device Gravity";
// sensorData.lastValues = new float[3];
// sensorData.createJoystick = false;
// }
//
// sensorData = initSensor(Sensor.TYPE_LINEAR_ACCELERATION);
// if (sensorData != null) {
// sensorData.joyName = "Device Linear Acceleration";
// sensorData.lastValues = new float[3];
// sensorData.createJoystick = false;
// }
//
// sensorData = initSensor(Sensor.TYPE_ROTATION_VECTOR);
// if (sensorData != null) {
// sensorData.joyName = "Device Rotation Vector";
// sensorData.lastValues = new float[4];
// sensorData.createJoystick = false;
// }
//
// sensorData = initSensor(Sensor.TYPE_PROXIMITY);
// if (sensorData != null) {
// sensorData.joyName = "Device Proximity";
// sensorData.lastValues = new float[1];
// sensorData.createJoystick = false;
// }
//
// sensorData = initSensor(Sensor.TYPE_LIGHT);
// if (sensorData != null) {
// sensorData.joyName = "Device Light";
// sensorData.lastValues = new float[1];
// sensorData.createJoystick = false;
// }
//
// sensorData = initSensor(Sensor.TYPE_PRESSURE);
// if (sensorData != null) {
// sensorData.joyName = "Device Pressure";
// sensorData.lastValues = new float[1];
// sensorData.createJoystick = false;
// }
//
// sensorData = initSensor(Sensor.TYPE_TEMPERATURE);
// if (sensorData != null) {
// sensorData.joyName = "Device Temperature";
// sensorData.lastValues = new float[1];
// sensorData.createJoystick = false;
// }
}
private SensorData initSensor(int sensorType) { private SensorData initSensor(int sensorType) {
boolean success = false; boolean success = false;
@ -301,8 +225,10 @@ public class AndroidSensorJoyInput implements JoyInput, SensorEventListener {
*/ */
public void pauseSensors() { public void pauseSensors() {
for (Entry entry: sensors) { for (Entry entry: sensors) {
if (entry.getKey() != Sensor.TYPE_ORIENTATION) {
unRegisterListener(entry.getKey()); unRegisterListener(entry.getKey());
} }
}
if (vibrator != null && vibratorActive) { if (vibrator != null && vibratorActive) {
vibrator.cancel(); vibrator.cancel();
} }
@ -314,9 +240,11 @@ public class AndroidSensorJoyInput implements JoyInput, SensorEventListener {
*/ */
public void resumeSensors() { public void resumeSensors() {
for (Entry entry: sensors) { for (Entry entry: sensors) {
if (entry.getKey() != Sensor.TYPE_ORIENTATION) {
registerListener(entry.getKey()); registerListener(entry.getKey());
} }
} }
}
/* /*
* Allows the orientation data to be rotated based on the current device * Allows the orientation data to be rotated based on the current device
@ -412,12 +340,13 @@ public class AndroidSensorJoyInput implements JoyInput, SensorEventListener {
*/ */
private boolean updateOrientation() { private boolean updateOrientation() {
SensorData sensorData; SensorData sensorData;
AndroidJoystickAxis axis;
final float[] curInclinationMat = new float[16]; final float[] curInclinationMat = new float[16];
final float[] curRotationMat = new float[16]; final float[] curRotationMat = new float[16];
final float[] rotatedRotationMat = new float[16]; final float[] rotatedRotationMat = new float[16];
final float[] accValues = new float[3]; final float[] accValues = new float[3];
final float[] magValues = new float[3]; final float[] magValues = new float[3];
final float[] deltaOrientation = new float[3]; final float[] orderedOrientation = new float[3];
// if the Gravity Sensor is available, use it for orientation, if not // if the Gravity Sensor is available, use it for orientation, if not
// use the accelerometer // use the accelerometer
@ -455,80 +384,42 @@ public class AndroidSensorJoyInput implements JoyInput, SensorEventListener {
// logger.log(Level.INFO, "Orientation Values: {0}, {1}, {2}", // logger.log(Level.INFO, "Orientation Values: {0}, {1}, {2}",
// new Object[]{orientValues[0], orientValues[1], orientValues[2]}); // new Object[]{orientValues[0], orientValues[1], orientValues[2]});
//values[0]: Azimuth - (the compass bearing east of magnetic north)
//values[1]: Pitch, rotation around x-axis (is the phone leaning forward or back)
//values[2]: Roll, rotation around y-axis (is the phone leaning over on its left or right side)
//Azimuth (degrees of rotation around the z axis). This is the angle between magnetic north
//and the device's y axis. For example, if the device's y axis is aligned with magnetic north
//this value is 0, and if the device's y axis is pointing south this value is 180.
//Likewise, when the y axis is pointing east this value is 90 and when it is pointing west
//this value is 270.
//Pitch (degrees of rotation around the x axis). This value is positive when the positive
//z axis rotates toward the positive y axis, and it is negative when the positive z axis
//rotates toward the negative y axis. The range of values is 180 degrees to -180 degrees.
//Roll (degrees of rotation around the y axis). This value is positive when the
//positive z axis rotates toward the positive x axis, and it is negative when the
//positive z axis rotates toward the negative x axis. The range of values
//is 90 degrees to -90 degrees.
// // Azimuth scaling
// if (orientValues[0]<0) {
// orientValues[0] += FastMath.TWO_PI;
// }
//
// // Pitch scaling
// if (orientValues[1] < -FastMath.HALF_PI) {
// orientValues[1] += (-2*(FastMath.HALF_PI+orientValues[1]));
// } else if (orientValues[1] > FastMath.HALF_PI) {
// orientValues[1] += (2*(FastMath.HALF_PI-orientValues[1]));
// }
//
// // Roll scaling
// // NOT NEEDED
// need to reorder to make it x, y, z order instead of z, x, y order // need to reorder to make it x, y, z order instead of z, x, y order
deltaOrientation[0] = orientValues[1] - orientationLastValues[1]; orderedOrientation[0] = orientValues[1];
deltaOrientation[1] = orientValues[2] - orientationLastValues[2]; orderedOrientation[1] = orientValues[2];
deltaOrientation[2] = orientValues[0] - orientationLastValues[0]; orderedOrientation[2] = orientValues[0];
// logger.log(Level.INFO, "Sensor Values x:{0}, y:{1}, z:{2}, deg x:{3}, y:{4}, z:{5}", sensorData = sensors.get(Sensor.TYPE_ORIENTATION);
// new Object[]{orientValues[1], orientValues[2], orientValues[0], if (sensorData != null && sensorData.axes.size() > 0) {
// orientValues[1]*FastMath.RAD_TO_DEG, orientValues[2]*FastMath.RAD_TO_DEG, orientValues[0]*FastMath.RAD_TO_DEG}); for (int i=0; i<orderedOrientation.length; i++) {
axis = sensorData.axes.get(i);
if (axis != null) {
axis.setCurRawValue(orderedOrientation[i]);
if (!sensorData.haveData) {
sensorData.haveData = true;
} else {
synchronized (eventQueue){ synchronized (eventQueue){
// only send data to inputManager if it is different than last time if (axis.isChanged()) {
// orientValues[1] is the X axis -> JoyAxisEvent Axis 0 eventQueue.add(new JoyAxisEvent(axis, axis.getJoystickAxisValue()));
// orientValues[2] is the Y axis -> JoyAxisEvent Axis 1
// orientValues[0] is the Z axis -> JoyAxisEvent Axis 2
if (Math.abs(deltaOrientation[0]) > FastMath.ZERO_TOLERANCE) {
// FIXME: need to be able to pass the axis instead of raw IDs here
//eventQueue.add(new JoyAxisEvent(0, 0, orientValues[1] / maxOrientationValues[1]));
} }
if (Math.abs(deltaOrientation[1]) > FastMath.ZERO_TOLERANCE) {
// FIXME: need to be able to pass the axis instead of raw IDs here
//eventQueue.add(new JoyAxisEvent(0, 1, orientValues[2] / maxOrientationValues[2]));
} }
if (Math.abs(deltaOrientation[2]) > FastMath.ZERO_TOLERANCE) {
// FIXME: need to be able to pass the axis instead of raw IDs here
//eventQueue.add(new JoyAxisEvent(0, 2, orientValues[0] / maxOrientationValues[0]));
} }
} }
}
orientationLastValues[0] = orientValues[0]; } else if (sensorData != null) {
orientationLastValues[1] = orientValues[1]; if (!sensorData.haveData) {
orientationLastValues[2] = orientValues[2]; sensorData.haveData = true;
}
}
return true; return true;
} else { } else {
//logger.log(Level.INFO, "remapCoordinateSystem failed"); logger.log(Level.INFO, "remapCoordinateSystem failed");
} }
} else { } else {
//logger.log(Level.INFO, "getRotationMatrix returned false"); logger.log(Level.INFO, "getRotationMatrix returned false");
} }
return false; return false;
@ -565,65 +456,118 @@ public class AndroidSensorJoyInput implements JoyInput, SensorEventListener {
public Joystick[] loadJoysticks(InputManager inputManager) { public Joystick[] loadJoysticks(InputManager inputManager) {
this.inputManager = inputManager; this.inputManager = inputManager;
int joyIndex = 1; // start with 1 for orientation initSensorManager();
for (Entry entry: sensors) {
SensorData sensorData = (SensorData)entry.getValue();
if (sensorData != null) {
if (sensorData.sensor != null && sensorData.createJoystick) {
joyIndex++; // add 1 for each of the physical sensors configured and enabled
}
}
}
joysticks = new Joystick[joyIndex]; SensorData sensorData;
joyIndex = 0; List<Joystick> list = new ArrayList<Joystick>();
Joystick joystick; AndroidJoystick joystick;
AndroidJoystickAxis axis;
// manually create a joystick for orientation since orientation
// is not an actual physical sensor
// Do the orientation joystick first so it is compatible with PC systems
// that only have a single joystick configured.
joystick = new AndroidJoystick(inputManager, joystick = new AndroidJoystick(inputManager,
this, this,
joyIndex, list.size(),
"Device Orientation" ); //, "AndroidSensorsJoystick");
//0, // button count list.add(joystick);
//3, // axis count
//0, 1); // xAxis, yAxis
joysticks[joyIndex] = joystick;
joyIndex++;
// create a joystick for each physical sensor configured
for (Entry entry: sensors) {
SensorData sensorData = (SensorData)entry.getValue();
if (sensorData != null) {
if (sensorData.sensor != null && sensorData.createJoystick) {
sensorData.joyID = joyIndex;
joystick = new AndroidJoystick(inputManager,
this,
joyIndex,
sensorData.joyName );//,
//0, // button count
//sensorData.lastValues.length, // axis count
//0, 1); // xAxis, yAxis
joysticks[joyIndex] = joystick;
joyIndex++;
List<Sensor> availSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
for (Sensor sensor: availSensors) {
logger.log(Level.INFO, "{0} Sensor is available, Type: {1}, Vendor: {2}, Version: {3}",
new Object[]{sensor.getName(), sensor.getType(), sensor.getVendor(), sensor.getVersion()});
} }
// manually create orientation sensor data since orientation is not a physical sensor
sensorData = new SensorData(Sensor.TYPE_ORIENTATION, null);
sensorData.lastValues = new float[3];
sensors.put(Sensor.TYPE_ORIENTATION, sensorData);
axis = joystick.addAxis(SensorJoystickAxis.ORIENTATION_X, SensorJoystickAxis.ORIENTATION_X, joystick.getAxisCount(), FastMath.HALF_PI);
joystick.setYAxis(axis); // joystick y axis = rotation around device x axis
sensorData.axes.add(axis);
axis = joystick.addAxis(SensorJoystickAxis.ORIENTATION_Y, SensorJoystickAxis.ORIENTATION_Y, joystick.getAxisCount(), FastMath.HALF_PI);
joystick.setXAxis(axis); // joystick x axis = rotation around device y axis
sensorData.axes.add(axis);
axis = joystick.addAxis(SensorJoystickAxis.ORIENTATION_Z, SensorJoystickAxis.ORIENTATION_Z, joystick.getAxisCount(), FastMath.HALF_PI);
sensorData.axes.add(axis);
// add axes for physical sensors
sensorData = initSensor(Sensor.TYPE_MAGNETIC_FIELD);
if (sensorData != null) {
sensorData.lastValues = new float[3];
sensors.put(Sensor.TYPE_MAGNETIC_FIELD, sensorData);
// axis = joystick.addAxis(SensorJoystickAxis.MAGNETIC_X, "MagneticField_X", joystick.getAxisCount(), 1f);
// sensorData.axes.add(axis);
// axis = joystick.addAxis(SensorJoystickAxis.MAGNETIC_Y, "MagneticField_Y", joystick.getAxisCount(), 1f);
// sensorData.axes.add(axis);
// axis = joystick.addAxis(SensorJoystickAxis.MAGNETIC_Z, "MagneticField_Z", joystick.getAxisCount(), 1f);
// sensorData.axes.add(axis);
} }
sensorData = initSensor(Sensor.TYPE_ACCELEROMETER);
if (sensorData != null) {
sensorData.lastValues = new float[3];
sensors.put(Sensor.TYPE_ACCELEROMETER, sensorData);
// axis = joystick.addAxis(SensorJoystickAxis.ACCELEROMETER_X, "Accelerometer_X", joystick.getAxisCount(), 1f);
// sensorData.axes.add(axis);
// axis = joystick.addAxis(SensorJoystickAxis.ACCELEROMETER_Y, "Accelerometer_Y", joystick.getAxisCount(), 1f);
// sensorData.axes.add(axis);
// axis = joystick.addAxis(SensorJoystickAxis.ACCELEROMETER_Z, "Accelerometer_Z", joystick.getAxisCount(), 1f);
// sensorData.axes.add(axis);
} }
// sensorData = initSensor(Sensor.TYPE_GYROSCOPE);
// if (sensorData != null) {
// sensorData.lastValues = new float[3];
// }
//
// sensorData = initSensor(Sensor.TYPE_GRAVITY);
// if (sensorData != null) {
// sensorData.lastValues = new float[3];
// }
//
// sensorData = initSensor(Sensor.TYPE_LINEAR_ACCELERATION);
// if (sensorData != null) {
// sensorData.lastValues = new float[3];
// }
//
// sensorData = initSensor(Sensor.TYPE_ROTATION_VECTOR);
// if (sensorData != null) {
// sensorData.lastValues = new float[4];
// }
//
// sensorData = initSensor(Sensor.TYPE_PROXIMITY);
// if (sensorData != null) {
// sensorData.lastValues = new float[1];
// }
//
// sensorData = initSensor(Sensor.TYPE_LIGHT);
// if (sensorData != null) {
// sensorData.lastValues = new float[1];
// }
//
// sensorData = initSensor(Sensor.TYPE_PRESSURE);
// if (sensorData != null) {
// sensorData.lastValues = new float[1];
// }
//
// sensorData = initSensor(Sensor.TYPE_TEMPERATURE);
// if (sensorData != null) {
// sensorData.lastValues = new float[1];
// }
joysticks = list.toArray( new AndroidJoystick[list.size()] );
loaded = true;
return joysticks; return joysticks;
} }
public void initialize() { public void initialize() {
logger.log(Level.INFO, "Doing Initialize.");
initSensorManager();
initialized = true; initialized = true;
loaded = false;
} }
public void update() { public void update() {
if (!loaded) {
return;
}
updateOrientation(); updateOrientation();
synchronized (eventQueue){ synchronized (eventQueue){
// flush events to listener // flush events to listener
@ -644,6 +588,8 @@ public class AndroidSensorJoyInput implements JoyInput, SensorEventListener {
} }
sensors.clear(); sensors.clear();
eventQueue.clear(); eventQueue.clear();
initialized = false;
loaded = false;
joysticks = null; joysticks = null;
} }
@ -664,7 +610,7 @@ public class AndroidSensorJoyInput implements JoyInput, SensorEventListener {
// Start of Android SensorEventListener methods // Start of Android SensorEventListener methods
public void onSensorChanged(SensorEvent se) { public void onSensorChanged(SensorEvent se) {
if (!initialized) { if (!initialized || !loaded) {
return; return;
} }
@ -673,34 +619,32 @@ public class AndroidSensorJoyInput implements JoyInput, SensorEventListener {
SensorData sensorData = sensors.get(sensorType); SensorData sensorData = sensors.get(sensorType);
if (sensorData != null && sensorData.sensor.equals(se.sensor) && sensorData.enabled) { if (sensorData != null && sensorData.sensor.equals(se.sensor) && sensorData.enabled) {
if (!sensorData.haveData) { synchronized(sensorData.valuesLock) {
sensorData.haveData = true;
} else {
if (sensorData.joyID != -1) {
final float[] deltaValues = new float[sensorData.lastValues.length];
for (int i=0; i<sensorData.lastValues.length; i++) { for (int i=0; i<sensorData.lastValues.length; i++) {
deltaValues[i] = se.values[i] - sensorData.lastValues[i]; sensorData.lastValues[i] = se.values[i];
}
} }
// TODO: need to scale physical sensor data to fit within if (sensorData != null && sensorData.axes.size() > 0) {
// joystick model of providing values of 0 to 1 AndroidJoystickAxis axis;
for (int i=0; i<se.values.length; i++) {
axis = sensorData.axes.get(i);
if (axis != null) {
axis.setCurRawValue(se.values[i]);
if (!sensorData.haveData) {
sensorData.haveData = true;
} else {
synchronized (eventQueue){ synchronized (eventQueue){
for (int i=0; i<deltaValues.length; i++) { if (axis.isChanged()) {
if (FastMath.abs(deltaValues[i]) > sensorData.lastValues[i] + FastMath.ZERO_TOLERANCE) { eventQueue.add(new JoyAxisEvent(axis, axis.getJoystickAxisValue()));
// FIXME: need to be able to pass the axis instead of raw IDs here
//eventQueue.add(new JoyAxisEvent(sensorData.joyID, i, se.values[i]));
} }
} }
} }
} }
} }
} else if (sensorData != null) {
synchronized(sensorData.valuesLock) { if (!sensorData.haveData) {
for (int i=0; i<sensorData.lastValues.length; i++) { sensorData.haveData = true;
sensorData.lastValues[i] = se.values[i];
} }
} }
@ -711,44 +655,133 @@ public class AndroidSensorJoyInput implements JoyInput, SensorEventListener {
int sensorType = sensor.getType(); int sensorType = sensor.getType();
SensorData sensorData = sensors.get(sensorType); SensorData sensorData = sensors.get(sensorType);
if (sensorData != null) { if (sensorData != null) {
logger.log(Level.INFO, "onAccuracyChanged for {0} ({1}): accuracy: {2}", logger.log(Level.INFO, "onAccuracyChanged for {0}: accuracy: {1}",
new Object[]{sensor.toString(), sensorData.joyName, i}); new Object[]{sensor.toString(), i});
logger.log(Level.INFO, "MaxRange: {0}, Resolution: {1}", logger.log(Level.INFO, "MaxRange: {0}, Resolution: {1}",
new Object[]{sensor.getMaximumRange(), sensor.getResolution()}); new Object[]{sensor.getMaximumRange(), sensor.getResolution()});
if (sensorData.sensor != null && sensorData.sensor.equals(sensor)) {
sensorData.resolution = sensor.getResolution();
sensorData.maxRange = sensor.getMaximumRange();
}
} }
} }
// End of SensorEventListener methods // End of SensorEventListener methods
protected class AndroidJoystick extends AbstractJoystick { protected class AndroidJoystick extends AbstractJoystick {
private JoystickAxis nullAxis;
private JoystickAxis xAxis;
private JoystickAxis yAxis;
private JoystickAxis povX;
private JoystickAxis povY;
public AndroidJoystick( InputManager inputManager, JoyInput joyInput, public AndroidJoystick( InputManager inputManager, JoyInput joyInput,
int joyId, String name){ int joyId, String name){
super( inputManager, joyInput, joyId, name ); super( inputManager, joyInput, joyId, name );
this.nullAxis = new DefaultJoystickAxis( getInputManager(), this, -1,
"Null", "null", false, false, 0 );
this.xAxis = nullAxis;
this.yAxis = nullAxis;
this.povX = nullAxis;
this.povY = nullAxis;
}
protected AndroidJoystickAxis addAxis(String axisName, String logicalName, int axisNum, float maxRawValue) {
AndroidJoystickAxis axis;
axis = new AndroidJoystickAxis(
inputManager, // InputManager (InputManager)
this, // parent Joystick (Joystick)
axisNum, // Axis Index (int)
axisName, // Axis Name (String)
logicalName, // Logical ID (String)
true, // isAnalog (boolean)
false, // isRelative (boolean)
0.01f, // Axis Deadzone (float)
maxRawValue); // Axis Max Raw Value (float)
super.addAxis(axis);
return axis;
}
protected void setXAxis(JoystickAxis axis) {
xAxis = axis;
}
protected void setYAxis(JoystickAxis axis) {
yAxis = axis;
} }
@Override @Override
public JoystickAxis getXAxis() { public JoystickAxis getXAxis() {
throw new UnsupportedOperationException(); return xAxis;
} }
@Override @Override
public JoystickAxis getYAxis() { public JoystickAxis getYAxis() {
throw new UnsupportedOperationException(); return yAxis;
} }
@Override @Override
public JoystickAxis getPovXAxis() { public JoystickAxis getPovXAxis() {
throw new UnsupportedOperationException(); return povX;
} }
@Override @Override
public JoystickAxis getPovYAxis() { public JoystickAxis getPovYAxis() {
throw new UnsupportedOperationException(); return povY;
}
}
public class AndroidJoystickAxis extends DefaultJoystickAxis implements SensorJoystickAxis {
float zeroRawValue = 0f;
float curRawValue = 0f;
float lastRawValue = 0f;
boolean hasChanged = false;
float maxRawValue = FastMath.HALF_PI;
boolean enabled = true;
public AndroidJoystickAxis(InputManager inputManager, Joystick parent,
int axisIndex, String name, String logicalId,
boolean isAnalog, boolean isRelative, float deadZone,
float maxRawValue) {
super(inputManager, parent, axisIndex, name, logicalId, isAnalog, isRelative, deadZone);
this.maxRawValue = maxRawValue;
}
public float getMaxRawValue() {
return maxRawValue;
}
public void setMaxRawValue(float maxRawValue) {
this.maxRawValue = maxRawValue;
}
protected float getLastRawValue() {
return lastRawValue;
} }
protected void setCurRawValue(float rawValue) {
this.curRawValue = rawValue;
if (Math.abs(curRawValue - lastRawValue) > getDeadZone()) {
hasChanged = true;
lastRawValue = curRawValue;
} else {
hasChanged = false;
}
}
protected float getJoystickAxisValue() {
return (lastRawValue-zeroRawValue) / maxRawValue;
}
protected boolean isChanged() {
return hasChanged;
}
public void calibrateCenter() {
zeroRawValue = lastRawValue;
}
} }
} }

@ -0,0 +1,39 @@
package com.jme3.input;
/**
* Represents a joystick axis based on an external sensor
* (ie. Android Device Orientation sensors)
* Sensor joystick axes can be calibrated to
* set the zero position dynamically
*
* @author iwgeric
*/
public interface SensorJoystickAxis {
public static String ORIENTATION_X = "Orientation_X";
public static String ORIENTATION_Y = "Orientation_Y";
public static String ORIENTATION_Z = "Orientation_Z";
/**
* Calibrates the axis to the current value. Future axis values will be
* sent as a delta from the calibratation value.
*/
public void calibrateCenter();
/**
* Method to allow users to set the raw sensor value that represents
* the maximum joystick axis value. Values sent to InputManager are scaled
* using the maxRawValue.
*
* @param maxRawValue Raw sensor value that will be used to scale joystick axis value
*/
public void setMaxRawValue(float maxRawValue);
/**
* Returns the current maximum raw sensor value that is being used to scale
* the joystick axis value.
*
* @return maxRawValue The current maximum raw sensor value used for scaling the joystick axis value
*/
public float getMaxRawValue();
}
Loading…
Cancel
Save