InputAndroid.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // Copyright (C) 2009-present, 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/Window/InputAndroid.h>
  6. #include <AnKi/Window/NativeWindowAndroid.h>
  7. #include <AnKi/Util/Logger.h>
  8. namespace anki {
  9. template<>
  10. template<>
  11. Input& MakeSingletonPtr<Input>::allocateSingleton<>()
  12. {
  13. ANKI_ASSERT(m_global == nullptr);
  14. m_global = new InputAndroid;
  15. #if ANKI_ASSERTIONS_ENABLED
  16. ++g_singletonsAllocated;
  17. #endif
  18. return *m_global;
  19. }
  20. template<>
  21. void MakeSingletonPtr<Input>::freeSingleton()
  22. {
  23. if(m_global)
  24. {
  25. delete static_cast<InputAndroid*>(m_global);
  26. m_global = nullptr;
  27. #if ANKI_ASSERTIONS_ENABLED
  28. --g_singletonsAllocated;
  29. #endif
  30. }
  31. }
  32. Error Input::init()
  33. {
  34. return static_cast<InputAndroid*>(this)->initInternal();
  35. }
  36. Error Input::handleEvents()
  37. {
  38. for(I32& k : m_touchPointers)
  39. {
  40. if(k > 0)
  41. {
  42. ++k;
  43. }
  44. else if(k < 0)
  45. {
  46. k = 0;
  47. }
  48. }
  49. int ident;
  50. int events;
  51. android_poll_source* source;
  52. while((ident = ALooper_pollAll(0, nullptr, &events, reinterpret_cast<void**>(&source))) >= 0)
  53. {
  54. if(source != nullptr)
  55. {
  56. source->process(g_androidApp, source);
  57. }
  58. }
  59. return Error::kNone;
  60. }
  61. void Input::moveMouseNdc(const Vec2& posNdc)
  62. {
  63. m_mousePosNdc = posNdc;
  64. }
  65. void Input::hideCursor([[maybe_unused]] Bool hide)
  66. {
  67. // do nothing
  68. }
  69. Bool Input::hasTouchDevice() const
  70. {
  71. return true;
  72. }
  73. void Input::setMouseCursor([[maybe_unused]] MouseCursor cursor)
  74. {
  75. // nothing
  76. }
  77. Error InputAndroid::initInternal()
  78. {
  79. g_androidApp->userData = this;
  80. g_androidApp->onAppCmd = [](android_app* app, int32_t cmd) {
  81. InputAndroid* self = static_cast<InputAndroid*>(app->userData);
  82. self->handleAndroidEvents(app, cmd);
  83. };
  84. g_androidApp->onInputEvent = [](android_app* app, AInputEvent* event) -> int {
  85. InputAndroid* self = static_cast<InputAndroid*>(app->userData);
  86. return self->handleAndroidInput(app, event);
  87. };
  88. return Error::kNone;
  89. }
  90. void InputAndroid::handleAndroidEvents([[maybe_unused]] android_app* app, int32_t cmd)
  91. {
  92. switch(cmd)
  93. {
  94. case APP_CMD_TERM_WINDOW:
  95. case APP_CMD_LOST_FOCUS:
  96. addEvent(InputEvent::kWindowClosed);
  97. break;
  98. }
  99. }
  100. int InputAndroid::handleAndroidInput([[maybe_unused]] android_app* app, AInputEvent* event)
  101. {
  102. const I32 type = AInputEvent_getType(event);
  103. const I32 source = AInputEvent_getSource(event);
  104. I32 handled = 0;
  105. switch(type)
  106. {
  107. case AINPUT_EVENT_TYPE_KEY:
  108. // TODO
  109. break;
  110. case AINPUT_EVENT_TYPE_MOTION:
  111. {
  112. const I32 pointer = AMotionEvent_getAction(event);
  113. const I32 action = pointer & AMOTION_EVENT_ACTION_MASK;
  114. const I32 index = (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_touchPointerPosNdc[id].x = F32(x) / F32(NativeWindow::getSingleton().getWidth()) * 2.0f - 1.0f;
  126. m_touchPointerPosNdc[id].y = -(F32(y) / F32(NativeWindow::getSingleton().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