InputSdl.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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/Input.h>
  6. #include <AnKi/Window/InputSdl.h>
  7. #include <AnKi/Window/NativeWindowSdl.h>
  8. #include <AnKi/Util/Logger.h>
  9. #include <SDL3/SDL.h>
  10. namespace anki {
  11. static MouseButton sdlMouseButtonToAnKi(const U32 sdl)
  12. {
  13. MouseButton out = MouseButton::kCount;
  14. switch(sdl)
  15. {
  16. case SDL_BUTTON_LEFT:
  17. out = MouseButton::kLeft;
  18. break;
  19. case SDL_BUTTON_RIGHT:
  20. out = MouseButton::kRight;
  21. break;
  22. case SDL_BUTTON_MIDDLE:
  23. out = MouseButton::kMiddle;
  24. break;
  25. }
  26. return out;
  27. }
  28. static KeyCode sdlKeytoAnKi(SDL_Keycode sdlk)
  29. {
  30. KeyCode akk = KeyCode::kUnknown;
  31. switch(sdlk)
  32. {
  33. #define ANKI_KEY_CODE(ak, sdl) \
  34. case SDLK_##sdl: \
  35. akk = KeyCode::k##ak; \
  36. break;
  37. #include <AnKi/Window/KeyCode.def.h>
  38. #undef ANKI_KEY_CODE
  39. }
  40. ANKI_ASSERT(akk != KeyCode::kUnknown);
  41. return akk;
  42. }
  43. template<>
  44. template<>
  45. Input& MakeSingletonPtr<Input>::allocateSingleton<>()
  46. {
  47. ANKI_ASSERT(m_global == nullptr);
  48. m_global = new InputSdl;
  49. #if ANKI_ASSERTIONS_ENABLED
  50. ++g_singletonsAllocated;
  51. #endif
  52. return *m_global;
  53. }
  54. template<>
  55. void MakeSingletonPtr<Input>::freeSingleton()
  56. {
  57. if(m_global)
  58. {
  59. delete static_cast<InputSdl*>(m_global);
  60. m_global = nullptr;
  61. #if ANKI_ASSERTIONS_ENABLED
  62. --g_singletonsAllocated;
  63. #endif
  64. }
  65. }
  66. Error Input::init()
  67. {
  68. return static_cast<InputSdl*>(this)->initInternal();
  69. }
  70. Error Input::handleEvents()
  71. {
  72. InputSdl* self = static_cast<InputSdl*>(this);
  73. return self->handleEventsInternal();
  74. }
  75. void Input::moveCursor(const Vec2& pos)
  76. {
  77. if(pos != m_mousePosNdc)
  78. {
  79. const F32 x = F32(NativeWindow::getSingleton().getWidth()) * (pos.x() * 0.5f + 0.5f);
  80. const F32 y = F32(NativeWindow::getSingleton().getHeight()) * (-pos.y() * 0.5f + 0.5f);
  81. SDL_WarpMouseInWindow(static_cast<NativeWindowSdl&>(NativeWindow::getSingleton()).m_sdlWindow, x, y);
  82. // SDL doesn't generate a SDL_MOUSEMOTION event if the cursor is outside the window. Push that event
  83. SDL_Event event;
  84. event.type = SDL_EVENT_MOUSE_MOTION;
  85. event.button.x = x;
  86. event.button.y = y;
  87. SDL_PushEvent(&event);
  88. }
  89. }
  90. void Input::hideCursor(Bool hide)
  91. {
  92. if(hide)
  93. {
  94. if(!SDL_HideCursor())
  95. {
  96. ANKI_WIND_LOGE("SDL_HideCursor() failed: %s", SDL_GetError());
  97. }
  98. }
  99. else
  100. {
  101. if(!SDL_ShowCursor())
  102. {
  103. ANKI_WIND_LOGE("SDL_ShowCursor() failed: %s", SDL_GetError());
  104. }
  105. }
  106. }
  107. Bool Input::hasTouchDevice() const
  108. {
  109. return false;
  110. }
  111. Error InputSdl::initInternal()
  112. {
  113. // Call once to clear first events
  114. return handleEvents();
  115. }
  116. Error InputSdl::handleEventsInternal()
  117. {
  118. m_textInput[0] = '\0';
  119. // add the times a key is being pressed
  120. for(auto& k : m_keys)
  121. {
  122. if(k)
  123. {
  124. ++k;
  125. }
  126. }
  127. for(auto& k : m_mouseBtns)
  128. {
  129. if(k)
  130. {
  131. ++k;
  132. }
  133. }
  134. SDL_Event event;
  135. KeyCode akkey;
  136. if(!SDL_StartTextInput(static_cast<NativeWindowSdl&>(NativeWindow::getSingleton()).m_sdlWindow))
  137. {
  138. ANKI_WIND_LOGE("SDL_StartTextInput() failed: %s", SDL_GetError());
  139. }
  140. while(SDL_PollEvent(&event))
  141. {
  142. switch(event.type)
  143. {
  144. case SDL_EVENT_KEY_DOWN:
  145. akkey = sdlKeytoAnKi(event.key.key);
  146. m_keys[akkey] = 1;
  147. break;
  148. case SDL_EVENT_KEY_UP:
  149. akkey = sdlKeytoAnKi(event.key.key);
  150. m_keys[akkey] = 0;
  151. break;
  152. case SDL_EVENT_MOUSE_BUTTON_DOWN:
  153. {
  154. MouseButton mb = sdlMouseButtonToAnKi(event.button.button);
  155. if(mb != MouseButton::kCount)
  156. {
  157. m_mouseBtns[mb] = 1;
  158. }
  159. break;
  160. }
  161. case SDL_EVENT_MOUSE_BUTTON_UP:
  162. {
  163. MouseButton mb = sdlMouseButtonToAnKi(event.button.button);
  164. if(mb != MouseButton::kCount)
  165. {
  166. m_mouseBtns[mb] = 0;
  167. }
  168. break;
  169. }
  170. case SDL_EVENT_MOUSE_WHEEL:
  171. m_mouseBtns[MouseButton::kScrollUp] = event.wheel.y > 0.0f;
  172. m_mouseBtns[MouseButton::kScrollDown] = event.wheel.y < 0.0f;
  173. break;
  174. case SDL_EVENT_MOUSE_MOTION:
  175. m_mousePosWin.x() = U32(event.button.x);
  176. m_mousePosWin.y() = U32(event.button.y);
  177. m_mousePosNdc.x() = F32(event.button.x) / F32(NativeWindow::getSingleton().getWidth()) * 2.0f - 1.0f;
  178. m_mousePosNdc.y() = -(F32(event.button.y) / F32(NativeWindow::getSingleton().getHeight()) * 2.0f - 1.0f);
  179. break;
  180. case SDL_EVENT_QUIT:
  181. addEvent(InputEvent::kWindowClosed);
  182. break;
  183. case SDL_EVENT_TEXT_INPUT:
  184. std::strncpy(&m_textInput[0], event.text.text, m_textInput.getSize() - 1);
  185. break;
  186. }
  187. } // end while events
  188. // Lock mouse
  189. if(m_lockCurs)
  190. {
  191. moveCursor(Vec2(0.0));
  192. }
  193. return Error::kNone;
  194. }
  195. } // end namespace anki