Rework of Android input system to support future expansion and gamepad support.
Gamepad support is still a work in progress, but functions.
This commit is contained in:
parent
60ed6b7620
commit
61ba11d872
@ -35,314 +35,240 @@ package com.jme3.input.android;
|
|||||||
import android.view.GestureDetector;
|
import android.view.GestureDetector;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.ScaleGestureDetector;
|
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 com.jme3.input.event.TouchEvent;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AndroidGestureHandler uses Gesture type listeners to create jME TouchEvents
|
* 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
|
* on Android rev 9 (Android 2.3). Extend this class to add functionality
|
||||||
* added by Android after rev 9.
|
* added by Android after rev 9.
|
||||||
*
|
*
|
||||||
* @author iwgeric
|
* @author iwgeric
|
||||||
*/
|
*/
|
||||||
public class AndroidGestureHandler implements
|
public class AndroidGestureProcessor implements
|
||||||
GestureDetector.OnGestureListener,
|
GestureDetector.OnGestureListener,
|
||||||
GestureDetector.OnDoubleTapListener,
|
GestureDetector.OnDoubleTapListener,
|
||||||
ScaleGestureDetector.OnScaleGestureListener {
|
ScaleGestureDetector.OnScaleGestureListener {
|
||||||
private static final Logger logger = Logger.getLogger(AndroidGestureHandler.class.getName());
|
private static final Logger logger = Logger.getLogger(AndroidGestureProcessor.class.getName());
|
||||||
private AndroidInputHandler androidInput;
|
|
||||||
private GestureDetector gestureDetector;
|
private AndroidTouchInput touchInput;
|
||||||
private ScaleGestureDetector scaleDetector;
|
|
||||||
float gestureDownX = -1f;
|
float gestureDownX = -1f;
|
||||||
float gestureDownY = -1f;
|
float gestureDownY = -1f;
|
||||||
float scaleStartX = -1f;
|
float scaleStartX = -1f;
|
||||||
float scaleStartY = -1f;
|
float scaleStartY = -1f;
|
||||||
|
|
||||||
public AndroidGestureHandler(AndroidInputHandler androidInput) {
|
public AndroidGestureProcessor(AndroidTouchInput touchInput) {
|
||||||
this.androidInput = androidInput;
|
this.touchInput = touchInput;
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
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 */
|
/* Events from onGestureListener */
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean onDown(MotionEvent event) {
|
public boolean onDown(MotionEvent event) {
|
||||||
// start of all GestureListeners. Not really a gesture by itself
|
// start of all GestureListeners. Not really a gesture by itself
|
||||||
// so we don't create an event.
|
// so we don't create an event.
|
||||||
// However, reset the scaleInProgress here since this is the beginning
|
// However, reset the scaleInProgress here since this is the beginning
|
||||||
// of a series of gesture events.
|
// of a series of gesture events.
|
||||||
// logger.log(Level.INFO, "onDown pointerId: {0}, action: {1}, x: {2}, y: {3}",
|
// logger.log(Level.INFO, "onDown pointerId: {0}, action: {1}, x: {2}, y: {3}",
|
||||||
// new Object[]{getPointerId(event), getAction(event), event.getX(), event.getY()});
|
// new Object[]{touchInput.getPointerId(event), touchInput.getAction(event), event.getX(), event.getY()});
|
||||||
gestureDownX = androidInput.getJmeX(event.getX());
|
gestureDownX = touchInput.getJmeX(event.getX());
|
||||||
gestureDownY = androidInput.invertY(androidInput.getJmeY(event.getY()));
|
gestureDownY = touchInput.invertY(touchInput.getJmeY(event.getY()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean onSingleTapUp(MotionEvent event) {
|
public boolean onSingleTapUp(MotionEvent event) {
|
||||||
// Up of single tap. May be followed by a double tap later.
|
// Up of single tap. May be followed by a double tap later.
|
||||||
// use onSingleTapConfirmed instead.
|
// use onSingleTapConfirmed instead.
|
||||||
// logger.log(Level.INFO, "onSingleTapUp pointerId: {0}, action: {1}, x: {2}, y: {3}",
|
// logger.log(Level.INFO, "onSingleTapUp pointerId: {0}, action: {1}, x: {2}, y: {3}",
|
||||||
// new Object[]{getPointerId(event), getAction(event), event.getX(), event.getY()});
|
// new Object[]{touchInput.getPointerId(event), touchInput.getAction(event), event.getX(), event.getY()});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onShowPress(MotionEvent event) {
|
public void onShowPress(MotionEvent event) {
|
||||||
// logger.log(Level.INFO, "onShowPress pointerId: {0}, action: {1}, x: {2}, y: {3}",
|
// logger.log(Level.INFO, "onShowPress pointerId: {0}, action: {1}, x: {2}, y: {3}",
|
||||||
// new Object[]{getPointerId(event), getAction(event), event.getX(), event.getY()});
|
// new Object[]{touchInput.getPointerId(event), touchInput.getAction(event), event.getX(), event.getY()});
|
||||||
float jmeX = androidInput.getJmeX(event.getX());
|
float jmeX = touchInput.getJmeX(event.getX());
|
||||||
float jmeY = androidInput.invertY(androidInput.getJmeY(event.getY()));
|
float jmeY = touchInput.invertY(touchInput.getJmeY(event.getY()));
|
||||||
TouchEvent touchEvent = androidInput.getFreeTouchEvent();
|
TouchEvent touchEvent = touchInput.getFreeTouchEvent();
|
||||||
touchEvent.set(TouchEvent.Type.SHOWPRESS, jmeX, jmeY, 0, 0);
|
touchEvent.set(TouchEvent.Type.SHOWPRESS, jmeX, jmeY, 0, 0);
|
||||||
touchEvent.setPointerId(getPointerId(event));
|
touchEvent.setPointerId(touchInput.getPointerId(event));
|
||||||
touchEvent.setTime(event.getEventTime());
|
touchEvent.setTime(event.getEventTime());
|
||||||
touchEvent.setPressure(event.getPressure());
|
touchEvent.setPressure(event.getPressure());
|
||||||
processEvent(touchEvent);
|
touchInput.addEvent(touchEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onLongPress(MotionEvent event) {
|
public void onLongPress(MotionEvent event) {
|
||||||
// logger.log(Level.INFO, "onLongPress pointerId: {0}, action: {1}, x: {2}, y: {3}",
|
// logger.log(Level.INFO, "onLongPress pointerId: {0}, action: {1}, x: {2}, y: {3}",
|
||||||
// new Object[]{getPointerId(event), getAction(event), event.getX(), event.getY()});
|
// new Object[]{touchInput.getPointerId(event), touchInput.getAction(event), event.getX(), event.getY()});
|
||||||
float jmeX = androidInput.getJmeX(event.getX());
|
float jmeX = touchInput.getJmeX(event.getX());
|
||||||
float jmeY = androidInput.invertY(androidInput.getJmeY(event.getY()));
|
float jmeY = touchInput.invertY(touchInput.getJmeY(event.getY()));
|
||||||
TouchEvent touchEvent = androidInput.getFreeTouchEvent();
|
TouchEvent touchEvent = touchInput.getFreeTouchEvent();
|
||||||
touchEvent.set(TouchEvent.Type.LONGPRESSED, jmeX, jmeY, 0, 0);
|
touchEvent.set(TouchEvent.Type.LONGPRESSED, jmeX, jmeY, 0, 0);
|
||||||
touchEvent.setPointerId(getPointerId(event));
|
touchEvent.setPointerId(touchInput.getPointerId(event));
|
||||||
touchEvent.setTime(event.getEventTime());
|
touchEvent.setTime(event.getEventTime());
|
||||||
touchEvent.setPressure(event.getPressure());
|
touchEvent.setPressure(event.getPressure());
|
||||||
processEvent(touchEvent);
|
touchInput.addEvent(touchEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean onScroll(MotionEvent startEvent, MotionEvent endEvent, float distX, float distY) {
|
public boolean onScroll(MotionEvent startEvent, MotionEvent endEvent, float distX, float distY) {
|
||||||
// if not scaleInProgess, send scroll events. This is to avoid sending
|
// 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.
|
// scroll events when one of the fingers is lifted just before the other one.
|
||||||
// Avoids sending the scroll for that brief period of time.
|
// 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.
|
// 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
|
// 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.
|
// for the fact that jME has y=0 at bottom where Android has y=0 at top.
|
||||||
// if (!scaleInProgress) {
|
if (!touchInput.getScaleDetector().isInProgress()) {
|
||||||
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}",
|
||||||
// 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});
|
||||||
// new Object[]{getPointerId(startEvent), getAction(startEvent), startEvent.getX(), startEvent.getY(), getAction(endEvent), endEvent.getX(), endEvent.getY(), distX, distY});
|
|
||||||
|
|
||||||
float jmeX = androidInput.getJmeX(endEvent.getX());
|
float jmeX = touchInput.getJmeX(endEvent.getX());
|
||||||
float jmeY = androidInput.invertY(androidInput.getJmeY(endEvent.getY()));
|
float jmeY = touchInput.invertY(touchInput.getJmeY(endEvent.getY()));
|
||||||
TouchEvent touchEvent = androidInput.getFreeTouchEvent();
|
TouchEvent touchEvent = touchInput.getFreeTouchEvent();
|
||||||
touchEvent.set(TouchEvent.Type.SCROLL, jmeX, jmeY, androidInput.getJmeX(-distX), androidInput.getJmeY(distY));
|
touchEvent.set(TouchEvent.Type.SCROLL, jmeX, jmeY, touchInput.getJmeX(-distX), touchInput.getJmeY(distY));
|
||||||
touchEvent.setPointerId(getPointerId(endEvent));
|
touchEvent.setPointerId(touchInput.getPointerId(endEvent));
|
||||||
touchEvent.setTime(endEvent.getEventTime());
|
touchEvent.setTime(endEvent.getEventTime());
|
||||||
touchEvent.setPressure(endEvent.getPressure());
|
touchEvent.setPressure(endEvent.getPressure());
|
||||||
processEvent(touchEvent);
|
touchInput.addEvent(touchEvent);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean onFling(MotionEvent startEvent, MotionEvent endEvent, float velocityX, float velocityY) {
|
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 happens only once at the end of the gesture (all fingers up).
|
||||||
// Fling returns the velocity of the finger movement in pixels/sec.
|
// Fling returns the velocity of the finger movement in pixels/sec.
|
||||||
// Therefore, the dX and dY values are actually velocity instead of distance values
|
// 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.
|
// 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());
|
// logger.log(Level.INFO, "onFling pointerId: {0}, startAction: {1}, startX: {2}, startY: {3}, endAction: {4}, endX: {5}, endY: {6}, velocityX: {7}, velocityY: {8}",
|
||||||
float jmeY = androidInput.invertY(androidInput.getJmeY(startEvent.getY()));
|
// new Object[]{touchInput.getPointerId(startEvent), touchInput.getAction(startEvent), startEvent.getX(), startEvent.getY(), touchInput.getAction(endEvent), endEvent.getX(), endEvent.getY(), velocityX, velocityY});
|
||||||
TouchEvent touchEvent = androidInput.getFreeTouchEvent();
|
|
||||||
|
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.set(TouchEvent.Type.FLING, jmeX, jmeY, velocityX, velocityY);
|
||||||
touchEvent.setPointerId(getPointerId(endEvent));
|
touchEvent.setPointerId(touchInput.getPointerId(endEvent));
|
||||||
touchEvent.setTime(endEvent.getEventTime());
|
touchEvent.setTime(endEvent.getEventTime());
|
||||||
touchEvent.setPressure(endEvent.getPressure());
|
touchEvent.setPressure(endEvent.getPressure());
|
||||||
processEvent(touchEvent);
|
touchInput.addEvent(touchEvent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Events from onDoubleTapListener */
|
/* Events from onDoubleTapListener */
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean onSingleTapConfirmed(MotionEvent event) {
|
public boolean onSingleTapConfirmed(MotionEvent event) {
|
||||||
// Up of single tap when no double tap followed.
|
// Up of single tap when no double tap followed.
|
||||||
// logger.log(Level.INFO, "onSingleTapConfirmed pointerId: {0}, action: {1}, x: {2}, y: {3}",
|
// logger.log(Level.INFO, "onSingleTapConfirmed pointerId: {0}, action: {1}, x: {2}, y: {3}",
|
||||||
// new Object[]{getPointerId(event), getAction(event), event.getX(), event.getY()});
|
// new Object[]{touchInput.getPointerId(event), touchInput.getAction(event), event.getX(), event.getY()});
|
||||||
float jmeX = androidInput.getJmeX(event.getX());
|
float jmeX = touchInput.getJmeX(event.getX());
|
||||||
float jmeY = androidInput.invertY(androidInput.getJmeY(event.getY()));
|
float jmeY = touchInput.invertY(touchInput.getJmeY(event.getY()));
|
||||||
TouchEvent touchEvent = androidInput.getFreeTouchEvent();
|
TouchEvent touchEvent = touchInput.getFreeTouchEvent();
|
||||||
touchEvent.set(TouchEvent.Type.TAP, jmeX, jmeY, 0, 0);
|
touchEvent.set(TouchEvent.Type.TAP, jmeX, jmeY, 0, 0);
|
||||||
touchEvent.setPointerId(getPointerId(event));
|
touchEvent.setPointerId(touchInput.getPointerId(event));
|
||||||
touchEvent.setTime(event.getEventTime());
|
touchEvent.setTime(event.getEventTime());
|
||||||
touchEvent.setPressure(event.getPressure());
|
touchEvent.setPressure(event.getPressure());
|
||||||
processEvent(touchEvent);
|
touchInput.addEvent(touchEvent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean onDoubleTap(MotionEvent event) {
|
public boolean onDoubleTap(MotionEvent event) {
|
||||||
//The down motion event of the first tap of the double-tap
|
//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
|
// DoubleTapEvent with a check for the UP action
|
||||||
// logger.log(Level.INFO, "onDoubleTap pointerId: {0}, action: {1}, x: {2}, y: {3}",
|
// logger.log(Level.INFO, "onDoubleTap pointerId: {0}, action: {1}, x: {2}, y: {3}",
|
||||||
// new Object[]{getPointerId(event), getAction(event), event.getX(), event.getY()});
|
// new Object[]{touchInput.getPointerId(event), touchInput.getAction(event), event.getX(), event.getY()});
|
||||||
float jmeX = androidInput.getJmeX(event.getX());
|
float jmeX = touchInput.getJmeX(event.getX());
|
||||||
float jmeY = androidInput.invertY(androidInput.getJmeY(event.getY()));
|
float jmeY = touchInput.invertY(touchInput.getJmeY(event.getY()));
|
||||||
TouchEvent touchEvent = androidInput.getFreeTouchEvent();
|
TouchEvent touchEvent = touchInput.getFreeTouchEvent();
|
||||||
touchEvent.set(TouchEvent.Type.DOUBLETAP, jmeX, jmeY, 0, 0);
|
touchEvent.set(TouchEvent.Type.DOUBLETAP, jmeX, jmeY, 0, 0);
|
||||||
touchEvent.setPointerId(getPointerId(event));
|
touchEvent.setPointerId(touchInput.getPointerId(event));
|
||||||
touchEvent.setTime(event.getEventTime());
|
touchEvent.setTime(event.getEventTime());
|
||||||
touchEvent.setPressure(event.getPressure());
|
touchEvent.setPressure(event.getPressure());
|
||||||
processEvent(touchEvent);
|
touchInput.addEvent(touchEvent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean onDoubleTapEvent(MotionEvent event) {
|
public boolean onDoubleTapEvent(MotionEvent event) {
|
||||||
//Notified when an event within a double-tap gesture occurs, including the down, move(s), and up events.
|
//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
|
// 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}",
|
// logger.log(Level.INFO, "onDoubleTapEvent pointerId: {0}, action: {1}, x: {2}, y: {3}",
|
||||||
// new Object[]{getPointerId(event), getAction(event), event.getX(), event.getY()});
|
// new Object[]{touchInput.getPointerId(event), touchInput.getAction(event), event.getX(), event.getY()});
|
||||||
// if (getAction(event) == MotionEvent.ACTION_UP) {
|
if (touchInput.getAction(event) == MotionEvent.ACTION_UP) {
|
||||||
// TouchEvent touchEvent = touchEventPool.getNextFreeEvent();
|
TouchEvent touchEvent = touchInput.getFreeTouchEvent();
|
||||||
// touchEvent.set(TouchEvent.Type.DOUBLETAP, event.getX(), androidInput.invertY(event.getY()), 0, 0);
|
touchEvent.set(TouchEvent.Type.DOUBLETAP, event.getX(), touchInput.invertY(event.getY()), 0, 0);
|
||||||
// touchEvent.setPointerId(getPointerId(event));
|
touchEvent.setPointerId(touchInput.getPointerId(event));
|
||||||
// touchEvent.setTime(event.getEventTime());
|
touchEvent.setTime(event.getEventTime());
|
||||||
// touchEvent.setPressure(event.getPressure());
|
touchEvent.setPressure(event.getPressure());
|
||||||
// processEvent(touchEvent);
|
touchInput.addEvent(touchEvent);
|
||||||
// }
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Events from ScaleGestureDetector */
|
/* Events from ScaleGestureDetector */
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
|
public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
|
||||||
// Scale uses a focusX and focusY instead of x and y. Focus is the middle
|
// 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
|
// 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.
|
// 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
|
// return true or all gestures for this beginning event will be discarded
|
||||||
logger.log(Level.INFO, "onScaleBegin");
|
// logger.log(Level.INFO, "onScaleBegin");
|
||||||
scaleStartX = gestureDownX;
|
scaleStartX = gestureDownX;
|
||||||
scaleStartY = gestureDownY;
|
scaleStartY = gestureDownY;
|
||||||
TouchEvent touchEvent = androidInput.getFreeTouchEvent();
|
TouchEvent touchEvent = touchInput.getFreeTouchEvent();
|
||||||
touchEvent.set(TouchEvent.Type.SCALE_START, scaleStartX, scaleStartY, 0f, 0f);
|
touchEvent.set(TouchEvent.Type.SCALE_START, scaleStartX, scaleStartY, 0f, 0f);
|
||||||
touchEvent.setPointerId(0);
|
touchEvent.setPointerId(0);
|
||||||
touchEvent.setTime(scaleGestureDetector.getEventTime());
|
touchEvent.setTime(scaleGestureDetector.getEventTime());
|
||||||
touchEvent.setScaleSpan(scaleGestureDetector.getCurrentSpan());
|
touchEvent.setScaleSpan(scaleGestureDetector.getCurrentSpan());
|
||||||
touchEvent.setDeltaScaleSpan(0f);
|
touchEvent.setDeltaScaleSpan(0f);
|
||||||
touchEvent.setScaleFactor(scaleGestureDetector.getScaleFactor());
|
touchEvent.setScaleFactor(scaleGestureDetector.getScaleFactor());
|
||||||
touchEvent.setScaleSpanInProgress(scaleDetector.isInProgress());
|
touchEvent.setScaleSpanInProgress(touchInput.getScaleDetector().isInProgress());
|
||||||
processEvent(touchEvent);
|
touchInput.addEvent(touchEvent);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
|
public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
|
||||||
// return true or all gestures for this event will be accumulated
|
// return true or all gestures for this event will be accumulated
|
||||||
logger.log(Level.INFO, "onScale");
|
// logger.log(Level.INFO, "onScale");
|
||||||
scaleStartX = gestureDownX;
|
scaleStartX = gestureDownX;
|
||||||
scaleStartY = gestureDownY;
|
scaleStartY = gestureDownY;
|
||||||
TouchEvent touchEvent = androidInput.getFreeTouchEvent();
|
TouchEvent touchEvent = touchInput.getFreeTouchEvent();
|
||||||
touchEvent.set(TouchEvent.Type.SCALE_MOVE, scaleStartX, scaleStartY, 0f, 0f);
|
touchEvent.set(TouchEvent.Type.SCALE_MOVE, scaleStartX, scaleStartY, 0f, 0f);
|
||||||
touchEvent.setPointerId(0);
|
touchEvent.setPointerId(0);
|
||||||
touchEvent.setTime(scaleGestureDetector.getEventTime());
|
touchEvent.setTime(scaleGestureDetector.getEventTime());
|
||||||
touchEvent.setScaleSpan(scaleGestureDetector.getCurrentSpan());
|
touchEvent.setScaleSpan(scaleGestureDetector.getCurrentSpan());
|
||||||
touchEvent.setDeltaScaleSpan(scaleGestureDetector.getCurrentSpan() - scaleGestureDetector.getPreviousSpan());
|
touchEvent.setDeltaScaleSpan(scaleGestureDetector.getCurrentSpan() - scaleGestureDetector.getPreviousSpan());
|
||||||
touchEvent.setScaleFactor(scaleGestureDetector.getScaleFactor());
|
touchEvent.setScaleFactor(scaleGestureDetector.getScaleFactor());
|
||||||
touchEvent.setScaleSpanInProgress(scaleDetector.isInProgress());
|
touchEvent.setScaleSpanInProgress(touchInput.getScaleDetector().isInProgress());
|
||||||
processEvent(touchEvent);
|
touchInput.addEvent(touchEvent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {
|
public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {
|
||||||
logger.log(Level.INFO, "onScaleEnd");
|
// logger.log(Level.INFO, "onScaleEnd");
|
||||||
scaleStartX = gestureDownX;
|
scaleStartX = gestureDownX;
|
||||||
scaleStartY = gestureDownY;
|
scaleStartY = gestureDownY;
|
||||||
TouchEvent touchEvent = androidInput.getFreeTouchEvent();
|
TouchEvent touchEvent = touchInput.getFreeTouchEvent();
|
||||||
touchEvent.set(TouchEvent.Type.SCALE_END, scaleStartX, scaleStartY, 0f, 0f);
|
touchEvent.set(TouchEvent.Type.SCALE_END, scaleStartX, scaleStartY, 0f, 0f);
|
||||||
touchEvent.setPointerId(0);
|
touchEvent.setPointerId(0);
|
||||||
touchEvent.setTime(scaleGestureDetector.getEventTime());
|
touchEvent.setTime(scaleGestureDetector.getEventTime());
|
||||||
touchEvent.setScaleSpan(scaleGestureDetector.getCurrentSpan());
|
touchEvent.setScaleSpan(scaleGestureDetector.getCurrentSpan());
|
||||||
touchEvent.setDeltaScaleSpan(scaleGestureDetector.getCurrentSpan() - scaleGestureDetector.getPreviousSpan());
|
touchEvent.setDeltaScaleSpan(scaleGestureDetector.getCurrentSpan() - scaleGestureDetector.getPreviousSpan());
|
||||||
touchEvent.setScaleFactor(scaleGestureDetector.getScaleFactor());
|
touchEvent.setScaleFactor(scaleGestureDetector.getScaleFactor());
|
||||||
touchEvent.setScaleSpanInProgress(scaleDetector.isInProgress());
|
touchEvent.setScaleSpanInProgress(touchInput.getScaleDetector().isInProgress());
|
||||||
processEvent(touchEvent);
|
touchInput.addEvent(touchEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <code>AndroidInput</code> 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<TouchEvent> eventQueue = new RingBuffer<TouchEvent>(MAX_EVENTS);
|
|
||||||
final private RingBuffer<TouchEvent> eventPoolUnConsumed = new RingBuffer<TouchEvent>(MAX_EVENTS);
|
|
||||||
final private RingBuffer<TouchEvent> eventPool = new RingBuffer<TouchEvent>(MAX_EVENTS);
|
|
||||||
final private HashMap<Integer, Vector2f> lastPositions = new HashMap<Integer, Vector2f>();
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -33,231 +33,206 @@
|
|||||||
package com.jme3.input.android;
|
package com.jme3.input.android;
|
||||||
|
|
||||||
import android.opengl.GLSurfaceView;
|
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 android.view.View;
|
||||||
import com.jme3.input.RawInputListener;
|
import com.jme3.input.JoyInput;
|
||||||
import com.jme3.input.TouchInput;
|
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 com.jme3.system.AppSettings;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>AndroidInput</code> is the main class that connects the Android system
|
* <code>AndroidInput</code> is the main class that connects the Android system
|
||||||
* inputs to jME. It serves as the manager that gathers inputs from the various
|
* inputs to jME. It receives the inputs from the Android View and passes them
|
||||||
* Android input methods and provides them to jME's <code>InputManager</code>.
|
* to the appropriate classes based on the source of the input.</br>
|
||||||
|
* This class is to be extended when new functionality is released in Android.
|
||||||
*
|
*
|
||||||
* @author iwgeric
|
* @author iwgeric
|
||||||
*/
|
*/
|
||||||
public class AndroidInputHandler implements TouchInput {
|
public class AndroidInputHandler implements View.OnTouchListener,
|
||||||
|
View.OnKeyListener {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(AndroidInputHandler.class.getName());
|
private static final Logger logger = Logger.getLogger(AndroidInputHandler.class.getName());
|
||||||
|
|
||||||
// Custom settings
|
protected GLSurfaceView view;
|
||||||
private boolean mouseEventsEnabled = true;
|
protected AndroidTouchInput touchInput;
|
||||||
private boolean mouseEventsInvertX = false;
|
protected AndroidJoyInput joyInput;
|
||||||
private boolean mouseEventsInvertY = false;
|
|
||||||
private boolean keyboardEventsEnabled = false;
|
|
||||||
private boolean dontSendHistory = false;
|
|
||||||
|
|
||||||
|
|
||||||
// Internal
|
|
||||||
private GLSurfaceView view;
|
|
||||||
private AndroidTouchHandler touchHandler;
|
|
||||||
private AndroidKeyHandler keyHandler;
|
|
||||||
private AndroidGestureHandler gestureHandler;
|
|
||||||
private boolean initialized = false;
|
|
||||||
private RawInputListener listener = null;
|
|
||||||
private ConcurrentLinkedQueue<InputEvent> inputEventQueue = new ConcurrentLinkedQueue<InputEvent>();
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
public AndroidInputHandler() {
|
public AndroidInputHandler() {
|
||||||
int buildVersion = Build.VERSION.SDK_INT;
|
touchInput = new AndroidTouchInput(this);
|
||||||
logger.log(Level.INFO, "Android Build Version: {0}", buildVersion);
|
joyInput = new AndroidJoyInput(this);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setView(View view) {
|
public void setView(View view) {
|
||||||
if (touchHandler != null) {
|
if (this.view != null && view != null && this.view.equals(view)) {
|
||||||
touchHandler.setView(view);
|
return;
|
||||||
}
|
}
|
||||||
if (keyHandler != null) {
|
|
||||||
keyHandler.setView(view);
|
if (this.view != null) {
|
||||||
}
|
removeListeners(this.view);
|
||||||
if (gestureHandler != null) {
|
|
||||||
gestureHandler.setView(view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.view = (GLSurfaceView)view;
|
this.view = (GLSurfaceView)view;
|
||||||
|
|
||||||
|
if (this.view != null) {
|
||||||
|
addListeners(this.view);
|
||||||
|
}
|
||||||
|
|
||||||
|
joyInput.setView((GLSurfaceView)view);
|
||||||
}
|
}
|
||||||
|
|
||||||
public View getView() {
|
public View getView() {
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float invertX(float origX) {
|
protected void removeListeners(GLSurfaceView view) {
|
||||||
return getJmeX(view.getWidth()) - origX;
|
view.setOnTouchListener(null);
|
||||||
|
view.setOnKeyListener(null);
|
||||||
|
touchInput.setGestureDetector(null);
|
||||||
|
touchInput.setScaleDetector(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float invertY(float origY) {
|
protected void addListeners(GLSurfaceView view) {
|
||||||
return getJmeY(view.getHeight()) - origY;
|
view.setOnTouchListener(this);
|
||||||
}
|
view.setOnKeyListener(this);
|
||||||
|
AndroidGestureProcessor gestureHandler = new AndroidGestureProcessor(touchInput);
|
||||||
public float getJmeX(float origX) {
|
touchInput.setGestureDetector(new GestureDetector(
|
||||||
return origX * scaleX;
|
view.getContext(), gestureHandler));
|
||||||
}
|
touchInput.setScaleDetector(new ScaleGestureDetector(
|
||||||
|
view.getContext(), gestureHandler));
|
||||||
public float getJmeY(float origY) {
|
|
||||||
return origY * scaleY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadSettings(AppSettings settings) {
|
public void loadSettings(AppSettings settings) {
|
||||||
keyboardEventsEnabled = settings.isEmulateKeyboard();
|
touchInput.loadSettings(settings);
|
||||||
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});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
public TouchInput getTouchInput() {
|
||||||
// JME3 Input interface
|
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.
|
||||||
|
* </br>
|
||||||
|
* 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.</br>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public boolean onTouch(View view, MotionEvent event) {
|
||||||
touchEventPool.initialize();
|
if (view != getView()) {
|
||||||
if (touchHandler != null) {
|
return false;
|
||||||
touchHandler.initialize();
|
|
||||||
}
|
|
||||||
if (keyHandler != null) {
|
|
||||||
keyHandler.initialize();
|
|
||||||
}
|
|
||||||
if (gestureHandler != null) {
|
|
||||||
gestureHandler.initialize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initialized = true;
|
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 = touchInput.onTouch(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public boolean onKey(View view, int keyCode, KeyEvent event) {
|
||||||
initialized = false;
|
if (view != getView()) {
|
||||||
|
return false;
|
||||||
touchEventPool.destroy();
|
|
||||||
if (touchHandler != null) {
|
|
||||||
touchHandler.destroy();
|
|
||||||
}
|
|
||||||
if (keyHandler != null) {
|
|
||||||
keyHandler.destroy();
|
|
||||||
}
|
|
||||||
if (gestureHandler != null) {
|
|
||||||
gestureHandler.destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setView(null);
|
boolean consumed = false;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
int source = event.getSource();
|
||||||
public boolean isInitialized() {
|
// logger.log(Level.INFO, "onKey source: {0}", source);
|
||||||
return initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
boolean isTouch =
|
||||||
public void setInputListener(RawInputListener listener) {
|
((source & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) ||
|
||||||
this.listener = listener;
|
((source & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD);
|
||||||
}
|
// logger.log(Level.INFO, "onKey source: {0}, isTouch: {1}",
|
||||||
|
// new Object[]{source, isTouch});
|
||||||
|
|
||||||
@Override
|
if (touchInput != null) {
|
||||||
public long getInputTimeNanos() {
|
consumed = touchInput.onKey(event);
|
||||||
return System.nanoTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------
|
return consumed;
|
||||||
|
|
||||||
public TouchEvent getFreeTouchEvent() {
|
|
||||||
return touchEventPool.getNextFreeEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addEvent(InputEvent event) {
|
|
||||||
inputEventQueue.add(event);
|
|
||||||
if (event instanceof TouchEvent) {
|
|
||||||
touchEventPool.storeEvent((TouchEvent)event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSimulateMouse(boolean simulate) {
|
|
||||||
this.mouseEventsEnabled = simulate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSimulateMouse() {
|
|
||||||
return mouseEventsEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMouseEventsInvertX() {
|
|
||||||
return mouseEventsInvertX;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMouseEventsInvertY() {
|
|
||||||
return mouseEventsInvertY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSimulateKeyboard(boolean simulate) {
|
|
||||||
this.keyboardEventsEnabled = simulate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSimulateKeyboard() {
|
|
||||||
return keyboardEventsEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOmitHistoricEvents(boolean dontSendHistory) {
|
|
||||||
this.dontSendHistory = dontSendHistory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>AndroidInputHandler14</code> extends <code>AndroidInputHandler</code> to
|
||||||
|
* add the onHover and onGenericMotion events that where added in Android rev 14 (Android 4.0).</br>
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -33,9 +33,7 @@ package com.jme3.input.android;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.opengl.GLSurfaceView;
|
import android.opengl.GLSurfaceView;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Vibrator;
|
import android.os.Vibrator;
|
||||||
import android.view.View;
|
|
||||||
import com.jme3.input.InputManager;
|
import com.jme3.input.InputManager;
|
||||||
import com.jme3.input.JoyInput;
|
import com.jme3.input.JoyInput;
|
||||||
import com.jme3.input.Joystick;
|
import com.jme3.input.Joystick;
|
||||||
@ -79,15 +77,15 @@ import java.util.logging.Logger;
|
|||||||
*
|
*
|
||||||
* @author iwgeric
|
* @author iwgeric
|
||||||
*/
|
*/
|
||||||
public class AndroidJoyInputHandler implements JoyInput {
|
public class AndroidJoyInput implements JoyInput {
|
||||||
private static final Logger logger = Logger.getLogger(AndroidJoyInputHandler.class.getName());
|
private static final Logger logger = Logger.getLogger(AndroidJoyInput.class.getName());
|
||||||
|
|
||||||
private List<Joystick> joystickList = new ArrayList<Joystick>();
|
protected AndroidInputHandler inputHandler;
|
||||||
|
protected List<Joystick> joystickList = new ArrayList<Joystick>();
|
||||||
// private boolean dontSendHistory = false;
|
// private boolean dontSendHistory = false;
|
||||||
|
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
private GLSurfaceView view;
|
|
||||||
private boolean initialized = false;
|
private boolean initialized = false;
|
||||||
private RawInputListener listener = null;
|
private RawInputListener listener = null;
|
||||||
private ConcurrentLinkedQueue<InputEvent> eventQueue = new ConcurrentLinkedQueue<InputEvent>();
|
private ConcurrentLinkedQueue<InputEvent> eventQueue = new ConcurrentLinkedQueue<InputEvent>();
|
||||||
@ -96,34 +94,29 @@ public class AndroidJoyInputHandler implements JoyInput {
|
|||||||
private boolean vibratorActive = false;
|
private boolean vibratorActive = false;
|
||||||
private long maxRumbleTime = 250; // 250ms
|
private long maxRumbleTime = 250; // 250ms
|
||||||
|
|
||||||
public AndroidJoyInputHandler() {
|
public AndroidJoyInput(AndroidInputHandler inputHandler) {
|
||||||
int buildVersion = Build.VERSION.SDK_INT;
|
this.inputHandler = inputHandler;
|
||||||
logger.log(Level.INFO, "Android Build Version: {0}", buildVersion);
|
|
||||||
// if (buildVersion >= 14) {
|
|
||||||
// touchHandler = new AndroidTouchHandler14(this);
|
|
||||||
// } else if (buildVersion >= 8){
|
|
||||||
// touchHandler = new AndroidTouchHandler(this);
|
|
||||||
// }
|
|
||||||
sensorJoyInput = new AndroidSensorJoyInput(this);
|
sensorJoyInput = new AndroidSensorJoyInput(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setView(GLSurfaceView view) {
|
public void setView(GLSurfaceView view) {
|
||||||
// if (touchHandler != null) {
|
if (view == null) {
|
||||||
// touchHandler.setView(view);
|
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) {
|
if (sensorJoyInput != null) {
|
||||||
sensorJoyInput.setView(view);
|
sensorJoyInput.setView(view);
|
||||||
}
|
}
|
||||||
this.view = (GLSurfaceView)view;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public View getView() {
|
|
||||||
return view;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadSettings(AppSettings settings) {
|
public void loadSettings(AppSettings settings) {
|
||||||
// sensorEventsEnabled = settings.useSensors();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addEvent(InputEvent event) {
|
public void addEvent(InputEvent event) {
|
||||||
@ -155,20 +148,8 @@ public class AndroidJoyInputHandler implements JoyInput {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
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;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,8 +192,8 @@ public class AndroidJoyInputHandler implements JoyInput {
|
|||||||
};
|
};
|
||||||
final int rumbleRepeatFrom = 0; // index into rumble pattern to repeat from
|
final int rumbleRepeatFrom = 0; // index into rumble pattern to repeat from
|
||||||
|
|
||||||
logger.log(Level.FINE, "Rumble amount: {0}, rumbleOnDur: {1}, rumbleOffDur: {2}",
|
// logger.log(Level.FINE, "Rumble amount: {0}, rumbleOnDur: {1}, rumbleOffDur: {2}",
|
||||||
new Object[]{amount, rumbleOnDur, rumbleOffDur});
|
// new Object[]{amount, rumbleOnDur, rumbleOffDur});
|
||||||
|
|
||||||
if (rumbleOnDur > 0) {
|
if (rumbleOnDur > 0) {
|
||||||
vibrator.vibrate(rumblePattern, rumbleRepeatFrom);
|
vibrator.vibrate(rumblePattern, rumbleRepeatFrom);
|
||||||
@ -226,9 +207,8 @@ public class AndroidJoyInputHandler implements JoyInput {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Joystick[] loadJoysticks(InputManager inputManager) {
|
public Joystick[] loadJoysticks(InputManager inputManager) {
|
||||||
|
logger.log(Level.INFO, "loading joysticks for {0}", this.getClass().getName());
|
||||||
joystickList.add(sensorJoyInput.loadJoystick(joystickList.size(), inputManager));
|
joystickList.add(sensorJoyInput.loadJoystick(joystickList.size(), inputManager));
|
||||||
|
|
||||||
|
|
||||||
return joystickList.toArray( new Joystick[joystickList.size()] );
|
return joystickList.toArray( new Joystick[joystickList.size()] );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,6 +232,4 @@ public class AndroidJoyInputHandler implements JoyInput {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>AndroidJoyInput14</code> extends <code>AndroidJoyInput</code>
|
||||||
|
* to include support for physical joysticks/gamepads.</br>
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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<Integer, AndroidJoystick> joystickIndex = new HashMap<Integer, AndroidJoystick>();
|
||||||
|
|
||||||
|
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<Joystick> loadJoysticks(int joyId, InputManager inputManager) {
|
||||||
|
logger.log(Level.INFO, "loading Joystick devices");
|
||||||
|
ArrayList<Joystick> joysticks = new ArrayList<Joystick>();
|
||||||
|
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<MotionRange> 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<Integer, JoystickAxis> axisIndex = new HashMap<Integer, JoystickAxis>();
|
||||||
|
private Map<Integer, JoystickButton> buttonIndex = new HashMap<Integer, JoystickButton>();
|
||||||
|
|
||||||
|
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<Integer> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -37,13 +37,14 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* AndroidKeyMapping is just a utility to convert the Android keyCodes into
|
* 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
|
* @author iwgeric
|
||||||
*/
|
*/
|
||||||
public class AndroidKeyMapping {
|
public class AndroidKeyMapping {
|
||||||
private static final Logger logger = Logger.getLogger(AndroidKeyMapping.class.getName());
|
private static final Logger logger = Logger.getLogger(AndroidKeyMapping.class.getName());
|
||||||
|
|
||||||
private static final int[] ANDROID_TO_JME = {
|
private static final int[] ANDROID_TO_JME = {
|
||||||
0x0, // unknown
|
0x0, // unknown
|
||||||
0x0, // key code soft left
|
0x0, // key code soft left
|
||||||
@ -141,9 +142,13 @@ public class AndroidKeyMapping {
|
|||||||
0x0,//media fastforward
|
0x0,//media fastforward
|
||||||
0x0,//mute
|
0x0,//mute
|
||||||
};
|
};
|
||||||
|
|
||||||
public static int getJmeKey(int androidKey) {
|
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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -75,15 +75,15 @@ import java.util.logging.Logger;
|
|||||||
public class AndroidSensorJoyInput implements SensorEventListener {
|
public class AndroidSensorJoyInput implements SensorEventListener {
|
||||||
private final static Logger logger = Logger.getLogger(AndroidSensorJoyInput.class.getName());
|
private final static Logger logger = Logger.getLogger(AndroidSensorJoyInput.class.getName());
|
||||||
|
|
||||||
private AndroidJoyInputHandler joyHandler;
|
private AndroidJoyInput joyInput;
|
||||||
private SensorManager sensorManager = null;
|
private SensorManager sensorManager = null;
|
||||||
private WindowManager windowManager = null;
|
private WindowManager windowManager = null;
|
||||||
private IntMap<SensorData> sensors = new IntMap<SensorData>();
|
private IntMap<SensorData> sensors = new IntMap<SensorData>();
|
||||||
private int lastRotation = 0;
|
private int lastRotation = 0;
|
||||||
private boolean loaded = false;
|
private boolean loaded = false;
|
||||||
|
|
||||||
public AndroidSensorJoyInput(AndroidJoyInputHandler joyHandler) {
|
public AndroidSensorJoyInput(AndroidJoyInput joyInput) {
|
||||||
this.joyHandler = joyHandler;
|
this.joyInput = joyInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,7 +96,7 @@ public class AndroidSensorJoyInput implements SensorEventListener {
|
|||||||
int sensorAccuracy = -1;
|
int sensorAccuracy = -1;
|
||||||
float[] lastValues;
|
float[] lastValues;
|
||||||
final Object valuesLock = new Object();
|
final Object valuesLock = new Object();
|
||||||
ArrayList<AndroidJoystickAxis> axes = new ArrayList<AndroidJoystickAxis>();
|
ArrayList<AndroidSensorJoystickAxis> axes = new ArrayList<AndroidSensorJoystickAxis>();
|
||||||
boolean enabled = false;
|
boolean enabled = false;
|
||||||
boolean haveData = false;
|
boolean haveData = false;
|
||||||
|
|
||||||
@ -306,7 +306,7 @@ public class AndroidSensorJoyInput implements SensorEventListener {
|
|||||||
*/
|
*/
|
||||||
private boolean updateOrientation() {
|
private boolean updateOrientation() {
|
||||||
SensorData sensorData;
|
SensorData sensorData;
|
||||||
AndroidJoystickAxis axis;
|
AndroidSensorJoystickAxis axis;
|
||||||
final float[] curInclinationMat = new float[16];
|
final float[] curInclinationMat = new float[16];
|
||||||
final float[] curRotationMat = new float[16];
|
final float[] curRotationMat = new float[16];
|
||||||
final float[] rotatedRotationMat = new float[16];
|
final float[] rotatedRotationMat = new float[16];
|
||||||
@ -374,7 +374,7 @@ public class AndroidSensorJoyInput implements SensorEventListener {
|
|||||||
sensorData.haveData = true;
|
sensorData.haveData = true;
|
||||||
} else {
|
} else {
|
||||||
if (axis.isChanged()) {
|
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) {
|
public Joystick loadJoystick(int joyId, InputManager inputManager) {
|
||||||
SensorData sensorData;
|
SensorData sensorData;
|
||||||
AndroidJoystickAxis axis;
|
AndroidSensorJoystickAxis axis;
|
||||||
|
|
||||||
AndroidJoystick joystick = new AndroidJoystick(inputManager,
|
AndroidSensorJoystick joystick = new AndroidSensorJoystick(inputManager,
|
||||||
joyHandler,
|
joyInput,
|
||||||
joyId,
|
joyId,
|
||||||
"AndroidSensorsJoystick");
|
"AndroidSensorsJoystick");
|
||||||
|
|
||||||
@ -522,15 +522,15 @@ public class AndroidSensorJoyInput implements SensorEventListener {
|
|||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logger.log(Level.FINE, "onSensorChanged for {0}: accuracy: {1}, values: {2}",
|
// logger.log(Level.FINE, "onSensorChanged for {0}: accuracy: {1}, values: {2}",
|
||||||
new Object[]{se.sensor.getName(), se.accuracy, se.values});
|
// new Object[]{se.sensor.getName(), se.accuracy, se.values});
|
||||||
|
|
||||||
int sensorType = se.sensor.getType();
|
int sensorType = se.sensor.getType();
|
||||||
|
|
||||||
SensorData sensorData = sensors.get(sensorType);
|
SensorData sensorData = sensors.get(sensorType);
|
||||||
if (sensorData != null) {
|
if (sensorData != null) {
|
||||||
logger.log(Level.FINE, "sensorData name: {0}, enabled: {1}, unreliable: {2}",
|
// logger.log(Level.FINE, "sensorData name: {0}, enabled: {1}, unreliable: {2}",
|
||||||
new Object[]{sensorData.sensor.getName(), sensorData.enabled, sensorData.sensorAccuracy == SensorManager.SENSOR_STATUS_UNRELIABLE});
|
// new Object[]{sensorData.sensor.getName(), sensorData.enabled, sensorData.sensorAccuracy == SensorManager.SENSOR_STATUS_UNRELIABLE});
|
||||||
}
|
}
|
||||||
if (sensorData != null && sensorData.sensor.equals(se.sensor) && sensorData.enabled) {
|
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) {
|
if (sensorData.axes.size() > 0) {
|
||||||
AndroidJoystickAxis axis;
|
AndroidSensorJoystickAxis axis;
|
||||||
for (int i=0; i<se.values.length; i++) {
|
for (int i=0; i<se.values.length; i++) {
|
||||||
axis = sensorData.axes.get(i);
|
axis = sensorData.axes.get(i);
|
||||||
if (axis != null) {
|
if (axis != null) {
|
||||||
@ -554,8 +554,8 @@ public class AndroidSensorJoyInput implements SensorEventListener {
|
|||||||
} else {
|
} else {
|
||||||
if (axis.isChanged()) {
|
if (axis.isChanged()) {
|
||||||
JoyAxisEvent event = new JoyAxisEvent(axis, axis.getJoystickAxisValue());
|
JoyAxisEvent event = new JoyAxisEvent(axis, axis.getJoystickAxisValue());
|
||||||
logger.log(Level.INFO, "adding JoyAxisEvent: {0}", event);
|
// logger.log(Level.INFO, "adding JoyAxisEvent: {0}", event);
|
||||||
joyHandler.addEvent(event);
|
joyInput.addEvent(event);
|
||||||
// joyHandler.addEvent(new JoyAxisEvent(axis, axis.getJoystickAxisValue()));
|
// joyHandler.addEvent(new JoyAxisEvent(axis, axis.getJoystickAxisValue()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -585,14 +585,14 @@ public class AndroidSensorJoyInput implements SensorEventListener {
|
|||||||
|
|
||||||
// End of SensorEventListener methods
|
// End of SensorEventListener methods
|
||||||
|
|
||||||
protected class AndroidJoystick extends AbstractJoystick {
|
protected class AndroidSensorJoystick extends AbstractJoystick {
|
||||||
private JoystickAxis nullAxis;
|
private JoystickAxis nullAxis;
|
||||||
private JoystickAxis xAxis;
|
private JoystickAxis xAxis;
|
||||||
private JoystickAxis yAxis;
|
private JoystickAxis yAxis;
|
||||||
private JoystickAxis povX;
|
private JoystickAxis povX;
|
||||||
private JoystickAxis povY;
|
private JoystickAxis povY;
|
||||||
|
|
||||||
public AndroidJoystick( InputManager inputManager, JoyInput joyInput,
|
public AndroidSensorJoystick( InputManager inputManager, JoyInput joyInput,
|
||||||
int joyId, String name){
|
int joyId, String name){
|
||||||
|
|
||||||
super( inputManager, joyInput, joyId, name );
|
super( inputManager, joyInput, joyId, name );
|
||||||
@ -606,10 +606,10 @@ public class AndroidSensorJoyInput implements SensorEventListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AndroidJoystickAxis addAxis(String axisName, String logicalName, int axisNum, float maxRawValue) {
|
protected AndroidSensorJoystickAxis addAxis(String axisName, String logicalName, int axisNum, float maxRawValue) {
|
||||||
AndroidJoystickAxis axis;
|
AndroidSensorJoystickAxis axis;
|
||||||
|
|
||||||
axis = new AndroidJoystickAxis(
|
axis = new AndroidSensorJoystickAxis(
|
||||||
getInputManager(), // InputManager (InputManager)
|
getInputManager(), // InputManager (InputManager)
|
||||||
this, // parent Joystick (Joystick)
|
this, // parent Joystick (Joystick)
|
||||||
axisNum, // Axis Index (int)
|
axisNum, // Axis Index (int)
|
||||||
@ -654,7 +654,7 @@ public class AndroidSensorJoyInput implements SensorEventListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AndroidJoystickAxis extends DefaultJoystickAxis implements SensorJoystickAxis {
|
public class AndroidSensorJoystickAxis extends DefaultJoystickAxis implements SensorJoystickAxis {
|
||||||
float zeroRawValue = 0f;
|
float zeroRawValue = 0f;
|
||||||
float curRawValue = 0f;
|
float curRawValue = 0f;
|
||||||
float lastRawValue = 0f;
|
float lastRawValue = 0f;
|
||||||
@ -662,7 +662,7 @@ public class AndroidSensorJoyInput implements SensorEventListener {
|
|||||||
float maxRawValue = FastMath.HALF_PI;
|
float maxRawValue = FastMath.HALF_PI;
|
||||||
boolean enabled = true;
|
boolean enabled = true;
|
||||||
|
|
||||||
public AndroidJoystickAxis(InputManager inputManager, Joystick parent,
|
public AndroidSensorJoystickAxis(InputManager inputManager, Joystick parent,
|
||||||
int axisIndex, String name, String logicalId,
|
int axisIndex, String name, String logicalId,
|
||||||
boolean isAnalog, boolean isRelative, float deadZone,
|
boolean isAnalog, boolean isRelative, float deadZone,
|
||||||
float maxRawValue) {
|
float maxRawValue) {
|
||||||
|
@ -1,257 +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.view.MotionEvent;
|
|
||||||
import android.view.View;
|
|
||||||
import com.jme3.input.event.InputEvent;
|
|
||||||
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 java.util.HashMap;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AndroidTouchHandler 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 AndroidTouchHandler implements View.OnTouchListener {
|
|
||||||
private static final Logger logger = Logger.getLogger(AndroidTouchHandler.class.getName());
|
|
||||||
|
|
||||||
final private HashMap<Integer, Vector2f> lastPositions = new HashMap<Integer, Vector2f>();
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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<Integer, Vector2f> lastPositions = new HashMap<Integer, Vector2f>();
|
||||||
|
final private ConcurrentLinkedQueue<InputEvent> inputEventQueue = new ConcurrentLinkedQueue<InputEvent>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -33,7 +33,6 @@
|
|||||||
package com.jme3.input.android;
|
package com.jme3.input.android;
|
||||||
|
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
|
||||||
import com.jme3.input.event.TouchEvent;
|
import com.jme3.input.event.TouchEvent;
|
||||||
import com.jme3.math.Vector2f;
|
import com.jme3.math.Vector2f;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -41,36 +40,20 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AndroidTouchHandler14 is an extension of AndroidTouchHander that adds the
|
* AndroidTouchHandler14 extends AndroidTouchHandler to process the onHover
|
||||||
* Android touch event functionality between Android rev 9 (Android 2.3) and
|
* events added in Android rev 14 (Android 4.0).
|
||||||
* Android rev 14 (Android 4.0).
|
*
|
||||||
*
|
|
||||||
* @author iwgeric
|
* @author iwgeric
|
||||||
*/
|
*/
|
||||||
public class AndroidTouchHandler14 extends AndroidTouchHandler implements
|
public class AndroidTouchInput14 extends AndroidTouchInput {
|
||||||
View.OnHoverListener {
|
private static final Logger logger = Logger.getLogger(AndroidTouchInput14.class.getName());
|
||||||
private static final Logger logger = Logger.getLogger(AndroidTouchHandler14.class.getName());
|
|
||||||
final private HashMap<Integer, Vector2f> lastHoverPositions = new HashMap<Integer, Vector2f>();
|
final private HashMap<Integer, Vector2f> lastHoverPositions = new HashMap<Integer, Vector2f>();
|
||||||
|
|
||||||
public AndroidTouchHandler14(AndroidInputHandler androidInput, AndroidGestureHandler gestureHandler) {
|
public AndroidTouchInput14(AndroidInputHandler androidInput) {
|
||||||
super(androidInput, gestureHandler);
|
super(androidInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public boolean onHover(MotionEvent event) {
|
||||||
public void setView(View view) {
|
|
||||||
if (view != null) {
|
|
||||||
view.setOnHoverListener(this);
|
|
||||||
} else {
|
|
||||||
androidInput.getView().setOnHoverListener(null);
|
|
||||||
}
|
|
||||||
super.setView(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean onHover(View view, MotionEvent event) {
|
|
||||||
if (view == null || view != androidInput.getView()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean consumed = false;
|
boolean consumed = false;
|
||||||
int action = getAction(event);
|
int action = getAction(event);
|
||||||
int pointerId = getPointerId(event);
|
int pointerId = getPointerId(event);
|
||||||
@ -78,34 +61,34 @@ public class AndroidTouchHandler14 extends AndroidTouchHandler implements
|
|||||||
Vector2f lastPos = lastHoverPositions.get(pointerId);
|
Vector2f lastPos = lastHoverPositions.get(pointerId);
|
||||||
float jmeX;
|
float jmeX;
|
||||||
float jmeY;
|
float jmeY;
|
||||||
|
|
||||||
numPointers = event.getPointerCount();
|
numPointers = event.getPointerCount();
|
||||||
|
|
||||||
logger.log(Level.INFO, "onHover pointerId: {0}, action: {1}, x: {2}, y: {3}, numPointers: {4}",
|
// 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()});
|
// new Object[]{pointerId, action, event.getX(), event.getY(), event.getPointerCount()});
|
||||||
|
|
||||||
TouchEvent touchEvent;
|
TouchEvent touchEvent;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case MotionEvent.ACTION_HOVER_ENTER:
|
case MotionEvent.ACTION_HOVER_ENTER:
|
||||||
jmeX = androidInput.getJmeX(event.getX(pointerIndex));
|
jmeX = getJmeX(event.getX(pointerIndex));
|
||||||
jmeY = androidInput.invertY(androidInput.getJmeY(event.getY(pointerIndex)));
|
jmeY = invertY(getJmeY(event.getY(pointerIndex)));
|
||||||
touchEvent = androidInput.getFreeTouchEvent();
|
touchEvent = getFreeTouchEvent();
|
||||||
touchEvent.set(TouchEvent.Type.HOVER_START, jmeX, jmeY, 0, 0);
|
touchEvent.set(TouchEvent.Type.HOVER_START, jmeX, jmeY, 0, 0);
|
||||||
touchEvent.setPointerId(pointerId);
|
touchEvent.setPointerId(pointerId);
|
||||||
touchEvent.setTime(event.getEventTime());
|
touchEvent.setTime(event.getEventTime());
|
||||||
touchEvent.setPressure(event.getPressure(pointerIndex));
|
touchEvent.setPressure(event.getPressure(pointerIndex));
|
||||||
|
|
||||||
lastPos = new Vector2f(jmeX, jmeY);
|
lastPos = new Vector2f(jmeX, jmeY);
|
||||||
lastHoverPositions.put(pointerId, lastPos);
|
lastHoverPositions.put(pointerId, lastPos);
|
||||||
|
|
||||||
processEvent(touchEvent);
|
addEvent(touchEvent);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
case MotionEvent.ACTION_HOVER_MOVE:
|
case MotionEvent.ACTION_HOVER_MOVE:
|
||||||
// Convert all pointers into events
|
// Convert all pointers into events
|
||||||
for (int p = 0; p < event.getPointerCount(); p++) {
|
for (int p = 0; p < event.getPointerCount(); p++) {
|
||||||
jmeX = androidInput.getJmeX(event.getX(p));
|
jmeX = getJmeX(event.getX(p));
|
||||||
jmeY = androidInput.invertY(androidInput.getJmeY(event.getY(p)));
|
jmeY = invertY(getJmeY(event.getY(p)));
|
||||||
lastPos = lastHoverPositions.get(event.getPointerId(p));
|
lastPos = lastHoverPositions.get(event.getPointerId(p));
|
||||||
if (lastPos == null) {
|
if (lastPos == null) {
|
||||||
lastPos = new Vector2f(jmeX, jmeY);
|
lastPos = new Vector2f(jmeX, jmeY);
|
||||||
@ -115,38 +98,39 @@ public class AndroidTouchHandler14 extends AndroidTouchHandler implements
|
|||||||
float dX = jmeX - lastPos.x;
|
float dX = jmeX - lastPos.x;
|
||||||
float dY = jmeY - lastPos.y;
|
float dY = jmeY - lastPos.y;
|
||||||
if (dX != 0 || dY != 0) {
|
if (dX != 0 || dY != 0) {
|
||||||
touchEvent = androidInput.getFreeTouchEvent();
|
touchEvent = getFreeTouchEvent();
|
||||||
touchEvent.set(TouchEvent.Type.HOVER_MOVE, jmeX, jmeY, dX, dY);
|
touchEvent.set(TouchEvent.Type.HOVER_MOVE, jmeX, jmeY, dX, dY);
|
||||||
touchEvent.setPointerId(event.getPointerId(p));
|
touchEvent.setPointerId(event.getPointerId(p));
|
||||||
touchEvent.setTime(event.getEventTime());
|
touchEvent.setTime(event.getEventTime());
|
||||||
touchEvent.setPressure(event.getPressure(p));
|
touchEvent.setPressure(event.getPressure(p));
|
||||||
lastPos.set(jmeX, jmeY);
|
lastPos.set(jmeX, jmeY);
|
||||||
|
|
||||||
processEvent(touchEvent);
|
addEvent(touchEvent);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
case MotionEvent.ACTION_HOVER_EXIT:
|
case MotionEvent.ACTION_HOVER_EXIT:
|
||||||
jmeX = androidInput.getJmeX(event.getX(pointerIndex));
|
jmeX = getJmeX(event.getX(pointerIndex));
|
||||||
jmeY = androidInput.invertY(androidInput.getJmeY(event.getY(pointerIndex)));
|
jmeY = invertY(getJmeY(event.getY(pointerIndex)));
|
||||||
touchEvent = androidInput.getFreeTouchEvent();
|
touchEvent = getFreeTouchEvent();
|
||||||
touchEvent.set(TouchEvent.Type.HOVER_END, jmeX, jmeY, 0, 0);
|
touchEvent.set(TouchEvent.Type.HOVER_END, jmeX, jmeY, 0, 0);
|
||||||
touchEvent.setPointerId(pointerId);
|
touchEvent.setPointerId(pointerId);
|
||||||
touchEvent.setTime(event.getEventTime());
|
touchEvent.setTime(event.getEventTime());
|
||||||
touchEvent.setPressure(event.getPressure(pointerIndex));
|
touchEvent.setPressure(event.getPressure(pointerIndex));
|
||||||
lastHoverPositions.remove(pointerId);
|
lastHoverPositions.remove(pointerId);
|
||||||
|
|
||||||
processEvent(touchEvent);
|
addEvent(touchEvent);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
consumed = false;
|
consumed = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -47,7 +47,7 @@ import android.widget.EditText;
|
|||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import com.jme3.input.*;
|
import com.jme3.input.*;
|
||||||
import com.jme3.input.android.AndroidInputHandler;
|
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.controls.SoftTextDialogInputListener;
|
||||||
import com.jme3.input.dummy.DummyKeyInput;
|
import com.jme3.input.dummy.DummyKeyInput;
|
||||||
import com.jme3.input.dummy.DummyMouseInput;
|
import com.jme3.input.dummy.DummyMouseInput;
|
||||||
@ -75,7 +75,6 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
|
|||||||
protected SystemListener listener;
|
protected SystemListener listener;
|
||||||
protected boolean autoFlush = true;
|
protected boolean autoFlush = true;
|
||||||
protected AndroidInputHandler androidInput;
|
protected AndroidInputHandler androidInput;
|
||||||
protected AndroidJoyInputHandler androidJoyInput = null;
|
|
||||||
protected long minFrameDuration = 0; // No FPS cap
|
protected long minFrameDuration = 0; // No FPS cap
|
||||||
protected long lastUpdateTime = 0;
|
protected long lastUpdateTime = 0;
|
||||||
|
|
||||||
@ -111,18 +110,17 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
|
|||||||
|
|
||||||
// Start to set up the view
|
// Start to set up the view
|
||||||
GLSurfaceView view = new GLSurfaceView(context);
|
GLSurfaceView view = new GLSurfaceView(context);
|
||||||
|
logger.log(Level.INFO, "Android Build Version: {0}", Build.VERSION.SDK_INT);
|
||||||
if (androidInput == null) {
|
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.setView(view);
|
||||||
androidInput.loadSettings(settings);
|
androidInput.loadSettings(settings);
|
||||||
|
|
||||||
if (androidJoyInput == null) {
|
|
||||||
androidJoyInput = new AndroidJoyInputHandler();
|
|
||||||
}
|
|
||||||
androidJoyInput.setView(view);
|
|
||||||
androidJoyInput.loadSettings(settings);
|
|
||||||
|
|
||||||
// setEGLContextClientVersion must be set before calling setRenderer
|
// setEGLContextClientVersion must be set before calling setRenderer
|
||||||
// this means it cannot be set in AndroidConfigChooser (too late)
|
// this means it cannot be set in AndroidConfigChooser (too late)
|
||||||
view.setEGLContextClientVersion(2);
|
view.setEGLContextClientVersion(2);
|
||||||
@ -235,9 +233,6 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
|
|||||||
if (androidInput != null) {
|
if (androidInput != null) {
|
||||||
androidInput.loadSettings(settings);
|
androidInput.loadSettings(settings);
|
||||||
}
|
}
|
||||||
if (androidJoyInput != null) {
|
|
||||||
androidJoyInput.loadSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings.getFrameRate() > 0) {
|
if (settings.getFrameRate() > 0) {
|
||||||
minFrameDuration = (long)(1000d / (double)settings.getFrameRate()); // ms
|
minFrameDuration = (long)(1000d / (double)settings.getFrameRate()); // ms
|
||||||
@ -274,12 +269,12 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JoyInput getJoyInput() {
|
public JoyInput getJoyInput() {
|
||||||
return androidJoyInput;
|
return androidInput.getJoyInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TouchInput getTouchInput() {
|
public TouchInput getTouchInput() {
|
||||||
return androidInput;
|
return androidInput.getTouchInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user