AndroidInput.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. package com.jme3.input.android;
  2. import java.util.List;
  3. import java.util.ArrayList;
  4. import java.util.logging.Logger;
  5. import android.content.Context;
  6. import android.opengl.GLSurfaceView;
  7. import android.util.AttributeSet;
  8. import android.view.GestureDetector;
  9. import android.view.KeyEvent;
  10. import android.view.MotionEvent;
  11. import android.view.ScaleGestureDetector;
  12. import com.jme3.input.android.TouchEvent;
  13. import com.jme3.input.KeyInput;
  14. import com.jme3.input.MouseInput;
  15. import com.jme3.input.RawInputListener;
  16. import com.jme3.input.event.KeyInputEvent;
  17. import com.jme3.input.event.MouseButtonEvent;
  18. import com.jme3.input.event.MouseMotionEvent;
  19. import com.jme3.math.Vector2f;
  20. public class AndroidInput extends GLSurfaceView implements KeyInput, MouseInput,
  21. GestureDetector.OnGestureListener, ScaleGestureDetector.OnScaleGestureListener
  22. {
  23. private final static Logger logger = Logger.getLogger(AndroidInput.class.getName());
  24. private RawInputListener listenerRaw = null;
  25. private AndroidTouchInputListener listenerTouch = null;
  26. private ScaleGestureDetector scaledetector;
  27. private GestureDetector detector;
  28. private Vector2f lastPos = new Vector2f();
  29. private boolean dragging = false;
  30. private List<Object> currentEvents = new ArrayList<Object>();
  31. private final static int MAX_EVENTS = 1024;
  32. private boolean FIRE_MOUSE_EVENTS = true;
  33. private static final int[] ANDROID_TO_JME = {
  34. 0x0, // unknown
  35. 0x0, // key code soft left
  36. 0x0, // key code soft right
  37. KeyInput.KEY_HOME,
  38. KeyInput.KEY_ESCAPE, // key back
  39. 0x0, // key call
  40. 0x0, // key endcall
  41. KeyInput.KEY_0,
  42. KeyInput.KEY_1,
  43. KeyInput.KEY_2,
  44. KeyInput.KEY_3,
  45. KeyInput.KEY_4,
  46. KeyInput.KEY_5,
  47. KeyInput.KEY_6,
  48. KeyInput.KEY_7,
  49. KeyInput.KEY_8,
  50. KeyInput.KEY_9,
  51. KeyInput.KEY_MULTIPLY,
  52. 0x0, // key pound
  53. KeyInput.KEY_UP,
  54. KeyInput.KEY_DOWN,
  55. KeyInput.KEY_LEFT,
  56. KeyInput.KEY_RIGHT,
  57. KeyInput.KEY_RETURN, // dpad center
  58. 0x0, // volume up
  59. 0x0, // volume down
  60. KeyInput.KEY_POWER, // power (?)
  61. 0x0, // camera
  62. 0x0, // clear
  63. KeyInput.KEY_A,
  64. KeyInput.KEY_B,
  65. KeyInput.KEY_C,
  66. KeyInput.KEY_D,
  67. KeyInput.KEY_E,
  68. KeyInput.KEY_F,
  69. KeyInput.KEY_G,
  70. KeyInput.KEY_H,
  71. KeyInput.KEY_I,
  72. KeyInput.KEY_J,
  73. KeyInput.KEY_K,
  74. KeyInput.KEY_L,
  75. KeyInput.KEY_M,
  76. KeyInput.KEY_N,
  77. KeyInput.KEY_O,
  78. KeyInput.KEY_P,
  79. KeyInput.KEY_Q,
  80. KeyInput.KEY_R,
  81. KeyInput.KEY_S,
  82. KeyInput.KEY_T,
  83. KeyInput.KEY_U,
  84. KeyInput.KEY_V,
  85. KeyInput.KEY_W,
  86. KeyInput.KEY_X,
  87. KeyInput.KEY_Y,
  88. KeyInput.KEY_Z,
  89. KeyInput.KEY_COMMA,
  90. KeyInput.KEY_PERIOD,
  91. KeyInput.KEY_LMENU,
  92. KeyInput.KEY_RMENU,
  93. KeyInput.KEY_LSHIFT,
  94. KeyInput.KEY_RSHIFT,
  95. // 0x0, // fn
  96. // 0x0, // cap (?)
  97. KeyInput.KEY_TAB,
  98. KeyInput.KEY_SPACE,
  99. 0x0, // sym (?) symbol
  100. 0x0, // explorer
  101. 0x0, // envelope
  102. KeyInput.KEY_RETURN, // newline/enter
  103. KeyInput.KEY_DELETE,
  104. KeyInput.KEY_GRAVE,
  105. KeyInput.KEY_MINUS,
  106. KeyInput.KEY_EQUALS,
  107. KeyInput.KEY_LBRACKET,
  108. KeyInput.KEY_RBRACKET,
  109. KeyInput.KEY_BACKSLASH,
  110. KeyInput.KEY_SEMICOLON,
  111. KeyInput.KEY_APOSTROPHE,
  112. KeyInput.KEY_SLASH,
  113. KeyInput.KEY_AT, // at (@)
  114. KeyInput.KEY_NUMLOCK, //0x0, // num
  115. 0x0, //headset hook
  116. 0x0, //focus
  117. KeyInput.KEY_ADD,
  118. KeyInput.KEY_LMETA, //menu
  119. 0x0,//notification
  120. 0x0,//search
  121. 0x0,//media play/pause
  122. 0x0,//media stop
  123. 0x0,//media next
  124. 0x0,//media previous
  125. 0x0,//media rewind
  126. 0x0,//media fastforward
  127. 0x0,//mute
  128. };
  129. public AndroidInput(Context ctx, AttributeSet attribs)
  130. {
  131. super(ctx, attribs);
  132. detector=new GestureDetector(this);
  133. scaledetector=new ScaleGestureDetector(ctx, this);
  134. }
  135. public AndroidInput(Context ctx)
  136. {
  137. super(ctx);
  138. detector=new GestureDetector(this);
  139. scaledetector=new ScaleGestureDetector(ctx, this);
  140. }
  141. /**
  142. * onTouchEvent gets called from android thread on touchpad events
  143. */
  144. @Override
  145. public boolean onTouchEvent(MotionEvent event)
  146. {
  147. boolean bWasHandled = false;
  148. MouseButtonEvent btn;
  149. TouchEvent touch;
  150. // Send the raw event
  151. processEvent(event);
  152. // Try to detect gestures
  153. this.detector.onTouchEvent(event);
  154. this.scaledetector.onTouchEvent(event);
  155. switch (event.getAction())
  156. {
  157. case MotionEvent.ACTION_DOWN:
  158. // Store current pos
  159. lastPos.set(event.getX(),event.getY());
  160. if (FIRE_MOUSE_EVENTS)
  161. {
  162. // Handle mouse events
  163. btn = new MouseButtonEvent(0, true, (int)lastPos.getX(), (int)lastPos.getY());
  164. btn.setTime(event.getEventTime());
  165. processEvent(btn);
  166. }
  167. // Handle gesture events
  168. touch = new TouchEvent(TouchEvent.Type.GRABBED, TouchEvent.Operation.NOP,event.getX(),event.getY(),0,0,null);
  169. processEvent(touch);
  170. bWasHandled = true;
  171. break;
  172. case MotionEvent.ACTION_UP:
  173. if (FIRE_MOUSE_EVENTS)
  174. {
  175. // Handle mouse events
  176. btn = new MouseButtonEvent(0, false, (int)event.getX(), (int)event.getY());
  177. btn.setTime(event.getEventTime());
  178. processEvent(btn);
  179. }
  180. // Handle gesture events
  181. if(dragging)
  182. {
  183. touch = new TouchEvent(TouchEvent.Type.DRAGGED, TouchEvent.Operation.STOPPED,event.getX(),event.getY(),event.getX()-lastPos.getX(),event.getY()-lastPos.getY(),null);
  184. processEvent(touch);
  185. }
  186. touch = new TouchEvent(TouchEvent.Type.RELEASED, TouchEvent.Operation.NOP,event.getX(),event.getY(),0,0,null);
  187. processEvent(touch);
  188. dragging=false;
  189. bWasHandled = true;
  190. break;
  191. case MotionEvent.ACTION_MOVE:
  192. if(!scaledetector.isInProgress())
  193. {
  194. if(!dragging)
  195. touch = new TouchEvent(TouchEvent.Type.DRAGGED, TouchEvent.Operation.STARTED,event.getX(),event.getY(),event.getX()-lastPos.getX(),event.getY()-lastPos.getY(),null);
  196. else
  197. touch = new TouchEvent(TouchEvent.Type.DRAGGED, TouchEvent.Operation.RUNNING,event.getX(),event.getY(),event.getX()-lastPos.getX(),event.getY()-lastPos.getY(),null);
  198. processEvent(touch);
  199. dragging=true;
  200. }
  201. if (FIRE_MOUSE_EVENTS)
  202. {
  203. int newX = getWidth() - (int) event.getX();
  204. int newY = (int) event.getY();
  205. int dx;
  206. int dy;
  207. if (lastPos.getX() != -1){
  208. dx = newX - (int)lastPos.getX();
  209. dy = newY - (int)lastPos.getY();
  210. }else{
  211. dx = 0;
  212. dy = 0;
  213. }
  214. MouseMotionEvent mot = new MouseMotionEvent(newX, newY, dx, dy, 0, 0);
  215. mot.setTime(event.getEventTime());
  216. processEvent(mot);
  217. }
  218. bWasHandled = true;
  219. break;
  220. // TODO: implement motion events
  221. case MotionEvent.ACTION_POINTER_UP:
  222. break;
  223. case MotionEvent.ACTION_POINTER_DOWN:
  224. break;
  225. case MotionEvent.ACTION_OUTSIDE:
  226. break;
  227. case MotionEvent.ACTION_CANCEL:
  228. break;
  229. }
  230. return bWasHandled;
  231. }
  232. @Override
  233. public boolean onKeyDown (int keyCode, KeyEvent event) {
  234. // Send the raw event
  235. processEvent(event);
  236. int jmeCode = ANDROID_TO_JME[keyCode];
  237. if (jmeCode != 0)
  238. {
  239. String str = event.getCharacters();
  240. char c = str != null && str.length() > 0 ? str.charAt(0) : 0x0;
  241. KeyInputEvent evt = new KeyInputEvent(jmeCode, c, true, false);
  242. logger.info("onKeyDown " + evt);
  243. processEvent(evt);
  244. }
  245. // Handle all keys ourself, except the back button (4)
  246. if (keyCode == 4)
  247. return false;
  248. else
  249. return true;
  250. }
  251. @Override
  252. public boolean onKeyUp (int keyCode, KeyEvent event) {
  253. // Send the raw event
  254. processEvent(event);
  255. int jmeCode = ANDROID_TO_JME[keyCode];
  256. if (jmeCode != 0)
  257. {
  258. String str = event.getCharacters();
  259. char c = str != null && str.length() > 0 ? str.charAt(0) : 0x0;
  260. KeyInputEvent evt = new KeyInputEvent(jmeCode, c, false, false);
  261. logger.info("onKeyUp " + evt);
  262. processEvent(evt);
  263. }
  264. // Handle all keys ourself, except the back button (4)
  265. if (keyCode == 4)
  266. return false;
  267. else
  268. return true;
  269. }
  270. public void setCursorVisible(boolean visible){
  271. }
  272. public int getButtonCount(){
  273. return 255;
  274. }
  275. public void initialize() {
  276. }
  277. public void update() {
  278. generateEvents();
  279. }
  280. public void destroy() {
  281. }
  282. public boolean isInitialized() {
  283. return true;
  284. }
  285. private void processEvent(Object event)
  286. {
  287. synchronized (currentEvents) {
  288. if (currentEvents.size() < MAX_EVENTS)
  289. currentEvents.add(event);
  290. }
  291. }
  292. Object event;
  293. private void generateEvents() {
  294. if (listenerRaw != null)
  295. {
  296. synchronized (currentEvents) {
  297. //for (Object event: currentEvents) {
  298. for (int i = 0; i < currentEvents.size(); i++) {
  299. event = currentEvents.get(i);
  300. if (event instanceof MouseButtonEvent) {
  301. listenerRaw.onMouseButtonEvent((MouseButtonEvent) event);
  302. } else if (event instanceof MouseMotionEvent) {
  303. listenerRaw.onMouseMotionEvent((MouseMotionEvent) event);
  304. } else if (event instanceof KeyInputEvent) {
  305. listenerRaw.onKeyEvent((KeyInputEvent) event);
  306. } else if (event instanceof TouchEvent) {
  307. if (listenerTouch != null)
  308. listenerTouch.onTouchEvent((TouchEvent) event);
  309. } else if (event instanceof MotionEvent) {
  310. if (listenerTouch != null)
  311. listenerTouch.onMotionEvent((MotionEvent) event);
  312. } else if (event instanceof KeyEvent) {
  313. if (listenerTouch != null)
  314. listenerTouch.onAndroidKeyEvent((KeyEvent) event);
  315. }
  316. }
  317. currentEvents.clear();
  318. }
  319. }
  320. }
  321. public void setInputListener(RawInputListener listener) {
  322. this.listenerRaw = listener;
  323. }
  324. public void setInputListener(AndroidTouchInputListener listener) {
  325. this.listenerRaw = listener;
  326. this.listenerTouch = listener;
  327. }
  328. public long getInputTimeNanos() {
  329. return System.nanoTime();
  330. }
  331. // --------------- Gesture detected callback events ----------------------------------
  332. public boolean onDown(MotionEvent event)
  333. {
  334. return false;
  335. }
  336. public void onLongPress(MotionEvent event)
  337. {
  338. TouchEvent touch = new TouchEvent(TouchEvent.Type.LONGPRESSED, TouchEvent.Operation.NOP,event.getX(),event.getY(),0,0,null);
  339. processEvent(touch);
  340. }
  341. public boolean onFling(MotionEvent event, MotionEvent event2, float vx, float vy)
  342. {
  343. TouchEvent touch = new TouchEvent(TouchEvent.Type.FLING, TouchEvent.Operation.NOP,event.getX(),event.getY(),0,0,null);
  344. processEvent(touch);
  345. return true;
  346. }
  347. public boolean onSingleTapConfirmed(MotionEvent event)
  348. {
  349. TouchEvent touch = new TouchEvent(TouchEvent.Type.TAP, TouchEvent.Operation.NOP,event.getX(),event.getY(),0,0,null);
  350. processEvent(touch);
  351. return true;
  352. }
  353. public boolean onDoubleTap(MotionEvent event)
  354. {
  355. TouchEvent touch = new TouchEvent(TouchEvent.Type.DOUBLETAP, TouchEvent.Operation.NOP,event.getX(),event.getY(),0,0,null);
  356. processEvent(touch);
  357. return true;
  358. }
  359. public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector)
  360. {
  361. TouchEvent touch = new TouchEvent(TouchEvent.Type.SCALE, TouchEvent.Operation.STARTED,scaleGestureDetector.getFocusX(),scaleGestureDetector.getFocusY(),0,0,new float[]{scaleGestureDetector.getCurrentSpan(),scaleGestureDetector.getScaleFactor()});
  362. processEvent(touch);
  363. return true;
  364. }
  365. public boolean onScale(ScaleGestureDetector scaleGestureDetector)
  366. {
  367. TouchEvent touch = new TouchEvent(TouchEvent.Type.SCALE, TouchEvent.Operation.RUNNING,scaleGestureDetector.getFocusX(),scaleGestureDetector.getFocusY(),0,0,new float[]{scaleGestureDetector.getCurrentSpan(),scaleGestureDetector.getScaleFactor()});
  368. processEvent(touch);
  369. if (FIRE_MOUSE_EVENTS)
  370. {
  371. MouseMotionEvent mot = new MouseMotionEvent(0, 0, 0, 0, 0, (int)scaleGestureDetector.getScaleFactor());
  372. mot.setTime(scaleGestureDetector.getEventTime());
  373. processEvent(mot);
  374. }
  375. return false;
  376. }
  377. public void onScaleEnd(ScaleGestureDetector scaleGestureDetector)
  378. {
  379. TouchEvent touch = new TouchEvent(TouchEvent.Type.SCALE, TouchEvent.Operation.STOPPED,scaleGestureDetector.getFocusX(),scaleGestureDetector.getFocusY(),0,0,new float[]{scaleGestureDetector.getCurrentSpan(),scaleGestureDetector.getScaleFactor()});
  380. processEvent(touch);
  381. }
  382. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
  383. float distanceY) {
  384. // TODO Auto-generated method stub
  385. return false;
  386. }
  387. public void onShowPress(MotionEvent e) {
  388. // TODO Auto-generated method stub
  389. }
  390. public boolean onSingleTapUp(MotionEvent event)
  391. {
  392. TouchEvent touch = new TouchEvent(TouchEvent.Type.TAP, TouchEvent.Operation.NOP,event.getX(),event.getY(),0,0,null);
  393. processEvent(touch);
  394. return true;
  395. }
  396. }