diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidGestureHandler.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidGestureProcessor.java
similarity index 51%
rename from jme3-android/src/main/java/com/jme3/input/android/AndroidGestureHandler.java
rename to jme3-android/src/main/java/com/jme3/input/android/AndroidGestureProcessor.java
index d233836a5..2c0367946 100644
--- a/jme3-android/src/main/java/com/jme3/input/android/AndroidGestureHandler.java
+++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidGestureProcessor.java
@@ -35,314 +35,240 @@ package com.jme3.input.android;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
-import android.view.View;
-import com.jme3.input.event.InputEvent;
-import com.jme3.input.event.MouseMotionEvent;
import com.jme3.input.event.TouchEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* AndroidGestureHandler uses Gesture type listeners to create jME TouchEvents
- * for gestures. This class is designed to handle the gestures supported
+ * for gestures. This class is designed to handle the gestures supported
* on Android rev 9 (Android 2.3). Extend this class to add functionality
* added by Android after rev 9.
- *
+ *
* @author iwgeric
*/
-public class AndroidGestureHandler implements
- GestureDetector.OnGestureListener,
+public class AndroidGestureProcessor implements
+ GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener,
ScaleGestureDetector.OnScaleGestureListener {
- private static final Logger logger = Logger.getLogger(AndroidGestureHandler.class.getName());
- private AndroidInputHandler androidInput;
- private GestureDetector gestureDetector;
- private ScaleGestureDetector scaleDetector;
+ private static final Logger logger = Logger.getLogger(AndroidGestureProcessor.class.getName());
+
+ private AndroidTouchInput touchInput;
float gestureDownX = -1f;
float gestureDownY = -1f;
float scaleStartX = -1f;
float scaleStartY = -1f;
- public AndroidGestureHandler(AndroidInputHandler androidInput) {
- this.androidInput = androidInput;
- }
-
- public void initialize() {
- }
-
- public void destroy() {
- setView(null);
- }
-
- public void setView(View view) {
- if (view != null) {
- gestureDetector = new GestureDetector(view.getContext(), this);
- scaleDetector = new ScaleGestureDetector(view.getContext(), this);
- } else {
- gestureDetector = null;
- scaleDetector = null;
- }
- }
-
- public void detectGesture(MotionEvent event) {
- if (gestureDetector != null && scaleDetector != null) {
- gestureDetector.onTouchEvent(event);
- scaleDetector.onTouchEvent(event);
- }
- }
-
- private int getPointerIndex(MotionEvent event) {
- return (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
- >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- }
-
- private int getPointerId(MotionEvent event) {
- return event.getPointerId(getPointerIndex(event));
+ public AndroidGestureProcessor(AndroidTouchInput touchInput) {
+ this.touchInput = touchInput;
}
-
- private void processEvent(TouchEvent event) {
- // Add the touch event
- androidInput.addEvent(event);
- if (androidInput.isSimulateMouse()) {
- InputEvent mouseEvent = generateMouseEvent(event);
- if (mouseEvent != null) {
- // Add the mouse event
- androidInput.addEvent(mouseEvent);
- }
- }
- }
-
- // TODO: Ring Buffer for mouse events?
- private InputEvent generateMouseEvent(TouchEvent event) {
- InputEvent inputEvent = null;
- int newX;
- int newY;
- int newDX;
- int newDY;
- if (androidInput.isMouseEventsInvertX()) {
- newX = (int) (androidInput.invertX(event.getX()));
- newDX = (int)event.getDeltaX() * -1;
- } else {
- newX = (int) event.getX();
- newDX = (int)event.getDeltaX();
- }
- int wheel = (int) (event.getScaleSpan()); // might need to scale to match mouse wheel
- int dWheel = (int) (event.getDeltaScaleSpan()); // might need to scale to match mouse wheel
-
- if (androidInput.isMouseEventsInvertY()) {
- newY = (int) (androidInput.invertY(event.getY()));
- newDY = (int)event.getDeltaY() * -1;
- } else {
- newY = (int) event.getY();
- newDY = (int)event.getDeltaY();
- }
-
- switch (event.getType()) {
- case SCALE_MOVE:
- inputEvent = new MouseMotionEvent(newX, newY, newDX, newDY, wheel, dWheel);
- inputEvent.setTime(event.getTime());
- break;
- }
-
- return inputEvent;
- }
-
/* Events from onGestureListener */
-
+
+ @Override
public boolean onDown(MotionEvent event) {
// start of all GestureListeners. Not really a gesture by itself
// so we don't create an event.
// However, reset the scaleInProgress here since this is the beginning
// of a series of gesture events.
-// logger.log(Level.INFO, "onDown pointerId: {0}, action: {1}, x: {2}, y: {3}",
-// new Object[]{getPointerId(event), getAction(event), event.getX(), event.getY()});
- gestureDownX = androidInput.getJmeX(event.getX());
- gestureDownY = androidInput.invertY(androidInput.getJmeY(event.getY()));
+// logger.log(Level.INFO, "onDown pointerId: {0}, action: {1}, x: {2}, y: {3}",
+// new Object[]{touchInput.getPointerId(event), touchInput.getAction(event), event.getX(), event.getY()});
+ gestureDownX = touchInput.getJmeX(event.getX());
+ gestureDownY = touchInput.invertY(touchInput.getJmeY(event.getY()));
return true;
}
+ @Override
public boolean onSingleTapUp(MotionEvent event) {
// Up of single tap. May be followed by a double tap later.
// use onSingleTapConfirmed instead.
-// logger.log(Level.INFO, "onSingleTapUp pointerId: {0}, action: {1}, x: {2}, y: {3}",
-// new Object[]{getPointerId(event), getAction(event), event.getX(), event.getY()});
+// logger.log(Level.INFO, "onSingleTapUp pointerId: {0}, action: {1}, x: {2}, y: {3}",
+// new Object[]{touchInput.getPointerId(event), touchInput.getAction(event), event.getX(), event.getY()});
return true;
}
+ @Override
public void onShowPress(MotionEvent event) {
-// logger.log(Level.INFO, "onShowPress pointerId: {0}, action: {1}, x: {2}, y: {3}",
-// new Object[]{getPointerId(event), getAction(event), event.getX(), event.getY()});
- float jmeX = androidInput.getJmeX(event.getX());
- float jmeY = androidInput.invertY(androidInput.getJmeY(event.getY()));
- TouchEvent touchEvent = androidInput.getFreeTouchEvent();
+// logger.log(Level.INFO, "onShowPress pointerId: {0}, action: {1}, x: {2}, y: {3}",
+// new Object[]{touchInput.getPointerId(event), touchInput.getAction(event), event.getX(), event.getY()});
+ float jmeX = touchInput.getJmeX(event.getX());
+ float jmeY = touchInput.invertY(touchInput.getJmeY(event.getY()));
+ TouchEvent touchEvent = touchInput.getFreeTouchEvent();
touchEvent.set(TouchEvent.Type.SHOWPRESS, jmeX, jmeY, 0, 0);
- touchEvent.setPointerId(getPointerId(event));
+ touchEvent.setPointerId(touchInput.getPointerId(event));
touchEvent.setTime(event.getEventTime());
touchEvent.setPressure(event.getPressure());
- processEvent(touchEvent);
+ touchInput.addEvent(touchEvent);
}
+ @Override
public void onLongPress(MotionEvent event) {
-// logger.log(Level.INFO, "onLongPress pointerId: {0}, action: {1}, x: {2}, y: {3}",
-// new Object[]{getPointerId(event), getAction(event), event.getX(), event.getY()});
- float jmeX = androidInput.getJmeX(event.getX());
- float jmeY = androidInput.invertY(androidInput.getJmeY(event.getY()));
- TouchEvent touchEvent = androidInput.getFreeTouchEvent();
+// logger.log(Level.INFO, "onLongPress pointerId: {0}, action: {1}, x: {2}, y: {3}",
+// new Object[]{touchInput.getPointerId(event), touchInput.getAction(event), event.getX(), event.getY()});
+ float jmeX = touchInput.getJmeX(event.getX());
+ float jmeY = touchInput.invertY(touchInput.getJmeY(event.getY()));
+ TouchEvent touchEvent = touchInput.getFreeTouchEvent();
touchEvent.set(TouchEvent.Type.LONGPRESSED, jmeX, jmeY, 0, 0);
- touchEvent.setPointerId(getPointerId(event));
+ touchEvent.setPointerId(touchInput.getPointerId(event));
touchEvent.setTime(event.getEventTime());
touchEvent.setPressure(event.getPressure());
- processEvent(touchEvent);
+ touchInput.addEvent(touchEvent);
}
+ @Override
public boolean onScroll(MotionEvent startEvent, MotionEvent endEvent, float distX, float distY) {
// if not scaleInProgess, send scroll events. This is to avoid sending
// scroll events when one of the fingers is lifted just before the other one.
// Avoids sending the scroll for that brief period of time.
// Return true so that the next event doesn't accumulate the distX and distY values.
- // Apparantly, both distX and distY are negative.
+ // Apparantly, both distX and distY are negative.
// Negate distX to get the real value, but leave distY negative to compensate
// for the fact that jME has y=0 at bottom where Android has y=0 at top.
-// if (!scaleInProgress) {
- if (!scaleDetector.isInProgress()) {
-// logger.log(Level.INFO, "onScroll pointerId: {0}, startAction: {1}, startX: {2}, startY: {3}, endAction: {4}, endX: {5}, endY: {6}, dx: {7}, dy: {8}",
-// new Object[]{getPointerId(startEvent), getAction(startEvent), startEvent.getX(), startEvent.getY(), getAction(endEvent), endEvent.getX(), endEvent.getY(), distX, distY});
+ if (!touchInput.getScaleDetector().isInProgress()) {
+// logger.log(Level.INFO, "onScroll pointerId: {0}, startAction: {1}, startX: {2}, startY: {3}, endAction: {4}, endX: {5}, endY: {6}, dx: {7}, dy: {8}",
+// new Object[]{touchInput.getPointerId(startEvent), touchInput.getAction(startEvent), startEvent.getX(), startEvent.getY(), touchInput.getAction(endEvent), endEvent.getX(), endEvent.getY(), distX, distY});
- float jmeX = androidInput.getJmeX(endEvent.getX());
- float jmeY = androidInput.invertY(androidInput.getJmeY(endEvent.getY()));
- TouchEvent touchEvent = androidInput.getFreeTouchEvent();
- touchEvent.set(TouchEvent.Type.SCROLL, jmeX, jmeY, androidInput.getJmeX(-distX), androidInput.getJmeY(distY));
- touchEvent.setPointerId(getPointerId(endEvent));
+ float jmeX = touchInput.getJmeX(endEvent.getX());
+ float jmeY = touchInput.invertY(touchInput.getJmeY(endEvent.getY()));
+ TouchEvent touchEvent = touchInput.getFreeTouchEvent();
+ touchEvent.set(TouchEvent.Type.SCROLL, jmeX, jmeY, touchInput.getJmeX(-distX), touchInput.getJmeY(distY));
+ touchEvent.setPointerId(touchInput.getPointerId(endEvent));
touchEvent.setTime(endEvent.getEventTime());
touchEvent.setPressure(endEvent.getPressure());
- processEvent(touchEvent);
+ touchInput.addEvent(touchEvent);
}
return true;
}
+ @Override
public boolean onFling(MotionEvent startEvent, MotionEvent endEvent, float velocityX, float velocityY) {
// Fling happens only once at the end of the gesture (all fingers up).
// Fling returns the velocity of the finger movement in pixels/sec.
// Therefore, the dX and dY values are actually velocity instead of distance values
// Since this does not track the movement, use the start position and velocity values.
-
-// logger.log(Level.INFO, "onFling pointerId: {0}, startAction: {1}, startX: {2}, startY: {3}, endAction: {4}, endX: {5}, endY: {6}, velocityX: {7}, velocityY: {8}",
-// new Object[]{getPointerId(startEvent), getAction(startEvent), startEvent.getX(), startEvent.getY(), getAction(endEvent), endEvent.getX(), endEvent.getY(), velocityX, velocityY});
- float jmeX = androidInput.getJmeX(startEvent.getX());
- float jmeY = androidInput.invertY(androidInput.getJmeY(startEvent.getY()));
- TouchEvent touchEvent = androidInput.getFreeTouchEvent();
+// logger.log(Level.INFO, "onFling pointerId: {0}, startAction: {1}, startX: {2}, startY: {3}, endAction: {4}, endX: {5}, endY: {6}, velocityX: {7}, velocityY: {8}",
+// new Object[]{touchInput.getPointerId(startEvent), touchInput.getAction(startEvent), startEvent.getX(), startEvent.getY(), touchInput.getAction(endEvent), endEvent.getX(), endEvent.getY(), velocityX, velocityY});
+
+ float jmeX = touchInput.getJmeX(startEvent.getX());
+ float jmeY = touchInput.invertY(touchInput.getJmeY(startEvent.getY()));
+ TouchEvent touchEvent = touchInput.getFreeTouchEvent();
touchEvent.set(TouchEvent.Type.FLING, jmeX, jmeY, velocityX, velocityY);
- touchEvent.setPointerId(getPointerId(endEvent));
+ touchEvent.setPointerId(touchInput.getPointerId(endEvent));
touchEvent.setTime(endEvent.getEventTime());
touchEvent.setPressure(endEvent.getPressure());
- processEvent(touchEvent);
+ touchInput.addEvent(touchEvent);
return true;
}
/* Events from onDoubleTapListener */
-
+
+ @Override
public boolean onSingleTapConfirmed(MotionEvent event) {
// Up of single tap when no double tap followed.
-// logger.log(Level.INFO, "onSingleTapConfirmed pointerId: {0}, action: {1}, x: {2}, y: {3}",
-// new Object[]{getPointerId(event), getAction(event), event.getX(), event.getY()});
- float jmeX = androidInput.getJmeX(event.getX());
- float jmeY = androidInput.invertY(androidInput.getJmeY(event.getY()));
- TouchEvent touchEvent = androidInput.getFreeTouchEvent();
+// logger.log(Level.INFO, "onSingleTapConfirmed pointerId: {0}, action: {1}, x: {2}, y: {3}",
+// new Object[]{touchInput.getPointerId(event), touchInput.getAction(event), event.getX(), event.getY()});
+ float jmeX = touchInput.getJmeX(event.getX());
+ float jmeY = touchInput.invertY(touchInput.getJmeY(event.getY()));
+ TouchEvent touchEvent = touchInput.getFreeTouchEvent();
touchEvent.set(TouchEvent.Type.TAP, jmeX, jmeY, 0, 0);
- touchEvent.setPointerId(getPointerId(event));
+ touchEvent.setPointerId(touchInput.getPointerId(event));
touchEvent.setTime(event.getEventTime());
touchEvent.setPressure(event.getPressure());
- processEvent(touchEvent);
+ touchInput.addEvent(touchEvent);
return true;
}
+ @Override
public boolean onDoubleTap(MotionEvent event) {
//The down motion event of the first tap of the double-tap
- // We could use this event to fire off a double tap event, or use
+ // We could use this event to fire off a double tap event, or use
// DoubleTapEvent with a check for the UP action
-// logger.log(Level.INFO, "onDoubleTap pointerId: {0}, action: {1}, x: {2}, y: {3}",
-// new Object[]{getPointerId(event), getAction(event), event.getX(), event.getY()});
- float jmeX = androidInput.getJmeX(event.getX());
- float jmeY = androidInput.invertY(androidInput.getJmeY(event.getY()));
- TouchEvent touchEvent = androidInput.getFreeTouchEvent();
+// logger.log(Level.INFO, "onDoubleTap pointerId: {0}, action: {1}, x: {2}, y: {3}",
+// new Object[]{touchInput.getPointerId(event), touchInput.getAction(event), event.getX(), event.getY()});
+ float jmeX = touchInput.getJmeX(event.getX());
+ float jmeY = touchInput.invertY(touchInput.getJmeY(event.getY()));
+ TouchEvent touchEvent = touchInput.getFreeTouchEvent();
touchEvent.set(TouchEvent.Type.DOUBLETAP, jmeX, jmeY, 0, 0);
- touchEvent.setPointerId(getPointerId(event));
+ touchEvent.setPointerId(touchInput.getPointerId(event));
touchEvent.setTime(event.getEventTime());
touchEvent.setPressure(event.getPressure());
- processEvent(touchEvent);
+ touchInput.addEvent(touchEvent);
return true;
}
+ @Override
public boolean onDoubleTapEvent(MotionEvent event) {
//Notified when an event within a double-tap gesture occurs, including the down, move(s), and up events.
// this means it will get called multiple times for a single double tap
-// logger.log(Level.INFO, "onDoubleTapEvent pointerId: {0}, action: {1}, x: {2}, y: {3}",
-// new Object[]{getPointerId(event), getAction(event), event.getX(), event.getY()});
-// if (getAction(event) == MotionEvent.ACTION_UP) {
-// TouchEvent touchEvent = touchEventPool.getNextFreeEvent();
-// touchEvent.set(TouchEvent.Type.DOUBLETAP, event.getX(), androidInput.invertY(event.getY()), 0, 0);
-// touchEvent.setPointerId(getPointerId(event));
-// touchEvent.setTime(event.getEventTime());
-// touchEvent.setPressure(event.getPressure());
-// processEvent(touchEvent);
-// }
+// logger.log(Level.INFO, "onDoubleTapEvent pointerId: {0}, action: {1}, x: {2}, y: {3}",
+// new Object[]{touchInput.getPointerId(event), touchInput.getAction(event), event.getX(), event.getY()});
+ if (touchInput.getAction(event) == MotionEvent.ACTION_UP) {
+ TouchEvent touchEvent = touchInput.getFreeTouchEvent();
+ touchEvent.set(TouchEvent.Type.DOUBLETAP, event.getX(), touchInput.invertY(event.getY()), 0, 0);
+ touchEvent.setPointerId(touchInput.getPointerId(event));
+ touchEvent.setTime(event.getEventTime());
+ touchEvent.setPressure(event.getPressure());
+ touchInput.addEvent(touchEvent);
+ }
return true;
}
/* Events from ScaleGestureDetector */
-
+
+ @Override
public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
// Scale uses a focusX and focusY instead of x and y. Focus is the middle
// of the fingers. Therefore, use the x and y values from the Down event
// so that the x and y values don't jump to the middle position.
// return true or all gestures for this beginning event will be discarded
- logger.log(Level.INFO, "onScaleBegin");
+// logger.log(Level.INFO, "onScaleBegin");
scaleStartX = gestureDownX;
scaleStartY = gestureDownY;
- TouchEvent touchEvent = androidInput.getFreeTouchEvent();
+ TouchEvent touchEvent = touchInput.getFreeTouchEvent();
touchEvent.set(TouchEvent.Type.SCALE_START, scaleStartX, scaleStartY, 0f, 0f);
touchEvent.setPointerId(0);
touchEvent.setTime(scaleGestureDetector.getEventTime());
touchEvent.setScaleSpan(scaleGestureDetector.getCurrentSpan());
touchEvent.setDeltaScaleSpan(0f);
touchEvent.setScaleFactor(scaleGestureDetector.getScaleFactor());
- touchEvent.setScaleSpanInProgress(scaleDetector.isInProgress());
- processEvent(touchEvent);
-
+ touchEvent.setScaleSpanInProgress(touchInput.getScaleDetector().isInProgress());
+ touchInput.addEvent(touchEvent);
+
return true;
}
+ @Override
public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
// return true or all gestures for this event will be accumulated
- logger.log(Level.INFO, "onScale");
+// logger.log(Level.INFO, "onScale");
scaleStartX = gestureDownX;
scaleStartY = gestureDownY;
- TouchEvent touchEvent = androidInput.getFreeTouchEvent();
+ TouchEvent touchEvent = touchInput.getFreeTouchEvent();
touchEvent.set(TouchEvent.Type.SCALE_MOVE, scaleStartX, scaleStartY, 0f, 0f);
touchEvent.setPointerId(0);
touchEvent.setTime(scaleGestureDetector.getEventTime());
touchEvent.setScaleSpan(scaleGestureDetector.getCurrentSpan());
touchEvent.setDeltaScaleSpan(scaleGestureDetector.getCurrentSpan() - scaleGestureDetector.getPreviousSpan());
touchEvent.setScaleFactor(scaleGestureDetector.getScaleFactor());
- touchEvent.setScaleSpanInProgress(scaleDetector.isInProgress());
- processEvent(touchEvent);
+ touchEvent.setScaleSpanInProgress(touchInput.getScaleDetector().isInProgress());
+ touchInput.addEvent(touchEvent);
return true;
}
+ @Override
public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {
- logger.log(Level.INFO, "onScaleEnd");
+// logger.log(Level.INFO, "onScaleEnd");
scaleStartX = gestureDownX;
scaleStartY = gestureDownY;
- TouchEvent touchEvent = androidInput.getFreeTouchEvent();
+ TouchEvent touchEvent = touchInput.getFreeTouchEvent();
touchEvent.set(TouchEvent.Type.SCALE_END, scaleStartX, scaleStartY, 0f, 0f);
touchEvent.setPointerId(0);
touchEvent.setTime(scaleGestureDetector.getEventTime());
touchEvent.setScaleSpan(scaleGestureDetector.getCurrentSpan());
touchEvent.setDeltaScaleSpan(scaleGestureDetector.getCurrentSpan() - scaleGestureDetector.getPreviousSpan());
touchEvent.setScaleFactor(scaleGestureDetector.getScaleFactor());
- touchEvent.setScaleSpanInProgress(scaleDetector.isInProgress());
- processEvent(touchEvent);
+ touchEvent.setScaleSpanInProgress(touchInput.getScaleDetector().isInProgress());
+ touchInput.addEvent(touchEvent);
}
}
diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidInput.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidInput.java
deleted file mode 100644
index 02fef6b0f..000000000
--- a/jme3-android/src/main/java/com/jme3/input/android/AndroidInput.java
+++ /dev/null
@@ -1,686 +0,0 @@
-package com.jme3.input.android;
-
-import android.view.*;
-import com.jme3.input.KeyInput;
-import com.jme3.input.RawInputListener;
-import com.jme3.input.TouchInput;
-import com.jme3.input.event.MouseButtonEvent;
-import com.jme3.input.event.MouseMotionEvent;
-import com.jme3.input.event.TouchEvent;
-import com.jme3.input.event.TouchEvent.Type;
-import com.jme3.math.Vector2f;
-import com.jme3.system.AppSettings;
-import com.jme3.util.RingBuffer;
-import java.util.HashMap;
-import java.util.logging.Logger;
-
-/**
- * AndroidInput
is one of the main components that connect jme with android. Is derived from GLSurfaceView and handles all Inputs
- * @author larynx
- *
- */
-public class AndroidInput implements
- TouchInput,
- View.OnTouchListener,
- View.OnKeyListener,
- GestureDetector.OnGestureListener,
- GestureDetector.OnDoubleTapListener,
- ScaleGestureDetector.OnScaleGestureListener {
-
- final private static int MAX_EVENTS = 1024;
- // Custom settings
- public boolean mouseEventsEnabled = true;
- public boolean mouseEventsInvertX = false;
- public boolean mouseEventsInvertY = false;
- public boolean keyboardEventsEnabled = false;
- public boolean dontSendHistory = false;
- // Used to transfer events from android thread to GLThread
- final private RingBuffer eventQueue = new RingBuffer(MAX_EVENTS);
- final private RingBuffer eventPoolUnConsumed = new RingBuffer(MAX_EVENTS);
- final private RingBuffer eventPool = new RingBuffer(MAX_EVENTS);
- final private HashMap lastPositions = new HashMap();
- // Internal
- private View view;
- private ScaleGestureDetector scaledetector;
- private boolean scaleInProgress = false;
- private GestureDetector detector;
- private int lastX;
- private int lastY;
- private final static Logger logger = Logger.getLogger(AndroidInput.class.getName());
- private boolean isInitialized = false;
- private RawInputListener listener = null;
- private static final int[] ANDROID_TO_JME = {
- 0x0, // unknown
- 0x0, // key code soft left
- 0x0, // key code soft right
- KeyInput.KEY_HOME,
- KeyInput.KEY_ESCAPE, // key back
- 0x0, // key call
- 0x0, // key endcall
- KeyInput.KEY_0,
- KeyInput.KEY_1,
- KeyInput.KEY_2,
- KeyInput.KEY_3,
- KeyInput.KEY_4,
- KeyInput.KEY_5,
- KeyInput.KEY_6,
- KeyInput.KEY_7,
- KeyInput.KEY_8,
- KeyInput.KEY_9,
- KeyInput.KEY_MULTIPLY,
- 0x0, // key pound
- KeyInput.KEY_UP,
- KeyInput.KEY_DOWN,
- KeyInput.KEY_LEFT,
- KeyInput.KEY_RIGHT,
- KeyInput.KEY_RETURN, // dpad center
- 0x0, // volume up
- 0x0, // volume down
- KeyInput.KEY_POWER, // power (?)
- 0x0, // camera
- 0x0, // clear
- KeyInput.KEY_A,
- KeyInput.KEY_B,
- KeyInput.KEY_C,
- KeyInput.KEY_D,
- KeyInput.KEY_E,
- KeyInput.KEY_F,
- KeyInput.KEY_G,
- KeyInput.KEY_H,
- KeyInput.KEY_I,
- KeyInput.KEY_J,
- KeyInput.KEY_K,
- KeyInput.KEY_L,
- KeyInput.KEY_M,
- KeyInput.KEY_N,
- KeyInput.KEY_O,
- KeyInput.KEY_P,
- KeyInput.KEY_Q,
- KeyInput.KEY_R,
- KeyInput.KEY_S,
- KeyInput.KEY_T,
- KeyInput.KEY_U,
- KeyInput.KEY_V,
- KeyInput.KEY_W,
- KeyInput.KEY_X,
- KeyInput.KEY_Y,
- KeyInput.KEY_Z,
- KeyInput.KEY_COMMA,
- KeyInput.KEY_PERIOD,
- KeyInput.KEY_LMENU,
- KeyInput.KEY_RMENU,
- KeyInput.KEY_LSHIFT,
- KeyInput.KEY_RSHIFT,
- // 0x0, // fn
- // 0x0, // cap (?)
-
- KeyInput.KEY_TAB,
- KeyInput.KEY_SPACE,
- 0x0, // sym (?) symbol
- 0x0, // explorer
- 0x0, // envelope
- KeyInput.KEY_RETURN, // newline/enter
- KeyInput.KEY_DELETE,
- KeyInput.KEY_GRAVE,
- KeyInput.KEY_MINUS,
- KeyInput.KEY_EQUALS,
- KeyInput.KEY_LBRACKET,
- KeyInput.KEY_RBRACKET,
- KeyInput.KEY_BACKSLASH,
- KeyInput.KEY_SEMICOLON,
- KeyInput.KEY_APOSTROPHE,
- KeyInput.KEY_SLASH,
- KeyInput.KEY_AT, // at (@)
- KeyInput.KEY_NUMLOCK, //0x0, // num
- 0x0, //headset hook
- 0x0, //focus
- KeyInput.KEY_ADD,
- KeyInput.KEY_LMETA, //menu
- 0x0,//notification
- 0x0,//search
- 0x0,//media play/pause
- 0x0,//media stop
- 0x0,//media next
- 0x0,//media previous
- 0x0,//media rewind
- 0x0,//media fastforward
- 0x0,//mute
- };
-
- public AndroidInput() {
- }
-
- public void setView(View view) {
- this.view = view;
- if (view != null) {
- detector = new GestureDetector(null, this, null, false);
- scaledetector = new ScaleGestureDetector(view.getContext(), this);
- view.setOnTouchListener(this);
- view.setOnKeyListener(this);
- }
- }
-
- private TouchEvent getNextFreeTouchEvent() {
- return getNextFreeTouchEvent(false);
- }
-
- /**
- * Fetches a touch event from the reuse pool
- * @param wait if true waits for a reusable event to get available/released
- * by an other thread, if false returns a new one if needed.
- *
- * @return a usable TouchEvent
- */
- private TouchEvent getNextFreeTouchEvent(boolean wait) {
- TouchEvent evt = null;
- synchronized (eventPoolUnConsumed) {
- int size = eventPoolUnConsumed.size();
- while (size > 0) {
- evt = eventPoolUnConsumed.pop();
- if (!evt.isConsumed()) {
- eventPoolUnConsumed.push(evt);
- evt = null;
- } else {
- break;
- }
- size--;
- }
- }
-
- if (evt == null) {
- if (eventPool.isEmpty() && wait) {
- logger.warning("eventPool buffer underrun");
- boolean isEmpty;
- do {
- synchronized (eventPool) {
- isEmpty = eventPool.isEmpty();
- }
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- }
- } while (isEmpty);
- synchronized (eventPool) {
- evt = eventPool.pop();
- }
- } else if (eventPool.isEmpty()) {
- evt = new TouchEvent();
- logger.warning("eventPool buffer underrun");
- } else {
- synchronized (eventPool) {
- evt = eventPool.pop();
- }
- }
- }
- return evt;
- }
-
- /**
- * onTouch gets called from android thread on touchpad events
- */
- public boolean onTouch(View view, MotionEvent event) {
- if (view != this.view) {
- return false;
- }
- boolean bWasHandled = false;
- TouchEvent touch;
- // System.out.println("native : " + event.getAction());
- int action = event.getAction() & MotionEvent.ACTION_MASK;
- int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
- >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- int pointerId = event.getPointerId(pointerIndex);
- Vector2f lastPos = lastPositions.get(pointerId);
-
- // final int historySize = event.getHistorySize();
- //final int pointerCount = event.getPointerCount();
- switch (action) {
- case MotionEvent.ACTION_POINTER_DOWN:
- case MotionEvent.ACTION_DOWN:
- touch = getNextFreeTouchEvent();
- touch.set(Type.DOWN, event.getX(pointerIndex), view.getHeight() - event.getY(pointerIndex), 0, 0);
- touch.setPointerId(pointerId);
- touch.setTime(event.getEventTime());
- touch.setPressure(event.getPressure(pointerIndex));
- processEvent(touch);
-
- lastPos = new Vector2f(event.getX(pointerIndex), view.getHeight() - event.getY(pointerIndex));
- lastPositions.put(pointerId, lastPos);
-
- bWasHandled = true;
- break;
- case MotionEvent.ACTION_POINTER_UP:
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- touch = getNextFreeTouchEvent();
- touch.set(Type.UP, event.getX(pointerIndex), view.getHeight() - event.getY(pointerIndex), 0, 0);
- touch.setPointerId(pointerId);
- touch.setTime(event.getEventTime());
- touch.setPressure(event.getPressure(pointerIndex));
- processEvent(touch);
- lastPositions.remove(pointerId);
-
- bWasHandled = true;
- break;
- case MotionEvent.ACTION_MOVE:
- // Convert all pointers into events
- for (int p = 0; p < event.getPointerCount(); p++) {
- lastPos = lastPositions.get(event.getPointerId(p));
- if (lastPos == null) {
- lastPos = new Vector2f(event.getX(p), view.getHeight() - event.getY(p));
- lastPositions.put(event.getPointerId(p), lastPos);
- }
-
- float dX = event.getX(p) - lastPos.x;
- float dY = view.getHeight() - event.getY(p) - lastPos.y;
- if (dX != 0 || dY != 0) {
- touch = getNextFreeTouchEvent();
- touch.set(Type.MOVE, event.getX(p), view.getHeight() - event.getY(p), dX, dY);
- touch.setPointerId(event.getPointerId(p));
- touch.setTime(event.getEventTime());
- touch.setPressure(event.getPressure(p));
- touch.setScaleSpanInProgress(scaleInProgress);
- processEvent(touch);
- lastPos.set(event.getX(p), view.getHeight() - event.getY(p));
- }
- }
- bWasHandled = true;
- break;
- case MotionEvent.ACTION_OUTSIDE:
- break;
-
- }
-
- // Try to detect gestures
- this.detector.onTouchEvent(event);
- this.scaledetector.onTouchEvent(event);
-
- return bWasHandled;
- }
-
- /**
- * onKey gets called from android thread on key events
- */
- public boolean onKey(View view, int keyCode, KeyEvent event) {
- if (view != this.view) {
- return false;
- }
-
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- TouchEvent evt;
- evt = getNextFreeTouchEvent();
- evt.set(TouchEvent.Type.KEY_DOWN);
- evt.setKeyCode(keyCode);
- evt.setCharacters(event.getCharacters());
- evt.setTime(event.getEventTime());
-
- // Send the event
- processEvent(evt);
-
- // Handle all keys ourself except Volume Up/Down
- if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP) || (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
- return false;
- } else {
- return true;
- }
- } else if (event.getAction() == KeyEvent.ACTION_UP) {
- TouchEvent evt;
- evt = getNextFreeTouchEvent();
- evt.set(TouchEvent.Type.KEY_UP);
- evt.setKeyCode(keyCode);
- evt.setCharacters(event.getCharacters());
- evt.setTime(event.getEventTime());
-
- // Send the event
- processEvent(evt);
-
- // Handle all keys ourself except Volume Up/Down
- if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP) || (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
- return false;
- } else {
- return true;
- }
- } else {
- return false;
- }
- }
-
- public void loadSettings(AppSettings settings) {
- mouseEventsEnabled = settings.isEmulateMouse();
- mouseEventsInvertX = settings.isEmulateMouseFlipX();
- mouseEventsInvertY = settings.isEmulateMouseFlipY();
- }
-
- // -----------------------------------------
- // JME3 Input interface
- @Override
- public void initialize() {
- TouchEvent item;
- for (int i = 0; i < MAX_EVENTS; i++) {
- item = new TouchEvent();
- eventPool.push(item);
- }
- isInitialized = true;
- }
-
- @Override
- public void destroy() {
- isInitialized = false;
-
- // Clean up queues
- while (!eventPool.isEmpty()) {
- eventPool.pop();
- }
- while (!eventQueue.isEmpty()) {
- eventQueue.pop();
- }
-
-
- this.view = null;
- }
-
- @Override
- public boolean isInitialized() {
- return isInitialized;
- }
-
- @Override
- public void setInputListener(RawInputListener listener) {
- this.listener = listener;
- }
-
- @Override
- public long getInputTimeNanos() {
- return System.nanoTime();
- }
- // -----------------------------------------
-
- private void processEvent(TouchEvent event) {
- synchronized (eventQueue) {
- //Discarding events when the ring buffer is full to avoid buffer overflow.
- if(eventQueue.size()< MAX_EVENTS){
- eventQueue.push(event);
- }
-
- }
- }
-
- // --------------- INSIDE GLThread ---------------
- @Override
- public void update() {
- generateEvents();
- }
-
- private void generateEvents() {
- if (listener != null) {
- TouchEvent event;
- MouseButtonEvent btn;
- MouseMotionEvent mot;
- int newX;
- int newY;
-
- while (!eventQueue.isEmpty()) {
- synchronized (eventQueue) {
- event = eventQueue.pop();
- }
- if (event != null) {
- listener.onTouchEvent(event);
-
- if (mouseEventsEnabled) {
- if (mouseEventsInvertX) {
- newX = view.getWidth() - (int) event.getX();
- } else {
- newX = (int) event.getX();
- }
-
- if (mouseEventsInvertY) {
- newY = view.getHeight() - (int) event.getY();
- } else {
- newY = (int) event.getY();
- }
-
- switch (event.getType()) {
- case DOWN:
- // Handle mouse down event
- btn = new MouseButtonEvent(0, true, newX, newY);
- btn.setTime(event.getTime());
- listener.onMouseButtonEvent(btn);
- // Store current pos
- lastX = -1;
- lastY = -1;
- break;
-
- case UP:
- // Handle mouse up event
- btn = new MouseButtonEvent(0, false, newX, newY);
- btn.setTime(event.getTime());
- listener.onMouseButtonEvent(btn);
- // Store current pos
- lastX = -1;
- lastY = -1;
- break;
-
- case SCALE_MOVE:
- if (lastX != -1 && lastY != -1) {
- newX = lastX;
- newY = lastY;
- }
- int wheel = (int) (event.getScaleSpan() / 4f); // scale to match mouse wheel
- int dwheel = (int) (event.getDeltaScaleSpan() / 4f); // scale to match mouse wheel
- mot = new MouseMotionEvent(newX, newX, 0, 0, wheel, dwheel);
- mot.setTime(event.getTime());
- listener.onMouseMotionEvent(mot);
- lastX = newX;
- lastY = newY;
-
- break;
-
- case MOVE:
- if (event.isScaleSpanInProgress()) {
- break;
- }
-
- int dx;
- int dy;
- if (lastX != -1) {
- dx = newX - lastX;
- dy = newY - lastY;
- } else {
- dx = 0;
- dy = 0;
- }
-
- mot = new MouseMotionEvent(newX, newY, dx, dy, (int)event.getScaleSpan(), (int)event.getDeltaScaleSpan());
- mot.setTime(event.getTime());
- listener.onMouseMotionEvent(mot);
- lastX = newX;
- lastY = newY;
-
- break;
- }
- }
- }
-
- if (event.isConsumed() == false) {
- synchronized (eventPoolUnConsumed) {
- eventPoolUnConsumed.push(event);
- }
-
- } else {
- synchronized (eventPool) {
- eventPool.push(event);
- }
- }
- }
-
- }
- }
- // --------------- ENDOF INSIDE GLThread ---------------
-
- // --------------- Gesture detected callback events ---------------
- public boolean onDown(MotionEvent event) {
- return false;
- }
-
- public void onLongPress(MotionEvent event) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.LONGPRESSED, event.getX(), view.getHeight() - event.getY(), 0f, 0f);
- touch.setPointerId(0);
- touch.setTime(event.getEventTime());
- processEvent(touch);
- }
-
- public boolean onFling(MotionEvent event, MotionEvent event2, float vx, float vy) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.FLING, event.getX(), view.getHeight() - event.getY(), vx, vy);
- touch.setPointerId(0);
- touch.setTime(event.getEventTime());
- processEvent(touch);
-
- return true;
- }
-
- public boolean onSingleTapConfirmed(MotionEvent event) {
- //Nothing to do here the tap has already been detected.
- return false;
- }
-
- public boolean onDoubleTap(MotionEvent event) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.DOUBLETAP, event.getX(), view.getHeight() - event.getY(), 0f, 0f);
- touch.setPointerId(0);
- touch.setTime(event.getEventTime());
- processEvent(touch);
- return true;
- }
-
- public boolean onDoubleTapEvent(MotionEvent event) {
- return false;
- }
-
- public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
- scaleInProgress = true;
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.SCALE_START, scaleGestureDetector.getFocusX(), scaleGestureDetector.getFocusY(), 0f, 0f);
- touch.setPointerId(0);
- touch.setTime(scaleGestureDetector.getEventTime());
- touch.setScaleSpan(scaleGestureDetector.getCurrentSpan());
- touch.setDeltaScaleSpan(scaleGestureDetector.getCurrentSpan() - scaleGestureDetector.getPreviousSpan());
- touch.setScaleFactor(scaleGestureDetector.getScaleFactor());
- touch.setScaleSpanInProgress(scaleInProgress);
- processEvent(touch);
- // System.out.println("scaleBegin");
-
- return true;
- }
-
- public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.SCALE_MOVE, scaleGestureDetector.getFocusX(), view.getHeight() - scaleGestureDetector.getFocusY(), 0f, 0f);
- touch.setPointerId(0);
- touch.setTime(scaleGestureDetector.getEventTime());
- touch.setScaleSpan(scaleGestureDetector.getCurrentSpan());
- touch.setDeltaScaleSpan(scaleGestureDetector.getCurrentSpan() - scaleGestureDetector.getPreviousSpan());
- touch.setScaleFactor(scaleGestureDetector.getScaleFactor());
- touch.setScaleSpanInProgress(scaleInProgress);
- processEvent(touch);
- // System.out.println("scale");
-
- return false;
- }
-
- public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {
- scaleInProgress = false;
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.SCALE_END, scaleGestureDetector.getFocusX(), view.getHeight() - scaleGestureDetector.getFocusY(), 0f, 0f);
- touch.setPointerId(0);
- touch.setTime(scaleGestureDetector.getEventTime());
- touch.setScaleSpan(scaleGestureDetector.getCurrentSpan());
- touch.setDeltaScaleSpan(scaleGestureDetector.getCurrentSpan() - scaleGestureDetector.getPreviousSpan());
- touch.setScaleFactor(scaleGestureDetector.getScaleFactor());
- touch.setScaleSpanInProgress(scaleInProgress);
- processEvent(touch);
- }
-
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.SCROLL, e1.getX(), view.getHeight() - e1.getY(), distanceX, distanceY * (-1));
- touch.setPointerId(0);
- touch.setTime(e1.getEventTime());
- processEvent(touch);
- //System.out.println("scroll " + e1.getPointerCount());
- return false;
- }
-
- public void onShowPress(MotionEvent event) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.SHOWPRESS, event.getX(), view.getHeight() - event.getY(), 0f, 0f);
- touch.setPointerId(0);
- touch.setTime(event.getEventTime());
- processEvent(touch);
- }
-
- public boolean onSingleTapUp(MotionEvent event) {
- TouchEvent touch = getNextFreeTouchEvent();
- touch.set(Type.TAP, event.getX(), view.getHeight() - event.getY(), 0f, 0f);
- touch.setPointerId(0);
- touch.setTime(event.getEventTime());
- processEvent(touch);
- return true;
- }
-
- @Override
- public void setSimulateKeyboard(boolean simulate) {
- keyboardEventsEnabled = simulate;
- }
-
- @Override
- public void setOmitHistoricEvents(boolean dontSendHistory) {
- this.dontSendHistory = dontSendHistory;
- }
-
- /**
- * @deprecated Use {@link #getSimulateMouse()};
- */
- @Deprecated
- public boolean isMouseEventsEnabled() {
- return mouseEventsEnabled;
- }
-
- @Deprecated
- public void setMouseEventsEnabled(boolean mouseEventsEnabled) {
- this.mouseEventsEnabled = mouseEventsEnabled;
- }
-
- public boolean isMouseEventsInvertY() {
- return mouseEventsInvertY;
- }
-
- public void setMouseEventsInvertY(boolean mouseEventsInvertY) {
- this.mouseEventsInvertY = mouseEventsInvertY;
- }
-
- public boolean isMouseEventsInvertX() {
- return mouseEventsInvertX;
- }
-
- public void setMouseEventsInvertX(boolean mouseEventsInvertX) {
- this.mouseEventsInvertX = mouseEventsInvertX;
- }
-
- public void setSimulateMouse(boolean simulate) {
- mouseEventsEnabled = simulate;
- }
-
- public boolean getSimulateMouse() {
- return isSimulateMouse();
- }
-
- public boolean isSimulateMouse() {
- return mouseEventsEnabled;
- }
-
- public boolean isSimulateKeyboard() {
- return keyboardEventsEnabled;
- }
-
-}
diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler.java
index 202907316..9f4729c66 100644
--- a/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler.java
+++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler.java
@@ -33,231 +33,206 @@
package com.jme3.input.android;
import android.opengl.GLSurfaceView;
-import android.os.Build;
+import android.view.GestureDetector;
+import android.view.InputDevice;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
import android.view.View;
-import com.jme3.input.RawInputListener;
+import com.jme3.input.JoyInput;
import com.jme3.input.TouchInput;
-import com.jme3.input.event.InputEvent;
-import com.jme3.input.event.KeyInputEvent;
-import com.jme3.input.event.MouseButtonEvent;
-import com.jme3.input.event.MouseMotionEvent;
-import com.jme3.input.event.TouchEvent;
import com.jme3.system.AppSettings;
-import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* AndroidInput
is the main class that connects the Android system
- * inputs to jME. It serves as the manager that gathers inputs from the various
- * Android input methods and provides them to jME's InputManager
.
+ * inputs to jME. It receives the inputs from the Android View and passes them
+ * to the appropriate classes based on the source of the input.
+ * This class is to be extended when new functionality is released in Android.
*
* @author iwgeric
*/
-public class AndroidInputHandler implements TouchInput {
- private static final Logger logger = Logger.getLogger(AndroidInputHandler.class.getName());
-
- // Custom settings
- private boolean mouseEventsEnabled = true;
- private boolean mouseEventsInvertX = false;
- private boolean mouseEventsInvertY = false;
- private boolean keyboardEventsEnabled = false;
- private boolean dontSendHistory = false;
+public class AndroidInputHandler implements View.OnTouchListener,
+ View.OnKeyListener {
+ private static final Logger logger = Logger.getLogger(AndroidInputHandler.class.getName());
- // Internal
- private GLSurfaceView view;
- private AndroidTouchHandler touchHandler;
- private AndroidKeyHandler keyHandler;
- private AndroidGestureHandler gestureHandler;
- private boolean initialized = false;
- private RawInputListener listener = null;
- private ConcurrentLinkedQueue inputEventQueue = new ConcurrentLinkedQueue();
- private final static int MAX_TOUCH_EVENTS = 1024;
- private final TouchEventPool touchEventPool = new TouchEventPool(MAX_TOUCH_EVENTS);
- private float scaleX = 1f;
- private float scaleY = 1f;
+ protected GLSurfaceView view;
+ protected AndroidTouchInput touchInput;
+ protected AndroidJoyInput joyInput;
public AndroidInputHandler() {
- int buildVersion = Build.VERSION.SDK_INT;
- logger.log(Level.INFO, "Android Build Version: {0}", buildVersion);
- if (buildVersion >= 14) {
- // add support for onHover and GenericMotionEvent (ie. gamepads)
- gestureHandler = new AndroidGestureHandler(this);
- touchHandler = new AndroidTouchHandler14(this, gestureHandler);
- keyHandler = new AndroidKeyHandler(this);
- } else if (buildVersion >= 8){
- gestureHandler = new AndroidGestureHandler(this);
- touchHandler = new AndroidTouchHandler(this, gestureHandler);
- keyHandler = new AndroidKeyHandler(this);
- }
- }
-
- public AndroidInputHandler(AndroidTouchHandler touchInput,
- AndroidKeyHandler keyInput, AndroidGestureHandler gestureHandler) {
- this.touchHandler = touchInput;
- this.keyHandler = keyInput;
- this.gestureHandler = gestureHandler;
+ touchInput = new AndroidTouchInput(this);
+ joyInput = new AndroidJoyInput(this);
}
public void setView(View view) {
- if (touchHandler != null) {
- touchHandler.setView(view);
+ if (this.view != null && view != null && this.view.equals(view)) {
+ return;
}
- if (keyHandler != null) {
- keyHandler.setView(view);
- }
- if (gestureHandler != null) {
- gestureHandler.setView(view);
+
+ if (this.view != null) {
+ removeListeners(this.view);
}
+
this.view = (GLSurfaceView)view;
- }
- public View getView() {
- return view;
- }
+ if (this.view != null) {
+ addListeners(this.view);
+ }
- public float invertX(float origX) {
- return getJmeX(view.getWidth()) - origX;
+ joyInput.setView((GLSurfaceView)view);
}
- public float invertY(float origY) {
- return getJmeY(view.getHeight()) - origY;
+ public View getView() {
+ return view;
}
- public float getJmeX(float origX) {
- return origX * scaleX;
+ protected void removeListeners(GLSurfaceView view) {
+ view.setOnTouchListener(null);
+ view.setOnKeyListener(null);
+ touchInput.setGestureDetector(null);
+ touchInput.setScaleDetector(null);
}
- public float getJmeY(float origY) {
- return origY * scaleY;
+ protected void addListeners(GLSurfaceView view) {
+ view.setOnTouchListener(this);
+ view.setOnKeyListener(this);
+ AndroidGestureProcessor gestureHandler = new AndroidGestureProcessor(touchInput);
+ touchInput.setGestureDetector(new GestureDetector(
+ view.getContext(), gestureHandler));
+ touchInput.setScaleDetector(new ScaleGestureDetector(
+ view.getContext(), gestureHandler));
}
public void loadSettings(AppSettings settings) {
- keyboardEventsEnabled = settings.isEmulateKeyboard();
- mouseEventsEnabled = settings.isEmulateMouse();
- mouseEventsInvertX = settings.isEmulateMouseFlipX();
- mouseEventsInvertY = settings.isEmulateMouseFlipY();
-
- // view width and height are 0 until the view is displayed on the screen
- if (view.getWidth() != 0 && view.getHeight() != 0) {
- scaleX = (float)settings.getWidth() / (float)view.getWidth();
- scaleY = (float)settings.getHeight() / (float)view.getHeight();
- }
- logger.log(Level.FINE, "Setting input scaling, scaleX: {0}, scaleY: {1}",
- new Object[]{scaleX, scaleY});
+ touchInput.loadSettings(settings);
+ }
+
+ public TouchInput getTouchInput() {
+ return touchInput;
+ }
+
+ public JoyInput getJoyInput() {
+ return joyInput;
+ }
+
+ /*
+ * Android input events include the source from which the input came from.
+ * We must look at the source of the input event to determine which type
+ * of jME input it belongs to.
+ * If the input is from a gamepad or joystick source, the event is sent
+ * to the JoyInput class to convert the event into jME joystick events.
+ *
+ * If the input is from a touchscreen source, the event is sent to the
+ * TouchProcessor to convert the event into touch events.
+ * The TouchProcessor also converts the events into Mouse and Key events
+ * if AppSettings is set to simulate Mouse or Keyboard events.
+ *
+ * Android reports the source as a bitmask as shown below.
+ *
+ * InputDevice Sources
+ * 0000 0000 0000 0000 0000 0000 0000 0000 - 32 bit bitmask
+ *
+ * 0000 0000 0000 0000 0000 0000 1111 1111 - SOURCE_CLASS_MASK (0x000000ff)
+ * 0000 0000 0000 0000 0000 0000 0000 0000 - SOURCE_CLASS_NONE (0x00000000)
+ * 0000 0000 0000 0000 0000 0000 0000 0001 - SOURCE_CLASS_BUTTON (0x00000001)
+ * 0000 0000 0000 0000 0000 0000 0000 0010 - SOURCE_CLASS_POINTER (0x00000002)
+ * 0000 0000 0000 0000 0000 0000 0000 0100 - SOURCE_CLASS_TRACKBALL (0x00000004)
+ * 0000 0000 0000 0000 0000 0000 0000 1000 - SOURCE_CLASS_POSITION (0x00000008)
+ * 0000 0000 0000 0000 0000 0000 0001 0000 - SOURCE_CLASS_JOYSTICK (0x00000010)
+ *
+ * 1111 1111 1111 1111 1111 1111 0000 0000 - Source_Any (0xffffff00)
+ * 0000 0000 0000 0000 0000 0000 0000 0000 - SOURCE_UNKNOWN (0x00000000)
+ * 0000 0000 0000 0000 0000 0001 0000 0001 - SOURCE_KEYBOARD (0x00000101)
+ * 0000 0000 0000 0000 0000 0010 0000 0001 - SOURCE_DPAD (0x00000201)
+ * 0000 0000 0000 0000 0000 0100 0000 0001 - SOURCE_GAMEPAD (0x00000401)
+ * 0000 0000 0000 0000 0001 0000 0000 0010 - SOURCE_TOUCHSCREEN (0x00001002)
+ * 0000 0000 0000 0000 0010 0000 0000 0010 - SOURCE_MOUSE (0x00002002)
+ * 0000 0000 0000 0000 0100 0000 0000 0010 - SOURCE_STYLUS (0x00004002)
+ * 0000 0000 0000 0001 0000 0000 0000 0100 - SOURCE_TRACKBALL (0x00010004)
+ * 0000 0000 0001 0000 0000 0000 0000 1000 - SOURCE_TOUCHPAD (0x00100008)
+ * 0000 0000 0010 0000 0000 0000 0000 0000 - SOURCE_TOUCH_NAVIGATION (0x00200000)
+ * 0000 0001 0000 0000 0000 0000 0001 0000 - SOURCE_JOYSTICK (0x01000010)
+ * 0000 0010 0000 0000 0000 0000 0000 0001 - SOURCE_HDMI (0x02000001)
+ *
+ * Example values reported by Android for Source
+ * 4,098 = 0x00001002 =
+ * 0000 0000 0000 0000 0001 0000 0000 0010 - SOURCE_CLASS_POINTER
+ * SOURCE_TOUCHSCREEN
+ * 1,281 = 0x00000501 =
+ * 0000 0000 0000 0000 0000 0101 0000 0001 - SOURCE_CLASS_BUTTON
+ * SOURCE_KEYBOARD
+ * SOURCE_GAMEPAD
+ * 16,777,232 = 0x01000010 =
+ * 0000 0001 0000 0000 0000 0000 0001 0000 - SOURCE_CLASS_JOYSTICK
+ * SOURCE_JOYSTICK
+ *
+ * 16,778,513 = 0x01000511 =
+ * 0000 0001 0000 0000 0000 0101 0001 0001 - SOURCE_CLASS_BUTTON
+ * SOURCE_CLASS_JOYSTICK
+ * SOURCE_GAMEPAD
+ * SOURCE_KEYBOARD
+ * SOURCE_JOYSTICK
+ *
+ * 257 = 0x00000101 =
+ * 0000 0000 0000 0000 0000 0001 0000 0001 - SOURCE_CLASS_BUTTON
+ * SOURCE_KEYBOARD
+ *
+ *
+ *
+ */
- }
- // -----------------------------------------
- // JME3 Input interface
@Override
- public void initialize() {
- touchEventPool.initialize();
- if (touchHandler != null) {
- touchHandler.initialize();
- }
- if (keyHandler != null) {
- keyHandler.initialize();
- }
- if (gestureHandler != null) {
- gestureHandler.initialize();
+ public boolean onTouch(View view, MotionEvent event) {
+ if (view != getView()) {
+ return false;
}
- initialized = true;
- }
+ boolean consumed = false;
- @Override
- public void destroy() {
- initialized = false;
+ int source = event.getSource();
+// logger.log(Level.INFO, "onTouch source: {0}", source);
- touchEventPool.destroy();
- if (touchHandler != null) {
- touchHandler.destroy();
- }
- if (keyHandler != null) {
- keyHandler.destroy();
- }
- if (gestureHandler != null) {
- gestureHandler.destroy();
- }
-
- setView(null);
- }
-
- @Override
- public boolean isInitialized() {
- return initialized;
- }
-
- @Override
- public void setInputListener(RawInputListener listener) {
- this.listener = listener;
- }
-
- @Override
- public long getInputTimeNanos() {
- return System.nanoTime();
- }
+ boolean isTouch = ((source & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN);
+// logger.log(Level.INFO, "onTouch source: {0}, isTouch: {1}",
+// new Object[]{source, isTouch});
- public void update() {
- if (listener != null) {
- InputEvent inputEvent;
-
- while ((inputEvent = inputEventQueue.poll()) != null) {
- if (inputEvent instanceof TouchEvent) {
- listener.onTouchEvent((TouchEvent)inputEvent);
- } else if (inputEvent instanceof MouseButtonEvent) {
- listener.onMouseButtonEvent((MouseButtonEvent)inputEvent);
- } else if (inputEvent instanceof MouseMotionEvent) {
- listener.onMouseMotionEvent((MouseMotionEvent)inputEvent);
- } else if (inputEvent instanceof KeyInputEvent) {
- listener.onKeyEvent((KeyInputEvent)inputEvent);
- }
- }
+ if (isTouch && touchInput != null) {
+ // send the event to the touch processor
+ consumed = touchInput.onTouch(event);
}
- }
- // -----------------------------------------
+ return consumed;
- public TouchEvent getFreeTouchEvent() {
- return touchEventPool.getNextFreeEvent();
}
- public void addEvent(InputEvent event) {
- inputEventQueue.add(event);
- if (event instanceof TouchEvent) {
- touchEventPool.storeEvent((TouchEvent)event);
+ @Override
+ public boolean onKey(View view, int keyCode, KeyEvent event) {
+ if (view != getView()) {
+ return false;
}
- }
- public void setSimulateMouse(boolean simulate) {
- this.mouseEventsEnabled = simulate;
- }
+ boolean consumed = false;
- public boolean isSimulateMouse() {
- return mouseEventsEnabled;
- }
+ int source = event.getSource();
+// logger.log(Level.INFO, "onKey source: {0}", source);
- public boolean isMouseEventsInvertX() {
- return mouseEventsInvertX;
- }
+ boolean isTouch =
+ ((source & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) ||
+ ((source & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD);
+// logger.log(Level.INFO, "onKey source: {0}, isTouch: {1}",
+// new Object[]{source, isTouch});
- public boolean isMouseEventsInvertY() {
- return mouseEventsInvertY;
- }
-
- public void setSimulateKeyboard(boolean simulate) {
- this.keyboardEventsEnabled = simulate;
- }
+ if (touchInput != null) {
+ consumed = touchInput.onKey(event);
+ }
- public boolean isSimulateKeyboard() {
- return keyboardEventsEnabled;
- }
+ return consumed;
- public void setOmitHistoricEvents(boolean dontSendHistory) {
- this.dontSendHistory = dontSendHistory;
}
}
diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler14.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler14.java
new file mode 100644
index 000000000..114bb98fd
--- /dev/null
+++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidInputHandler14.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2009-2012 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.jme3.input.android;
+
+import android.opengl.GLSurfaceView;
+import android.view.InputDevice;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * AndroidInputHandler14
extends AndroidInputHandler
to
+ * add the onHover and onGenericMotion events that where added in Android rev 14 (Android 4.0).
+ * The onGenericMotion events are the main interface to Joystick axes. They
+ * were actually released in Android rev 12.
+ *
+ * @author iwgeric
+ */
+public class AndroidInputHandler14 extends AndroidInputHandler implements View.OnHoverListener,
+ View.OnGenericMotionListener {
+
+ private static final Logger logger = Logger.getLogger(AndroidInputHandler14.class.getName());
+
+ public AndroidInputHandler14() {
+ touchInput = new AndroidTouchInput14(this);
+ joyInput = new AndroidJoyInput14(this);
+ }
+
+ @Override
+ protected void removeListeners(GLSurfaceView view) {
+ super.removeListeners(view);
+ view.setOnHoverListener(null);
+ view.setOnGenericMotionListener(null);
+ }
+
+ @Override
+ protected void addListeners(GLSurfaceView view) {
+ super.addListeners(view);
+ view.setOnHoverListener(this);
+ view.setOnGenericMotionListener(this);
+ }
+
+ @Override
+ public boolean onHover(View view, MotionEvent event) {
+ if (view != getView()) {
+ return false;
+ }
+
+ boolean consumed = false;
+
+ int source = event.getSource();
+// logger.log(Level.INFO, "onTouch source: {0}", source);
+
+ boolean isTouch = ((source & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN);
+// logger.log(Level.INFO, "onTouch source: {0}, isTouch: {1}",
+// new Object[]{source, isTouch});
+
+ if (isTouch && touchInput != null) {
+ // send the event to the touch processor
+ consumed = ((AndroidTouchInput14)touchInput).onHover(event);
+ }
+
+ return consumed;
+ }
+
+ @Override
+ public boolean onGenericMotion(View view, MotionEvent event) {
+ if (view != getView()) {
+ return false;
+ }
+
+ boolean consumed = false;
+
+ int source = event.getSource();
+// logger.log(Level.INFO, "onGenericMotion source: {0}", source);
+
+ boolean isJoystick =
+ ((source & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) ||
+ ((source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK);
+
+ if (isJoystick && joyInput != null) {
+// logger.log(Level.INFO, "onGenericMotion source: {0}, isJoystick: {1}",
+// new Object[]{source, isJoystick});
+ // send the event to the touch processor
+ consumed = consumed || ((AndroidJoyInput14)joyInput).onGenericMotion(event);
+ }
+
+ return consumed;
+ }
+
+ @Override
+ public boolean onKey(View view, int keyCode, KeyEvent event) {
+ if (view != getView()) {
+ return false;
+ }
+
+ boolean consumed = false;
+
+// logger.log(Level.INFO, "onKey keyCode: {0}, action: {1}, event: {2}",
+// new Object[]{KeyEvent.keyCodeToString(keyCode), event.getAction(), event});
+ int source = event.getSource();
+// logger.log(Level.INFO, "onKey source: {0}", source);
+
+ boolean isTouch =
+ ((source & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) ||
+ ((source & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD);
+ boolean isJoystick =
+ ((source & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) ||
+ ((source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK);
+
+ if (isTouch && touchInput != null) {
+// logger.log(Level.INFO, "onKey source: {0}, isTouch: {1}",
+// new Object[]{source, isTouch});
+ consumed = touchInput.onKey(event);
+ }
+ if (isJoystick && joyInput != null) {
+// logger.log(Level.INFO, "onKey source: {0}, isJoystick: {1}",
+// new Object[]{source, isJoystick});
+ consumed = consumed || ((AndroidJoyInput14)joyInput).onKey(event);
+ }
+
+ return consumed;
+
+ }
+
+}
diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInputHandler.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInput.java
similarity index 84%
rename from jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInputHandler.java
rename to jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInput.java
index 2c3a1d74e..e31504520 100644
--- a/jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInputHandler.java
+++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInput.java
@@ -33,9 +33,7 @@ package com.jme3.input.android;
import android.content.Context;
import android.opengl.GLSurfaceView;
-import android.os.Build;
import android.os.Vibrator;
-import android.view.View;
import com.jme3.input.InputManager;
import com.jme3.input.JoyInput;
import com.jme3.input.Joystick;
@@ -79,15 +77,15 @@ import java.util.logging.Logger;
*
* @author iwgeric
*/
-public class AndroidJoyInputHandler implements JoyInput {
- private static final Logger logger = Logger.getLogger(AndroidJoyInputHandler.class.getName());
+public class AndroidJoyInput implements JoyInput {
+ private static final Logger logger = Logger.getLogger(AndroidJoyInput.class.getName());
- private List joystickList = new ArrayList();
+ protected AndroidInputHandler inputHandler;
+ protected List joystickList = new ArrayList();
// private boolean dontSendHistory = false;
// Internal
- private GLSurfaceView view;
private boolean initialized = false;
private RawInputListener listener = null;
private ConcurrentLinkedQueue eventQueue = new ConcurrentLinkedQueue();
@@ -96,34 +94,29 @@ public class AndroidJoyInputHandler implements JoyInput {
private boolean vibratorActive = false;
private long maxRumbleTime = 250; // 250ms
- public AndroidJoyInputHandler() {
- int buildVersion = Build.VERSION.SDK_INT;
- logger.log(Level.INFO, "Android Build Version: {0}", buildVersion);
-// if (buildVersion >= 14) {
-// touchHandler = new AndroidTouchHandler14(this);
-// } else if (buildVersion >= 8){
-// touchHandler = new AndroidTouchHandler(this);
-// }
+ public AndroidJoyInput(AndroidInputHandler inputHandler) {
+ this.inputHandler = inputHandler;
sensorJoyInput = new AndroidSensorJoyInput(this);
}
public void setView(GLSurfaceView view) {
-// if (touchHandler != null) {
-// touchHandler.setView(view);
-// }
+ if (view == null) {
+ vibrator = null;
+ } else {
+ // Get instance of Vibrator from current Context
+ vibrator = (Vibrator) view.getContext().getSystemService(Context.VIBRATOR_SERVICE);
+ if (vibrator == null) {
+ logger.log(Level.FINE, "Vibrator Service not found.");
+ }
+ }
+
if (sensorJoyInput != null) {
sensorJoyInput.setView(view);
}
- this.view = (GLSurfaceView)view;
-
- }
-
- public View getView() {
- return view;
}
public void loadSettings(AppSettings settings) {
-// sensorEventsEnabled = settings.useSensors();
+
}
public void addEvent(InputEvent event) {
@@ -155,20 +148,8 @@ public class AndroidJoyInputHandler implements JoyInput {
}
-
-
-
-
@Override
public void initialize() {
-// if (sensorJoyInput != null) {
-// sensorJoyInput.initialize();
-// }
- // Get instance of Vibrator from current Context
- vibrator = (Vibrator) view.getContext().getSystemService(Context.VIBRATOR_SERVICE);
- if (vibrator == null) {
- logger.log(Level.FINE, "Vibrator Service not found.");
- }
initialized = true;
}
@@ -211,8 +192,8 @@ public class AndroidJoyInputHandler implements JoyInput {
};
final int rumbleRepeatFrom = 0; // index into rumble pattern to repeat from
- logger.log(Level.FINE, "Rumble amount: {0}, rumbleOnDur: {1}, rumbleOffDur: {2}",
- new Object[]{amount, rumbleOnDur, rumbleOffDur});
+// logger.log(Level.FINE, "Rumble amount: {0}, rumbleOnDur: {1}, rumbleOffDur: {2}",
+// new Object[]{amount, rumbleOnDur, rumbleOffDur});
if (rumbleOnDur > 0) {
vibrator.vibrate(rumblePattern, rumbleRepeatFrom);
@@ -226,9 +207,8 @@ public class AndroidJoyInputHandler implements JoyInput {
@Override
public Joystick[] loadJoysticks(InputManager inputManager) {
+ logger.log(Level.INFO, "loading joysticks for {0}", this.getClass().getName());
joystickList.add(sensorJoyInput.loadJoystick(joystickList.size(), inputManager));
-
-
return joystickList.toArray( new Joystick[joystickList.size()] );
}
@@ -252,6 +232,4 @@ public class AndroidJoyInputHandler implements JoyInput {
}
-
-
}
diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInput14.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInput14.java
new file mode 100644
index 000000000..00478aea1
--- /dev/null
+++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidJoyInput14.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2009-2015 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.input.android;
+
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import com.jme3.input.InputManager;
+import com.jme3.input.Joystick;
+import java.util.logging.Logger;
+
+/**
+ * AndroidJoyInput14
extends AndroidJoyInput
+ * to include support for physical joysticks/gamepads.
+ *
+ * @author iwgeric
+ */
+public class AndroidJoyInput14 extends AndroidJoyInput {
+ private static final Logger logger = Logger.getLogger(AndroidJoyInput14.class.getName());
+
+ private AndroidJoystickJoyInput14 joystickJoyInput;
+
+ public AndroidJoyInput14(AndroidInputHandler inputHandler) {
+ super(inputHandler);
+ joystickJoyInput = new AndroidJoystickJoyInput14(this);
+ }
+
+ /**
+ * Pauses the joystick device listeners to save battery life if they are not needed.
+ * Used to pause when the activity pauses
+ */
+ @Override
+ public void pauseJoysticks() {
+ super.pauseJoysticks();
+
+ if (joystickJoyInput != null) {
+ joystickJoyInput.pauseJoysticks();
+ }
+ }
+
+ /**
+ * Resumes the joystick device listeners.
+ * Used to resume when the activity comes to the top of the stack
+ */
+ @Override
+ public void resumeJoysticks() {
+ super.resumeJoysticks();
+ if (joystickJoyInput != null) {
+ joystickJoyInput.resumeJoysticks();
+ }
+
+ }
+
+ @Override
+ public void destroy() {
+ super.destroy();
+ if (joystickJoyInput != null) {
+ joystickJoyInput.destroy();
+ }
+ }
+
+ @Override
+ public Joystick[] loadJoysticks(InputManager inputManager) {
+ // load the simulated joystick for device orientation
+ super.loadJoysticks(inputManager);
+ // load physical gamepads/joysticks
+ joystickList.addAll(joystickJoyInput.loadJoysticks(joystickList.size(), inputManager));
+ // return the list of joysticks back to InputManager
+ return joystickList.toArray( new Joystick[joystickList.size()] );
+ }
+
+ public boolean onGenericMotion(MotionEvent event) {
+ return joystickJoyInput.onGenericMotion(event);
+ }
+
+ public boolean onKey(KeyEvent event) {
+ return joystickJoyInput.onKey(event);
+ }
+
+}
diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidJoystickJoyInput14.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidJoystickJoyInput14.java
new file mode 100644
index 000000000..370db4f10
--- /dev/null
+++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidJoystickJoyInput14.java
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2009-2015 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.input.android;
+
+import android.view.InputDevice;
+import android.view.InputDevice.MotionRange;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import com.jme3.input.AbstractJoystick;
+import com.jme3.input.DefaultJoystickAxis;
+import com.jme3.input.DefaultJoystickButton;
+import com.jme3.input.InputManager;
+import com.jme3.input.JoyInput;
+import com.jme3.input.Joystick;
+import com.jme3.input.JoystickAxis;
+import com.jme3.input.JoystickButton;
+import com.jme3.input.event.JoyAxisEvent;
+import com.jme3.input.event.JoyButtonEvent;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Main class that creates and manages Android inputs for physical gamepads/joysticks.
+ *
+ * @author iwgeric
+ */
+public class AndroidJoystickJoyInput14 {
+ private static final Logger logger = Logger.getLogger(AndroidJoystickJoyInput14.class.getName());
+
+ private boolean loaded = false;
+ private AndroidJoyInput joyInput;
+ private Map joystickIndex = new HashMap();
+
+ private static int[] AndroidGamepadButtons = {
+ // Dpad buttons
+ KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN,
+ KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT,
+ KeyEvent.KEYCODE_DPAD_CENTER,
+
+ // pressing joystick down
+ KeyEvent.KEYCODE_BUTTON_THUMBL, KeyEvent.KEYCODE_BUTTON_THUMBR,
+
+ // buttons
+ KeyEvent.KEYCODE_BUTTON_A, KeyEvent.KEYCODE_BUTTON_B,
+ KeyEvent.KEYCODE_BUTTON_X, KeyEvent.KEYCODE_BUTTON_Y,
+
+ // buttons on back of device
+ KeyEvent.KEYCODE_BUTTON_L1, KeyEvent.KEYCODE_BUTTON_R1,
+ KeyEvent.KEYCODE_BUTTON_L2, KeyEvent.KEYCODE_BUTTON_R2,
+
+ // start / select buttons
+ KeyEvent.KEYCODE_BUTTON_START, KeyEvent.KEYCODE_BUTTON_SELECT,
+ KeyEvent.KEYCODE_BUTTON_MODE,
+
+ };
+
+ public AndroidJoystickJoyInput14(AndroidJoyInput joyInput) {
+ this.joyInput = joyInput;
+ }
+
+
+ public void pauseJoysticks() {
+
+ }
+
+ public void resumeJoysticks() {
+
+ }
+
+ public void destroy() {
+
+ }
+
+ public List loadJoysticks(int joyId, InputManager inputManager) {
+ logger.log(Level.INFO, "loading Joystick devices");
+ ArrayList joysticks = new ArrayList();
+ joysticks.clear();
+ joystickIndex.clear();
+
+ ArrayList gameControllerDeviceIds = new ArrayList();
+ int[] deviceIds = InputDevice.getDeviceIds();
+ for (int deviceId : deviceIds) {
+ InputDevice dev = InputDevice.getDevice(deviceId);
+ int sources = dev.getSources();
+ logger.log(Level.FINE, "deviceId[{0}] sources: {1}", new Object[]{deviceId, sources});
+
+ // Verify that the device has gamepad buttons, control sticks, or both.
+ if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) ||
+ ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK)) {
+ // This device is a game controller. Store its device ID.
+ if (!gameControllerDeviceIds.contains(deviceId)) {
+ gameControllerDeviceIds.add(deviceId);
+ logger.log(Level.FINE, "Attempting to create joystick for device: {0}", dev);
+ // Create an AndroidJoystick and store the InputDevice so we
+ // can later correspond the input from the InputDevice to the
+ // appropriate jME Joystick event
+ AndroidJoystick joystick = new AndroidJoystick(inputManager,
+ joyInput,
+ dev,
+ joyId+joysticks.size(),
+ dev.getName());
+ joystickIndex.put(deviceId, joystick);
+ joysticks.add(joystick);
+
+ // Each analog input is reported as a MotionRange
+ // The axis number corresponds to the type of axis
+ // The AndroidJoystick.addAxis(MotionRange) converts the axis
+ // type reported by Android into the jME Joystick axis
+ List motionRanges = dev.getMotionRanges();
+ for (MotionRange motionRange: motionRanges) {
+ logger.log(Level.INFO, "motion range: {0}", motionRange.toString());
+ logger.log(Level.INFO, "axis: {0}", motionRange.getAxis());
+ JoystickAxis axis = joystick.addAxis(motionRange);
+ logger.log(Level.INFO, "added axis: {0}", axis);
+ }
+
+ // InputDevice has a method for determining if a keyCode is
+ // supported (InputDevice public boolean[] hasKeys (int... keys)).
+ // But this method wasn't added until rev 19 (Android 4.4)
+ // Therefore, we only can query the entire device and see if
+ // any InputDevice supports the keyCode. This may result in
+ // buttons being configured that don't exist on the specific
+ // device, but I haven't found a better way yet.
+ for (int keyCode: AndroidGamepadButtons) {
+ logger.log(Level.INFO, "button[{0}]: {1}",
+ new Object[]{keyCode, KeyCharacterMap.deviceHasKey(keyCode)});
+ if (KeyCharacterMap.deviceHasKey(keyCode)) {
+ // add button even though we aren't sure if the button
+ // actually exists on this InputDevice
+ logger.log(Level.INFO, "button[{0}] exists somewhere", keyCode);
+ JoystickButton button = joystick.addButton(keyCode);
+ logger.log(Level.INFO, "added button: {0}", button);
+ }
+ }
+
+ }
+ }
+ }
+
+
+ loaded = true;
+ return joysticks;
+ }
+
+ public boolean onGenericMotion(MotionEvent event) {
+ boolean consumed = false;
+// logger.log(Level.INFO, "onGenericMotion event: {0}", event);
+ event.getDeviceId();
+ event.getSource();
+// logger.log(Level.INFO, "deviceId: {0}, source: {1}", new Object[]{event.getDeviceId(), event.getSource()});
+ AndroidJoystick joystick = joystickIndex.get(event.getDeviceId());
+ if (joystick != null) {
+ for (int androidAxis: joystick.getAndroidAxes()) {
+ String axisName = MotionEvent.axisToString(androidAxis);
+ float value = event.getAxisValue(androidAxis);
+ int action = event.getAction();
+ if (action == MotionEvent.ACTION_MOVE) {
+// logger.log(Level.INFO, "MOVE axis num: {0}, axisName: {1}, value: {2}",
+// new Object[]{androidAxis, axisName, value});
+ JoystickAxis axis = joystick.getAxis(androidAxis);
+ if (axis != null) {
+// logger.log(Level.INFO, "MOVE axis num: {0}, axisName: {1}, value: {2}, deadzone: {3}",
+// new Object[]{androidAxis, axisName, value, axis.getDeadZone()});
+ JoyAxisEvent axisEvent = new JoyAxisEvent(axis, value);
+ joyInput.addEvent(axisEvent);
+ consumed = true;
+ } else {
+// logger.log(Level.INFO, "axis was null for axisName: {0}", axisName);
+ }
+ } else {
+// logger.log(Level.INFO, "action: {0}", action);
+ }
+ }
+ }
+
+ return consumed;
+ }
+
+ public boolean onKey(KeyEvent event) {
+ boolean consumed = false;
+// logger.log(Level.INFO, "onKey event: {0}", event);
+
+ event.getDeviceId();
+ event.getSource();
+ AndroidJoystick joystick = joystickIndex.get(event.getDeviceId());
+ if (joystick != null) {
+ JoystickButton button = joystick.getButton(event.getKeyCode());
+ if (button != null) {
+ boolean pressed = event.getAction() == KeyEvent.ACTION_DOWN;
+ JoyButtonEvent buttonEvent = new JoyButtonEvent(button, pressed);
+ joyInput.addEvent(buttonEvent);
+ consumed = true;
+ }
+ }
+
+ return consumed;
+ }
+
+ protected class AndroidJoystick extends AbstractJoystick {
+
+ private JoystickAxis nullAxis;
+ private InputDevice device;
+ private JoystickAxis xAxis;
+ private JoystickAxis yAxis;
+ private JoystickAxis povX;
+ private JoystickAxis povY;
+ private Map axisIndex = new HashMap();
+ private Map buttonIndex = new HashMap();
+
+ public AndroidJoystick( InputManager inputManager, JoyInput joyInput, InputDevice device,
+ int joyId, String name ) {
+ super( inputManager, joyInput, joyId, name );
+
+ this.device = device;
+
+ 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 JoystickAxis getAxis(int androidAxis) {
+ return axisIndex.get(androidAxis);
+ }
+
+ protected Set getAndroidAxes() {
+ return axisIndex.keySet();
+ }
+
+ protected JoystickButton getButton(int keyCode) {
+ return buttonIndex.get(keyCode);
+ }
+
+ protected JoystickButton addButton( int keyCode ) {
+
+// logger.log(Level.FINE, "Adding button: {0}", keyCode);
+
+ String name = KeyEvent.keyCodeToString(keyCode);
+ String logicalId = KeyEvent.keyCodeToString(keyCode);
+ // A/B/X/Y buttons
+ if (keyCode == KeyEvent.KEYCODE_BUTTON_Y) {
+ logicalId = JoystickButton.BUTTON_0;
+ } else if (keyCode == KeyEvent.KEYCODE_BUTTON_A) {
+ logicalId = JoystickButton.BUTTON_2;
+ } else if (keyCode == KeyEvent.KEYCODE_BUTTON_B) {
+ logicalId = JoystickButton.BUTTON_1;
+ } else if (keyCode == KeyEvent.KEYCODE_BUTTON_X) {
+ logicalId = JoystickButton.BUTTON_3;
+ // Front buttons Some of these have the top ones and the bottoms ones flipped.
+ } else if (keyCode == KeyEvent.KEYCODE_BUTTON_L1) {
+ logicalId = JoystickButton.BUTTON_4;
+ } else if (keyCode == KeyEvent.KEYCODE_BUTTON_R1) {
+ logicalId = JoystickButton.BUTTON_5;
+ } else if (keyCode == KeyEvent.KEYCODE_BUTTON_L2) {
+ logicalId = JoystickButton.BUTTON_6;
+ } else if (keyCode == KeyEvent.KEYCODE_BUTTON_R2) {
+ logicalId = JoystickButton.BUTTON_7;
+// // Dpad buttons
+// } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
+// logicalId = JoystickButton.BUTTON_8;
+// } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
+// logicalId = JoystickButton.BUTTON_9;
+// } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
+// logicalId = JoystickButton.BUTTON_8;
+// } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
+// logicalId = JoystickButton.BUTTON_9;
+ // Select and start buttons
+ } else if (keyCode == KeyEvent.KEYCODE_BUTTON_SELECT) {
+ logicalId = JoystickButton.BUTTON_8;
+ } else if (keyCode == KeyEvent.KEYCODE_BUTTON_START) {
+ logicalId = JoystickButton.BUTTON_9;
+ // Joystick push buttons
+ } else if (keyCode == KeyEvent.KEYCODE_BUTTON_THUMBL) {
+ logicalId = JoystickButton.BUTTON_10;
+ } else if (keyCode == KeyEvent.KEYCODE_BUTTON_THUMBR) {
+ logicalId = JoystickButton.BUTTON_11;
+ }
+
+ JoystickButton button = new DefaultJoystickButton( getInputManager(), this, getButtonCount(),
+ name, logicalId );
+ addButton(button);
+ buttonIndex.put( keyCode, button );
+ return button;
+ }
+
+ protected JoystickAxis addAxis(MotionRange motionRange) {
+
+ String name = MotionEvent.axisToString(motionRange.getAxis());
+
+ String logicalId = MotionEvent.axisToString(motionRange.getAxis());
+ if (motionRange.getAxis() == MotionEvent.AXIS_X) {
+ logicalId = JoystickAxis.X_AXIS;
+ } else if (motionRange.getAxis() == MotionEvent.AXIS_Y) {
+ logicalId = JoystickAxis.Y_AXIS;
+ } else if (motionRange.getAxis() == MotionEvent.AXIS_Z) {
+ logicalId = JoystickAxis.Z_AXIS;
+ } else if (motionRange.getAxis() == MotionEvent.AXIS_RZ) {
+ logicalId = JoystickAxis.Z_ROTATION;
+ } else if (motionRange.getAxis() == MotionEvent.AXIS_HAT_X) {
+ logicalId = JoystickAxis.POV_X;
+ } else if (motionRange.getAxis() == MotionEvent.AXIS_HAT_Y) {
+ logicalId = JoystickAxis.POV_Y;
+ }
+// String logicalId = JoystickCompatibilityMappings.remapComponent( controller.getName(), original );
+// if( name != original ) {
+// logger.log(Level.FINE, "Remapped:" + original + " to:" + logicalId);
+// }
+
+ JoystickAxis axis = new DefaultJoystickAxis(getInputManager(),
+ this,
+ getAxisCount(),
+ name,
+ logicalId,
+ true,
+ true,
+ motionRange.getFlat());
+
+ if (motionRange.getAxis() == MotionEvent.AXIS_X) {
+ xAxis = axis;
+ }
+ if (motionRange.getAxis() == MotionEvent.AXIS_Y) {
+ yAxis = axis;
+ }
+ if (motionRange.getAxis() == MotionEvent.AXIS_HAT_X) {
+ povX = axis;
+ }
+ if (motionRange.getAxis() == MotionEvent.AXIS_HAT_Y) {
+ povY = axis;
+ }
+
+ addAxis(axis);
+ axisIndex.put(motionRange.getAxis(), axis);
+ return axis;
+ }
+
+ @Override
+ public JoystickAxis getXAxis() {
+ return xAxis;
+ }
+
+ @Override
+ public JoystickAxis getYAxis() {
+ return yAxis;
+ }
+
+ @Override
+ public JoystickAxis getPovXAxis() {
+ return povX;
+ }
+
+ @Override
+ public JoystickAxis getPovYAxis() {
+ return povY;
+ }
+
+ @Override
+ public int getXAxisIndex(){
+ return xAxis.getAxisId();
+ }
+
+ @Override
+ public int getYAxisIndex(){
+ return yAxis.getAxisId();
+ }
+ }
+}
diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidKeyHandler.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidKeyHandler.java
deleted file mode 100644
index 997974c31..000000000
--- a/jme3-android/src/main/java/com/jme3/input/android/AndroidKeyHandler.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2009-2012 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.jme3.input.android;
-
-import android.content.Context;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.inputmethod.InputMethodManager;
-import com.jme3.input.event.KeyInputEvent;
-import com.jme3.input.event.TouchEvent;
-import java.util.logging.Logger;
-
-/**
- * AndroidKeyHandler recieves onKey events from the Android system and creates
- * the jME KeyEvents. onKey is used by Android to receive keys from the keyboard
- * or device buttons. All key events are consumed by jME except for the Volume
- * buttons and menu button.
- *
- * This class also provides the functionality to display or hide the soft keyboard
- * for inputing single key events. Use OGLESContext to display an dialog to type
- * in complete strings.
- *
- * @author iwgeric
- */
-public class AndroidKeyHandler implements View.OnKeyListener {
- private static final Logger logger = Logger.getLogger(AndroidKeyHandler.class.getName());
-
- private AndroidInputHandler androidInput;
- private boolean sendKeyEvents = true;
-
- public AndroidKeyHandler(AndroidInputHandler androidInput) {
- this.androidInput = androidInput;
- }
-
- public void initialize() {
- }
-
- public void destroy() {
- }
-
- public void setView(View view) {
- if (view != null) {
- view.setOnKeyListener(this);
- } else {
- androidInput.getView().setOnKeyListener(null);
- }
- }
-
- /**
- * onKey gets called from android thread on key events
- */
- public boolean onKey(View view, int keyCode, KeyEvent event) {
- if (androidInput.isInitialized() && view != androidInput.getView()) {
- return false;
- }
-
- TouchEvent evt;
- // TODO: get touch event from pool
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- evt = new TouchEvent();
- evt.set(TouchEvent.Type.KEY_DOWN);
- evt.setKeyCode(keyCode);
- evt.setCharacters(event.getCharacters());
- evt.setTime(event.getEventTime());
-
- // Send the event
- androidInput.addEvent(evt);
-
- } else if (event.getAction() == KeyEvent.ACTION_UP) {
- evt = new TouchEvent();
- evt.set(TouchEvent.Type.KEY_UP);
- evt.setKeyCode(keyCode);
- evt.setCharacters(event.getCharacters());
- evt.setTime(event.getEventTime());
-
- // Send the event
- androidInput.addEvent(evt);
-
- }
-
- if (androidInput.isSimulateKeyboard()) {
- KeyInputEvent kie;
- char unicodeChar = (char)event.getUnicodeChar();
- int jmeKeyCode = AndroidKeyMapping.getJmeKey(keyCode);
-
- boolean pressed = event.getAction() == KeyEvent.ACTION_DOWN;
- boolean repeating = pressed && event.getRepeatCount() > 0;
-
- kie = new KeyInputEvent(jmeKeyCode, unicodeChar, pressed, repeating);
- kie.setTime(event.getEventTime());
- androidInput.addEvent(kie);
-// logger.log(Level.FINE, "onKey keyCode: {0}, jmeKeyCode: {1}, pressed: {2}, repeating: {3}",
-// new Object[]{keyCode, jmeKeyCode, pressed, repeating});
-// logger.log(Level.FINE, "creating KeyInputEvent: {0}", kie);
- }
-
- // consume all keys ourself except Volume Up/Down and Menu
- // Don't do Menu so that typical Android Menus can be created and used
- // by the user in MainActivity
- if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP) ||
- (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) ||
- (keyCode == KeyEvent.KEYCODE_MENU)) {
- return false;
- } else {
- return true;
- }
-
- }
-
-}
diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidKeyMapping.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidKeyMapping.java
index e99d8e9fc..32d1e0008 100644
--- a/jme3-android/src/main/java/com/jme3/input/android/AndroidKeyMapping.java
+++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidKeyMapping.java
@@ -37,13 +37,14 @@ import java.util.logging.Logger;
/**
* AndroidKeyMapping is just a utility to convert the Android keyCodes into
- * jME KeyCodes received in jME's KeyEvent will match between Desktop and Android.
- *
+ * jME KeyCodes so that events received in jME's KeyEvent will match between
+ * Desktop and Android.
+ *
* @author iwgeric
*/
public class AndroidKeyMapping {
private static final Logger logger = Logger.getLogger(AndroidKeyMapping.class.getName());
-
+
private static final int[] ANDROID_TO_JME = {
0x0, // unknown
0x0, // key code soft left
@@ -141,9 +142,13 @@ public class AndroidKeyMapping {
0x0,//media fastforward
0x0,//mute
};
-
+
public static int getJmeKey(int androidKey) {
- return ANDROID_TO_JME[androidKey];
+ if (androidKey > ANDROID_TO_JME.length) {
+ return androidKey;
+ } else {
+ return ANDROID_TO_JME[androidKey];
+ }
}
-
+
}
diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidSensorJoyInput.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidSensorJoyInput.java
index 823aa3d9d..cdd7e6494 100644
--- a/jme3-android/src/main/java/com/jme3/input/android/AndroidSensorJoyInput.java
+++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidSensorJoyInput.java
@@ -75,15 +75,15 @@ import java.util.logging.Logger;
public class AndroidSensorJoyInput implements SensorEventListener {
private final static Logger logger = Logger.getLogger(AndroidSensorJoyInput.class.getName());
- private AndroidJoyInputHandler joyHandler;
+ private AndroidJoyInput joyInput;
private SensorManager sensorManager = null;
private WindowManager windowManager = null;
private IntMap sensors = new IntMap();
private int lastRotation = 0;
private boolean loaded = false;
- public AndroidSensorJoyInput(AndroidJoyInputHandler joyHandler) {
- this.joyHandler = joyHandler;
+ public AndroidSensorJoyInput(AndroidJoyInput joyInput) {
+ this.joyInput = joyInput;
}
/**
@@ -96,7 +96,7 @@ public class AndroidSensorJoyInput implements SensorEventListener {
int sensorAccuracy = -1;
float[] lastValues;
final Object valuesLock = new Object();
- ArrayList axes = new ArrayList();
+ ArrayList axes = new ArrayList();
boolean enabled = false;
boolean haveData = false;
@@ -306,7 +306,7 @@ public class AndroidSensorJoyInput implements SensorEventListener {
*/
private boolean updateOrientation() {
SensorData sensorData;
- AndroidJoystickAxis axis;
+ AndroidSensorJoystickAxis axis;
final float[] curInclinationMat = new float[16];
final float[] curRotationMat = new float[16];
final float[] rotatedRotationMat = new float[16];
@@ -374,7 +374,7 @@ public class AndroidSensorJoyInput implements SensorEventListener {
sensorData.haveData = true;
} else {
if (axis.isChanged()) {
- joyHandler.addEvent(new JoyAxisEvent(axis, axis.getJoystickAxisValue()));
+ joyInput.addEvent(new JoyAxisEvent(axis, axis.getJoystickAxisValue()));
}
}
}
@@ -401,10 +401,10 @@ public class AndroidSensorJoyInput implements SensorEventListener {
public Joystick loadJoystick(int joyId, InputManager inputManager) {
SensorData sensorData;
- AndroidJoystickAxis axis;
+ AndroidSensorJoystickAxis axis;
- AndroidJoystick joystick = new AndroidJoystick(inputManager,
- joyHandler,
+ AndroidSensorJoystick joystick = new AndroidSensorJoystick(inputManager,
+ joyInput,
joyId,
"AndroidSensorsJoystick");
@@ -522,15 +522,15 @@ public class AndroidSensorJoyInput implements SensorEventListener {
if (!loaded) {
return;
}
- logger.log(Level.FINE, "onSensorChanged for {0}: accuracy: {1}, values: {2}",
- new Object[]{se.sensor.getName(), se.accuracy, se.values});
+// logger.log(Level.FINE, "onSensorChanged for {0}: accuracy: {1}, values: {2}",
+// new Object[]{se.sensor.getName(), se.accuracy, se.values});
int sensorType = se.sensor.getType();
SensorData sensorData = sensors.get(sensorType);
if (sensorData != null) {
- logger.log(Level.FINE, "sensorData name: {0}, enabled: {1}, unreliable: {2}",
- new Object[]{sensorData.sensor.getName(), sensorData.enabled, sensorData.sensorAccuracy == SensorManager.SENSOR_STATUS_UNRELIABLE});
+// logger.log(Level.FINE, "sensorData name: {0}, enabled: {1}, unreliable: {2}",
+// new Object[]{sensorData.sensor.getName(), sensorData.enabled, sensorData.sensorAccuracy == SensorManager.SENSOR_STATUS_UNRELIABLE});
}
if (sensorData != null && sensorData.sensor.equals(se.sensor) && sensorData.enabled) {
@@ -543,8 +543,8 @@ public class AndroidSensorJoyInput implements SensorEventListener {
}
}
- if (sensorData != null && sensorData.axes.size() > 0) {
- AndroidJoystickAxis axis;
+ if (sensorData.axes.size() > 0) {
+ AndroidSensorJoystickAxis axis;
for (int i=0; i lastPositions = new HashMap();
-
- protected int numPointers = 0;
-
- protected AndroidInputHandler androidInput;
- protected AndroidGestureHandler gestureHandler;
-
- public AndroidTouchHandler(AndroidInputHandler androidInput, AndroidGestureHandler gestureHandler) {
- this.androidInput = androidInput;
- this.gestureHandler = gestureHandler;
- }
-
- public void initialize() {
- }
-
- public void destroy() {
- setView(null);
- }
-
- public void setView(View view) {
- if (view != null) {
- view.setOnTouchListener(this);
- } else {
- androidInput.getView().setOnTouchListener(null);
- }
- }
-
- protected int getPointerIndex(MotionEvent event) {
- return (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
- >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- }
-
- protected int getPointerId(MotionEvent event) {
- return event.getPointerId(getPointerIndex(event));
- }
-
- protected int getAction(MotionEvent event) {
- return event.getAction() & MotionEvent.ACTION_MASK;
- }
-
- /**
- * onTouch gets called from android thread on touch events
- */
- public boolean onTouch(View view, MotionEvent event) {
- if (!androidInput.isInitialized() || view != androidInput.getView()) {
- return false;
- }
-
- boolean bWasHandled = false;
- TouchEvent touch = null;
- // System.out.println("native : " + event.getAction());
- int action = getAction(event);
- int pointerIndex = getPointerIndex(event);
- int pointerId = getPointerId(event);
- Vector2f lastPos = lastPositions.get(pointerId);
- float jmeX;
- float jmeY;
-
- numPointers = event.getPointerCount();
-
- // final int historySize = event.getHistorySize();
- //final int pointerCount = event.getPointerCount();
- switch (getAction(event)) {
- case MotionEvent.ACTION_POINTER_DOWN:
- case MotionEvent.ACTION_DOWN:
- jmeX = androidInput.getJmeX(event.getX(pointerIndex));
- jmeY = androidInput.invertY(androidInput.getJmeY(event.getY(pointerIndex)));
- touch = androidInput.getFreeTouchEvent();
- touch.set(TouchEvent.Type.DOWN, jmeX, jmeY, 0, 0);
- touch.setPointerId(pointerId);
- touch.setTime(event.getEventTime());
- touch.setPressure(event.getPressure(pointerIndex));
-
- lastPos = new Vector2f(jmeX, jmeY);
- lastPositions.put(pointerId, lastPos);
-
- processEvent(touch);
-
- bWasHandled = true;
- break;
- case MotionEvent.ACTION_POINTER_UP:
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- jmeX = androidInput.getJmeX(event.getX(pointerIndex));
- jmeY = androidInput.invertY(androidInput.getJmeY(event.getY(pointerIndex)));
- touch = androidInput.getFreeTouchEvent();
- touch.set(TouchEvent.Type.UP, jmeX, jmeY, 0, 0);
- touch.setPointerId(pointerId);
- touch.setTime(event.getEventTime());
- touch.setPressure(event.getPressure(pointerIndex));
- lastPositions.remove(pointerId);
-
- processEvent(touch);
-
- bWasHandled = true;
- break;
- case MotionEvent.ACTION_MOVE:
- // Convert all pointers into events
- for (int p = 0; p < event.getPointerCount(); p++) {
- jmeX = androidInput.getJmeX(event.getX(p));
- jmeY = androidInput.invertY(androidInput.getJmeY(event.getY(p)));
- lastPos = lastPositions.get(event.getPointerId(p));
- if (lastPos == null) {
- lastPos = new Vector2f(jmeX, jmeY);
- lastPositions.put(event.getPointerId(p), lastPos);
- }
-
- float dX = jmeX - lastPos.x;
- float dY = jmeY - lastPos.y;
- if (dX != 0 || dY != 0) {
- touch = androidInput.getFreeTouchEvent();
- touch.set(TouchEvent.Type.MOVE, jmeX, jmeY, dX, dY);
- touch.setPointerId(event.getPointerId(p));
- touch.setTime(event.getEventTime());
- touch.setPressure(event.getPressure(p));
- lastPos.set(jmeX, jmeY);
-
- processEvent(touch);
-
- bWasHandled = true;
- }
- }
- break;
- case MotionEvent.ACTION_OUTSIDE:
- break;
-
- }
-
- // Try to detect gestures
- if (gestureHandler != null) {
- gestureHandler.detectGesture(event);
- }
-
- return bWasHandled;
- }
-
- protected void processEvent(TouchEvent event) {
- // Add the touch event
- androidInput.addEvent(event);
- // MouseEvents do not support multi-touch, so only evaluate 1 finger pointer events
- if (androidInput.isSimulateMouse() && numPointers == 1) {
- InputEvent mouseEvent = generateMouseEvent(event);
- if (mouseEvent != null) {
- // Add the mouse event
- androidInput.addEvent(mouseEvent);
- }
- }
-
- }
-
- // TODO: Ring Buffer for mouse events?
- protected InputEvent generateMouseEvent(TouchEvent event) {
- InputEvent inputEvent = null;
- int newX;
- int newY;
- int newDX;
- int newDY;
-
- if (androidInput.isMouseEventsInvertX()) {
- newX = (int) (androidInput.invertX(event.getX()));
- newDX = (int)event.getDeltaX() * -1;
- } else {
- newX = (int) event.getX();
- newDX = (int)event.getDeltaX();
- }
-
- if (androidInput.isMouseEventsInvertY()) {
- newY = (int) (androidInput.invertY(event.getY()));
- newDY = (int)event.getDeltaY() * -1;
- } else {
- newY = (int) event.getY();
- newDY = (int)event.getDeltaY();
- }
-
- switch (event.getType()) {
- case DOWN:
- // Handle mouse down event
- inputEvent = new MouseButtonEvent(0, true, newX, newY);
- inputEvent.setTime(event.getTime());
- break;
-
- case UP:
- // Handle mouse up event
- inputEvent = new MouseButtonEvent(0, false, newX, newY);
- inputEvent.setTime(event.getTime());
- break;
-
- case HOVER_MOVE:
- case MOVE:
- inputEvent = new MouseMotionEvent(newX, newY, newDX, newDY, (int)event.getScaleSpan(), (int)event.getDeltaScaleSpan());
- inputEvent.setTime(event.getTime());
- break;
- }
-
- return inputEvent;
- }
-
-}
diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidTouchInput.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidTouchInput.java
new file mode 100644
index 000000000..bddc5fab3
--- /dev/null
+++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidTouchInput.java
@@ -0,0 +1,475 @@
+/*
+ * Copyright (c) 2009-2012 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.jme3.input.android;
+
+import android.view.GestureDetector;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import com.jme3.input.RawInputListener;
+import com.jme3.input.TouchInput;
+import com.jme3.input.event.InputEvent;
+import com.jme3.input.event.KeyInputEvent;
+import com.jme3.input.event.MouseButtonEvent;
+import com.jme3.input.event.MouseMotionEvent;
+import com.jme3.input.event.TouchEvent;
+import static com.jme3.input.event.TouchEvent.Type.DOWN;
+import static com.jme3.input.event.TouchEvent.Type.MOVE;
+import static com.jme3.input.event.TouchEvent.Type.UP;
+import com.jme3.math.Vector2f;
+import com.jme3.system.AppSettings;
+import java.util.HashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * AndroidTouchInput is the base class that receives touch inputs from the
+ * Android system and creates the TouchEvents for jME. This class is designed
+ * to handle the base touch events for Android rev 9 (Android 2.3). This is
+ * extended by other classes to add features that were introducted after
+ * Android rev 9.
+ *
+ * @author iwgeric
+ */
+public class AndroidTouchInput implements TouchInput {
+ private static final Logger logger = Logger.getLogger(AndroidTouchInput.class.getName());
+
+ private boolean mouseEventsEnabled = true;
+ private boolean mouseEventsInvertX = false;
+ private boolean mouseEventsInvertY = false;
+ private boolean keyboardEventsEnabled = false;
+ private boolean dontSendHistory = false;
+
+ protected int numPointers = 0;
+ final private HashMap lastPositions = new HashMap();
+ final private ConcurrentLinkedQueue inputEventQueue = new ConcurrentLinkedQueue();
+ private final static int MAX_TOUCH_EVENTS = 1024;
+ private final TouchEventPool touchEventPool = new TouchEventPool(MAX_TOUCH_EVENTS);
+ private float scaleX = 1f;
+ private float scaleY = 1f;
+
+ private boolean initialized = false;
+ private RawInputListener listener = null;
+
+ private GestureDetector gestureDetector;
+ private ScaleGestureDetector scaleDetector;
+
+ protected AndroidInputHandler androidInput;
+
+ public AndroidTouchInput(AndroidInputHandler androidInput) {
+ this.androidInput = androidInput;
+ }
+
+ public GestureDetector getGestureDetector() {
+ return gestureDetector;
+ }
+
+ public void setGestureDetector(GestureDetector gestureDetector) {
+ this.gestureDetector = gestureDetector;
+ }
+
+ public ScaleGestureDetector getScaleDetector() {
+ return scaleDetector;
+ }
+
+ public void setScaleDetector(ScaleGestureDetector scaleDetector) {
+ this.scaleDetector = scaleDetector;
+ }
+
+ public float invertX(float origX) {
+ return getJmeX(androidInput.getView().getWidth()) - origX;
+ }
+
+ public float invertY(float origY) {
+ return getJmeY(androidInput.getView().getHeight()) - origY;
+ }
+
+ public float getJmeX(float origX) {
+ return origX * scaleX;
+ }
+
+ public float getJmeY(float origY) {
+ return origY * scaleY;
+ }
+
+ public void loadSettings(AppSettings settings) {
+ keyboardEventsEnabled = settings.isEmulateKeyboard();
+ mouseEventsEnabled = settings.isEmulateMouse();
+ mouseEventsInvertX = settings.isEmulateMouseFlipX();
+ mouseEventsInvertY = settings.isEmulateMouseFlipY();
+
+ // view width and height are 0 until the view is displayed on the screen
+ if (androidInput.getView().getWidth() != 0 && androidInput.getView().getHeight() != 0) {
+ scaleX = (float)settings.getWidth() / (float)androidInput.getView().getWidth();
+ scaleY = (float)settings.getHeight() / (float)androidInput.getView().getHeight();
+ }
+ logger.log(Level.FINE, "Setting input scaling, scaleX: {0}, scaleY: {1}",
+ new Object[]{scaleX, scaleY});
+
+
+ }
+
+
+ protected int getPointerIndex(MotionEvent event) {
+ return (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
+ >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ }
+
+ protected int getPointerId(MotionEvent event) {
+ return event.getPointerId(getPointerIndex(event));
+ }
+
+ protected int getAction(MotionEvent event) {
+ return event.getAction() & MotionEvent.ACTION_MASK;
+ }
+
+ public boolean onTouch(MotionEvent event) {
+ if (!isInitialized()) {
+ return false;
+ }
+
+ boolean bWasHandled = false;
+ TouchEvent touch = null;
+ // System.out.println("native : " + event.getAction());
+ int action = getAction(event);
+ int pointerIndex = getPointerIndex(event);
+ int pointerId = getPointerId(event);
+ Vector2f lastPos = lastPositions.get(pointerId);
+ float jmeX;
+ float jmeY;
+
+ numPointers = event.getPointerCount();
+
+ // final int historySize = event.getHistorySize();
+ //final int pointerCount = event.getPointerCount();
+ switch (getAction(event)) {
+ case MotionEvent.ACTION_POINTER_DOWN:
+ case MotionEvent.ACTION_DOWN:
+ jmeX = getJmeX(event.getX(pointerIndex));
+ jmeY = invertY(getJmeY(event.getY(pointerIndex)));
+ touch = getFreeTouchEvent();
+ touch.set(TouchEvent.Type.DOWN, jmeX, jmeY, 0, 0);
+ touch.setPointerId(pointerId);
+ touch.setTime(event.getEventTime());
+ touch.setPressure(event.getPressure(pointerIndex));
+
+ lastPos = new Vector2f(jmeX, jmeY);
+ lastPositions.put(pointerId, lastPos);
+
+ addEvent(touch);
+ addEvent(generateMouseEvent(touch));
+
+ bWasHandled = true;
+ break;
+ case MotionEvent.ACTION_POINTER_UP:
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ jmeX = getJmeX(event.getX(pointerIndex));
+ jmeY = invertY(getJmeY(event.getY(pointerIndex)));
+ touch = getFreeTouchEvent();
+ touch.set(TouchEvent.Type.UP, jmeX, jmeY, 0, 0);
+ touch.setPointerId(pointerId);
+ touch.setTime(event.getEventTime());
+ touch.setPressure(event.getPressure(pointerIndex));
+ lastPositions.remove(pointerId);
+
+ addEvent(touch);
+ addEvent(generateMouseEvent(touch));
+
+ bWasHandled = true;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ // Convert all pointers into events
+ for (int p = 0; p < event.getPointerCount(); p++) {
+ jmeX = getJmeX(event.getX(p));
+ jmeY = invertY(getJmeY(event.getY(p)));
+ lastPos = lastPositions.get(event.getPointerId(p));
+ if (lastPos == null) {
+ lastPos = new Vector2f(jmeX, jmeY);
+ lastPositions.put(event.getPointerId(p), lastPos);
+ }
+
+ float dX = jmeX - lastPos.x;
+ float dY = jmeY - lastPos.y;
+ if (dX != 0 || dY != 0) {
+ touch = getFreeTouchEvent();
+ touch.set(TouchEvent.Type.MOVE, jmeX, jmeY, dX, dY);
+ touch.setPointerId(event.getPointerId(p));
+ touch.setTime(event.getEventTime());
+ touch.setPressure(event.getPressure(p));
+ lastPos.set(jmeX, jmeY);
+
+ addEvent(touch);
+ addEvent(generateMouseEvent(touch));
+
+ bWasHandled = true;
+ }
+ }
+ break;
+ case MotionEvent.ACTION_OUTSIDE:
+ break;
+
+ }
+
+ // Try to detect gestures
+ if (gestureDetector != null) {
+ gestureDetector.onTouchEvent(event);
+ }
+ if (scaleDetector != null) {
+ scaleDetector.onTouchEvent(event);
+ }
+
+ return bWasHandled;
+ }
+
+ // TODO: Ring Buffer for mouse events?
+ public InputEvent generateMouseEvent(TouchEvent event) {
+ InputEvent inputEvent = null;
+ int newX;
+ int newY;
+ int newDX;
+ int newDY;
+
+ // MouseEvents do not support multi-touch, so only evaluate 1 finger pointer events
+ if (!isSimulateMouse() || numPointers > 1) {
+ return null;
+ }
+
+
+ if (isMouseEventsInvertX()) {
+ newX = (int) (invertX(event.getX()));
+ newDX = (int)event.getDeltaX() * -1;
+ } else {
+ newX = (int) event.getX();
+ newDX = (int)event.getDeltaX();
+ }
+
+ if (isMouseEventsInvertY()) {
+ newY = (int) (invertY(event.getY()));
+ newDY = (int)event.getDeltaY() * -1;
+ } else {
+ newY = (int) event.getY();
+ newDY = (int)event.getDeltaY();
+ }
+
+ switch (event.getType()) {
+ case DOWN:
+ // Handle mouse down event
+ inputEvent = new MouseButtonEvent(0, true, newX, newY);
+ inputEvent.setTime(event.getTime());
+ break;
+
+ case UP:
+ // Handle mouse up event
+ inputEvent = new MouseButtonEvent(0, false, newX, newY);
+ inputEvent.setTime(event.getTime());
+ break;
+
+ case HOVER_MOVE:
+ case MOVE:
+ inputEvent = new MouseMotionEvent(newX, newY, newDX, newDY, (int)event.getScaleSpan(), (int)event.getDeltaScaleSpan());
+ inputEvent.setTime(event.getTime());
+ break;
+ }
+
+ return inputEvent;
+ }
+
+
+ public boolean onKey(KeyEvent event) {
+ if (!isInitialized()) {
+ return false;
+ }
+
+ TouchEvent evt;
+ // TODO: get touch event from pool
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ evt = new TouchEvent();
+ evt.set(TouchEvent.Type.KEY_DOWN);
+ evt.setKeyCode(event.getKeyCode());
+ evt.setCharacters(event.getCharacters());
+ evt.setTime(event.getEventTime());
+
+ // Send the event
+ addEvent(evt);
+
+ } else if (event.getAction() == KeyEvent.ACTION_UP) {
+ evt = new TouchEvent();
+ evt.set(TouchEvent.Type.KEY_UP);
+ evt.setKeyCode(event.getKeyCode());
+ evt.setCharacters(event.getCharacters());
+ evt.setTime(event.getEventTime());
+
+ // Send the event
+ addEvent(evt);
+
+ }
+
+ if (isSimulateKeyboard()) {
+ KeyInputEvent kie;
+ char unicodeChar = (char)event.getUnicodeChar();
+ int jmeKeyCode = AndroidKeyMapping.getJmeKey(event.getKeyCode());
+
+ boolean pressed = event.getAction() == KeyEvent.ACTION_DOWN;
+ boolean repeating = pressed && event.getRepeatCount() > 0;
+
+ kie = new KeyInputEvent(jmeKeyCode, unicodeChar, pressed, repeating);
+ kie.setTime(event.getEventTime());
+ addEvent(kie);
+// logger.log(Level.FINE, "onKey keyCode: {0}, jmeKeyCode: {1}, pressed: {2}, repeating: {3}",
+// new Object[]{event.getKeyCode(), jmeKeyCode, pressed, repeating});
+// logger.log(Level.FINE, "creating KeyInputEvent: {0}", kie);
+ }
+
+ // consume all keys ourself except Volume Up/Down and Menu
+ // Don't do Menu so that typical Android Menus can be created and used
+ // by the user in MainActivity
+ if ((event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP) ||
+ (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN) ||
+ (event.getKeyCode() == KeyEvent.KEYCODE_MENU)) {
+ return false;
+ } else {
+ return true;
+ }
+
+ }
+
+
+
+
+ // -----------------------------------------
+ // JME3 Input interface
+ @Override
+ public void initialize() {
+ touchEventPool.initialize();
+
+ initialized = true;
+ }
+
+ @Override
+ public void destroy() {
+ initialized = false;
+
+ touchEventPool.destroy();
+
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return initialized;
+ }
+
+ @Override
+ public void setInputListener(RawInputListener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public long getInputTimeNanos() {
+ return System.nanoTime();
+ }
+
+ @Override
+ public void update() {
+ if (listener != null) {
+ InputEvent inputEvent;
+
+ while ((inputEvent = inputEventQueue.poll()) != null) {
+ if (inputEvent instanceof TouchEvent) {
+ listener.onTouchEvent((TouchEvent)inputEvent);
+ } else if (inputEvent instanceof MouseButtonEvent) {
+ listener.onMouseButtonEvent((MouseButtonEvent)inputEvent);
+ } else if (inputEvent instanceof MouseMotionEvent) {
+ listener.onMouseMotionEvent((MouseMotionEvent)inputEvent);
+ } else if (inputEvent instanceof KeyInputEvent) {
+ listener.onKeyEvent((KeyInputEvent)inputEvent);
+ }
+ }
+ }
+ }
+
+ // -----------------------------------------
+
+ public TouchEvent getFreeTouchEvent() {
+ return touchEventPool.getNextFreeEvent();
+ }
+
+ public void addEvent(InputEvent event) {
+ if (event == null) {
+ return;
+ }
+
+ logger.log(Level.INFO, "event: {0}", event);
+
+ inputEventQueue.add(event);
+ if (event instanceof TouchEvent) {
+ touchEventPool.storeEvent((TouchEvent)event);
+ }
+
+ }
+
+ @Override
+ public void setSimulateMouse(boolean simulate) {
+ this.mouseEventsEnabled = simulate;
+ }
+
+ @Override
+ public boolean isSimulateMouse() {
+ return mouseEventsEnabled;
+ }
+
+ public boolean isMouseEventsInvertX() {
+ return mouseEventsInvertX;
+ }
+
+ public boolean isMouseEventsInvertY() {
+ return mouseEventsInvertY;
+ }
+
+ @Override
+ public void setSimulateKeyboard(boolean simulate) {
+ this.keyboardEventsEnabled = simulate;
+ }
+
+ @Override
+ public boolean isSimulateKeyboard() {
+ return keyboardEventsEnabled;
+ }
+
+ @Override
+ public void setOmitHistoricEvents(boolean dontSendHistory) {
+ this.dontSendHistory = dontSendHistory;
+ }
+
+}
diff --git a/jme3-android/src/main/java/com/jme3/input/android/AndroidTouchHandler14.java b/jme3-android/src/main/java/com/jme3/input/android/AndroidTouchInput14.java
similarity index 67%
rename from jme3-android/src/main/java/com/jme3/input/android/AndroidTouchHandler14.java
rename to jme3-android/src/main/java/com/jme3/input/android/AndroidTouchInput14.java
index 1a785a5e9..617a4b719 100644
--- a/jme3-android/src/main/java/com/jme3/input/android/AndroidTouchHandler14.java
+++ b/jme3-android/src/main/java/com/jme3/input/android/AndroidTouchInput14.java
@@ -33,7 +33,6 @@
package com.jme3.input.android;
import android.view.MotionEvent;
-import android.view.View;
import com.jme3.input.event.TouchEvent;
import com.jme3.math.Vector2f;
import java.util.HashMap;
@@ -41,36 +40,20 @@ import java.util.logging.Level;
import java.util.logging.Logger;
/**
- * AndroidTouchHandler14 is an extension of AndroidTouchHander that adds the
- * Android touch event functionality between Android rev 9 (Android 2.3) and
- * Android rev 14 (Android 4.0).
- *
+ * AndroidTouchHandler14 extends AndroidTouchHandler to process the onHover
+ * events added in Android rev 14 (Android 4.0).
+ *
* @author iwgeric
*/
-public class AndroidTouchHandler14 extends AndroidTouchHandler implements
- View.OnHoverListener {
- private static final Logger logger = Logger.getLogger(AndroidTouchHandler14.class.getName());
+public class AndroidTouchInput14 extends AndroidTouchInput {
+ private static final Logger logger = Logger.getLogger(AndroidTouchInput14.class.getName());
final private HashMap lastHoverPositions = new HashMap();
-
- public AndroidTouchHandler14(AndroidInputHandler androidInput, AndroidGestureHandler gestureHandler) {
- super(androidInput, gestureHandler);
- }
- @Override
- public void setView(View view) {
- if (view != null) {
- view.setOnHoverListener(this);
- } else {
- androidInput.getView().setOnHoverListener(null);
- }
- super.setView(view);
+ public AndroidTouchInput14(AndroidInputHandler androidInput) {
+ super(androidInput);
}
-
- public boolean onHover(View view, MotionEvent event) {
- if (view == null || view != androidInput.getView()) {
- return false;
- }
-
+
+ public boolean onHover(MotionEvent event) {
boolean consumed = false;
int action = getAction(event);
int pointerId = getPointerId(event);
@@ -78,34 +61,34 @@ public class AndroidTouchHandler14 extends AndroidTouchHandler implements
Vector2f lastPos = lastHoverPositions.get(pointerId);
float jmeX;
float jmeY;
-
+
numPointers = event.getPointerCount();
-
- logger.log(Level.INFO, "onHover pointerId: {0}, action: {1}, x: {2}, y: {3}, numPointers: {4}",
- new Object[]{pointerId, action, event.getX(), event.getY(), event.getPointerCount()});
+
+// logger.log(Level.INFO, "onHover pointerId: {0}, action: {1}, x: {2}, y: {3}, numPointers: {4}",
+// new Object[]{pointerId, action, event.getX(), event.getY(), event.getPointerCount()});
TouchEvent touchEvent;
switch (action) {
case MotionEvent.ACTION_HOVER_ENTER:
- jmeX = androidInput.getJmeX(event.getX(pointerIndex));
- jmeY = androidInput.invertY(androidInput.getJmeY(event.getY(pointerIndex)));
- touchEvent = androidInput.getFreeTouchEvent();
+ jmeX = getJmeX(event.getX(pointerIndex));
+ jmeY = invertY(getJmeY(event.getY(pointerIndex)));
+ touchEvent = getFreeTouchEvent();
touchEvent.set(TouchEvent.Type.HOVER_START, jmeX, jmeY, 0, 0);
touchEvent.setPointerId(pointerId);
touchEvent.setTime(event.getEventTime());
touchEvent.setPressure(event.getPressure(pointerIndex));
-
+
lastPos = new Vector2f(jmeX, jmeY);
lastHoverPositions.put(pointerId, lastPos);
-
- processEvent(touchEvent);
+
+ addEvent(touchEvent);
consumed = true;
break;
case MotionEvent.ACTION_HOVER_MOVE:
// Convert all pointers into events
for (int p = 0; p < event.getPointerCount(); p++) {
- jmeX = androidInput.getJmeX(event.getX(p));
- jmeY = androidInput.invertY(androidInput.getJmeY(event.getY(p)));
+ jmeX = getJmeX(event.getX(p));
+ jmeY = invertY(getJmeY(event.getY(p)));
lastPos = lastHoverPositions.get(event.getPointerId(p));
if (lastPos == null) {
lastPos = new Vector2f(jmeX, jmeY);
@@ -115,38 +98,39 @@ public class AndroidTouchHandler14 extends AndroidTouchHandler implements
float dX = jmeX - lastPos.x;
float dY = jmeY - lastPos.y;
if (dX != 0 || dY != 0) {
- touchEvent = androidInput.getFreeTouchEvent();
+ touchEvent = getFreeTouchEvent();
touchEvent.set(TouchEvent.Type.HOVER_MOVE, jmeX, jmeY, dX, dY);
touchEvent.setPointerId(event.getPointerId(p));
touchEvent.setTime(event.getEventTime());
touchEvent.setPressure(event.getPressure(p));
lastPos.set(jmeX, jmeY);
- processEvent(touchEvent);
+ addEvent(touchEvent);
}
}
consumed = true;
break;
case MotionEvent.ACTION_HOVER_EXIT:
- jmeX = androidInput.getJmeX(event.getX(pointerIndex));
- jmeY = androidInput.invertY(androidInput.getJmeY(event.getY(pointerIndex)));
- touchEvent = androidInput.getFreeTouchEvent();
+ jmeX = getJmeX(event.getX(pointerIndex));
+ jmeY = invertY(getJmeY(event.getY(pointerIndex)));
+ touchEvent = getFreeTouchEvent();
touchEvent.set(TouchEvent.Type.HOVER_END, jmeX, jmeY, 0, 0);
touchEvent.setPointerId(pointerId);
touchEvent.setTime(event.getEventTime());
touchEvent.setPressure(event.getPressure(pointerIndex));
lastHoverPositions.remove(pointerId);
- processEvent(touchEvent);
+ addEvent(touchEvent);
consumed = true;
break;
default:
consumed = false;
break;
}
-
+
return consumed;
+
}
-
+
}
diff --git a/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java b/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java
index 5ef866188..9472bff0b 100644
--- a/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java
+++ b/jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java
@@ -47,7 +47,7 @@ import android.widget.EditText;
import android.widget.FrameLayout;
import com.jme3.input.*;
import com.jme3.input.android.AndroidInputHandler;
-import com.jme3.input.android.AndroidJoyInputHandler;
+import com.jme3.input.android.AndroidInputHandler14;
import com.jme3.input.controls.SoftTextDialogInputListener;
import com.jme3.input.dummy.DummyKeyInput;
import com.jme3.input.dummy.DummyMouseInput;
@@ -75,7 +75,6 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
protected SystemListener listener;
protected boolean autoFlush = true;
protected AndroidInputHandler androidInput;
- protected AndroidJoyInputHandler androidJoyInput = null;
protected long minFrameDuration = 0; // No FPS cap
protected long lastUpdateTime = 0;
@@ -111,18 +110,17 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
// Start to set up the view
GLSurfaceView view = new GLSurfaceView(context);
+ logger.log(Level.INFO, "Android Build Version: {0}", Build.VERSION.SDK_INT);
if (androidInput == null) {
- androidInput = new AndroidInputHandler();
+ if (Build.VERSION.SDK_INT >= 14) {
+ androidInput = new AndroidInputHandler14();
+ } else if (Build.VERSION.SDK_INT >= 9){
+ androidInput = new AndroidInputHandler();
+ }
}
androidInput.setView(view);
androidInput.loadSettings(settings);
- if (androidJoyInput == null) {
- androidJoyInput = new AndroidJoyInputHandler();
- }
- androidJoyInput.setView(view);
- androidJoyInput.loadSettings(settings);
-
// setEGLContextClientVersion must be set before calling setRenderer
// this means it cannot be set in AndroidConfigChooser (too late)
view.setEGLContextClientVersion(2);
@@ -235,9 +233,6 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
if (androidInput != null) {
androidInput.loadSettings(settings);
}
- if (androidJoyInput != null) {
- androidJoyInput.loadSettings(settings);
- }
if (settings.getFrameRate() > 0) {
minFrameDuration = (long)(1000d / (double)settings.getFrameRate()); // ms
@@ -274,12 +269,12 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
@Override
public JoyInput getJoyInput() {
- return androidJoyInput;
+ return androidInput.getJoyInput();
}
@Override
public TouchInput getTouchInput() {
- return androidInput;
+ return androidInput.getTouchInput();
}
@Override