InputAndroid.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Input/InputAndroid.h>
  6. #include <AnKi/Core/NativeWindowAndroid.h>
  7. #include <AnKi/Util/Logger.h>
  8. namespace anki
  9. {
  10. Error Input::newInstance(AllocAlignedCallback allocCallback, void* allocCallbackUserData, NativeWindow* nativeWindow,
  11. Input*& input)
  12. {
  13. ANKI_ASSERT(allocCallback && nativeWindow);
  14. HeapAllocator<U8> alloc(allocCallback, allocCallbackUserData);
  15. InputAndroid* ainput =
  16. static_cast<InputAndroid*>(alloc.getMemoryPool().allocate(sizeof(InputAndroid), alignof(InputAndroid)));
  17. ::new(ainput) InputAndroid();
  18. ainput->m_alloc = alloc;
  19. ainput->m_nativeWindow = nativeWindow;
  20. const Error err = ainput->init();
  21. if(err)
  22. {
  23. ainput->~InputAndroid();
  24. alloc.getMemoryPool().free(ainput);
  25. input = nullptr;
  26. return err;
  27. }
  28. else
  29. {
  30. input = ainput;
  31. return Error::NONE;
  32. }
  33. }
  34. void Input::deleteInstance(Input* input)
  35. {
  36. if(input)
  37. {
  38. InputAndroid* self = static_cast<InputAndroid*>(input);
  39. HeapAllocator<U8> alloc = self->m_alloc;
  40. self->~InputAndroid();
  41. alloc.getMemoryPool().free(self);
  42. }
  43. }
  44. Error Input::handleEvents()
  45. {
  46. for(U32& k : m_touchPointers)
  47. {
  48. if(k)
  49. {
  50. ++k;
  51. }
  52. }
  53. int ident;
  54. int events;
  55. android_poll_source* source;
  56. while((ident = ALooper_pollAll(0, nullptr, &events, reinterpret_cast<void**>(&source))) >= 0)
  57. {
  58. if(source != nullptr)
  59. {
  60. source->process(g_androidApp, source);
  61. }
  62. }
  63. return Error::NONE;
  64. }
  65. void Input::moveCursor(const Vec2& posNdc)
  66. {
  67. m_mousePosNdc = posNdc;
  68. m_mousePosWin =
  69. UVec2((posNdc * 0.5f + 0.5f) * Vec2(F32(m_nativeWindow->getWidth()), F32(m_nativeWindow->getHeight())));
  70. }
  71. void Input::hideCursor(Bool hide)
  72. {
  73. // do nothing
  74. }
  75. Error InputAndroid::init()
  76. {
  77. ANKI_ASSERT(m_nativeWindow);
  78. g_androidApp->userData = this;
  79. g_androidApp->onAppCmd = [](android_app* app, int32_t cmd) {
  80. InputAndroid* self = static_cast<InputAndroid*>(app->userData);
  81. self->handleAndroidEvents(app, cmd);
  82. };
  83. g_androidApp->onInputEvent = [](android_app* app, AInputEvent* event) -> int {
  84. InputAndroid* self = static_cast<InputAndroid*>(app->userData);
  85. return self->handleAndroidInput(app, event);
  86. };
  87. return Error::NONE;
  88. }
  89. void InputAndroid::handleAndroidEvents(android_app* app, int32_t cmd)
  90. {
  91. switch(cmd)
  92. {
  93. case APP_CMD_TERM_WINDOW:
  94. case APP_CMD_LOST_FOCUS:
  95. addEvent(InputEvent::WINDOW_CLOSED);
  96. break;
  97. }
  98. }
  99. int InputAndroid::handleAndroidInput(android_app* app, AInputEvent* event)
  100. {
  101. const I32 type = AInputEvent_getType(event);
  102. const I32 source = AInputEvent_getSource(event);
  103. I32 handled = 0;
  104. switch(type)
  105. {
  106. case AINPUT_EVENT_TYPE_KEY:
  107. // TODO
  108. break;
  109. case AINPUT_EVENT_TYPE_MOTION:
  110. {
  111. const I32 pointer = AMotionEvent_getAction(event);
  112. const I32 action = pointer & AMOTION_EVENT_ACTION_MASK;
  113. const I32 index =
  114. (pointer & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
  115. if(source & AINPUT_SOURCE_JOYSTICK)
  116. {
  117. // TODO
  118. }
  119. else if(source & AINPUT_SOURCE_TOUCHSCREEN)
  120. {
  121. auto update = [event, this](U32 index, U32 pressValue) {
  122. const F32 x = AMotionEvent_getX(event, index);
  123. const F32 y = AMotionEvent_getY(event, index);
  124. const I32 id = AMotionEvent_getPointerId(event, index);
  125. m_touchPointerPosWin[id] = UVec2(U32(x), U32(y));
  126. m_touchPointerPosNdc[id].x() = F32(x) / F32(m_nativeWindow->getWidth()) * 2.0f - 1.0f;
  127. m_touchPointerPosNdc[id].y() = -(F32(y) / F32(m_nativeWindow->getHeight()) * 2.0f - 1.0f);
  128. if(pressValue == 0 || pressValue == 1)
  129. {
  130. m_touchPointers[id] = pressValue;
  131. }
  132. };
  133. switch(action)
  134. {
  135. case AMOTION_EVENT_ACTION_DOWN:
  136. case AMOTION_EVENT_ACTION_POINTER_DOWN:
  137. update(index, 1);
  138. break;
  139. case AMOTION_EVENT_ACTION_MOVE:
  140. {
  141. const U32 count = U32(AMotionEvent_getPointerCount(event));
  142. for(U32 i = 0; i < count; i++)
  143. {
  144. update(i, 2);
  145. }
  146. break;
  147. }
  148. case AMOTION_EVENT_ACTION_UP:
  149. case AMOTION_EVENT_ACTION_POINTER_UP:
  150. update(index, 0);
  151. break;
  152. default:
  153. break;
  154. }
  155. }
  156. break;
  157. }
  158. default:
  159. break;
  160. }
  161. return handled;
  162. }
  163. } // end namespace anki