InputAndroid.cpp 4.1 KB

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