225 行
5.4 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #if defined USE_SDL
  14. # if defined HAVE_SDL_SDL_H
  15. # include <SDL/SDL.h>
  16. # else
  17. # include <SDL.h>
  18. # endif
  19. #endif
  20. #include "core.h"
  21. #include "sdlinput.h"
  22. /* We force joystick polling because no events are received when
  23. * there is no SDL display (eg. on the Raspberry Pi). */
  24. #define SDL_FORCE_POLL_JOYSTICK 1
  25. namespace lol
  26. {
  27. /*
  28. * SDL Input implementation class
  29. */
  30. class SdlInputData
  31. {
  32. friend class SdlInput;
  33. private:
  34. void Tick(float seconds);
  35. static ivec2 GetMousePos();
  36. #if defined USE_SDL
  37. Array<SDL_Joystick *, Stick *> m_joysticks;
  38. #endif
  39. };
  40. /*
  41. * Public SdlInput class
  42. */
  43. SdlInput::SdlInput()
  44. : m_data(new SdlInputData())
  45. {
  46. #if defined USE_SDL
  47. /* Enable Unicode translation of keyboard events */
  48. SDL_EnableUNICODE(1);
  49. SDL_Init(SDL_INIT_TIMER | SDL_INIT_JOYSTICK);
  50. # if SDL_FORCE_POLL_JOYSTICK
  51. SDL_JoystickEventState(SDL_QUERY);
  52. # else
  53. SDL_JoystickEventState(SDL_ENABLE);
  54. # endif
  55. /* Register all the joysticks we can find, and let the input
  56. * system decide what it wants to track. */
  57. for (int i = 0; i < SDL_NumJoysticks(); i++)
  58. {
  59. SDL_Joystick *sdlstick = SDL_JoystickOpen(i);
  60. /* Blacklist some devices:
  61. * - HDAPS, it's not a real joystick.
  62. * - X360 controllers, Xinput handles them better since
  63. * it won't think there is only one trigger axis. */
  64. char const *name = SDL_JoystickName(i);
  65. if (strstr(name, "HDAPS")
  66. # if defined USE_XINPUT
  67. || strstr(name, "XBOX 360 For Windows")
  68. # endif
  69. || false)
  70. {
  71. SDL_JoystickClose(sdlstick);
  72. continue;
  73. }
  74. Stick *stick = Input::CreateStick();
  75. stick->SetAxisCount(SDL_JoystickNumAxes(sdlstick));
  76. stick->SetButtonCount(SDL_JoystickNumButtons(sdlstick));
  77. /* It's possible to remap axes */
  78. //stick->RemapAxis(4, 2);
  79. //stick->RemapAxis(2, 4);
  80. m_data->m_joysticks.Push(sdlstick, stick);
  81. }
  82. #endif
  83. m_gamegroup = GAMEGROUP_BEFORE;
  84. }
  85. SdlInput::~SdlInput()
  86. {
  87. #if defined USE_SDL
  88. /* Unregister all the joysticks we added */
  89. while (m_data->m_joysticks.Count())
  90. {
  91. SDL_JoystickClose(m_data->m_joysticks[0].m1);
  92. Input::DestroyStick(m_data->m_joysticks[0].m2);
  93. m_data->m_joysticks.Remove(0);
  94. }
  95. #endif
  96. delete m_data;
  97. }
  98. void SdlInput::TickGame(float seconds)
  99. {
  100. Entity::TickGame(seconds);
  101. #if !defined _WIN32
  102. m_data->Tick(seconds);
  103. #endif
  104. }
  105. void SdlInput::TickDraw(float seconds)
  106. {
  107. Entity::TickDraw(seconds);
  108. #if defined _WIN32
  109. m_data->Tick(seconds);
  110. #endif
  111. }
  112. void SdlInputData::Tick(float seconds)
  113. {
  114. #if defined USE_SDL
  115. /* Handle mouse input */
  116. ivec2 mouse = SdlInputData::GetMousePos();;
  117. Input::SetMousePos(mouse);
  118. # if SDL_FORCE_POLL_JOYSTICK
  119. /* Pump all joystick events because no event is coming to us. */
  120. SDL_JoystickUpdate();
  121. for (int j = 0; j < m_joysticks.Count(); j++)
  122. {
  123. for (int i = 0; i < SDL_JoystickNumButtons(m_joysticks[j].m1); i++)
  124. m_joysticks[j].m2->SetButton(i, SDL_JoystickGetButton(m_joysticks[j].m1, i));
  125. for (int i = 0; i < SDL_JoystickNumAxes(m_joysticks[j].m1); i++)
  126. m_joysticks[j].m2->SetAxis(i, (float)SDL_JoystickGetAxis(m_joysticks[j].m1, i) / 32768.f);
  127. }
  128. # endif
  129. /* Handle keyboard and WM events */
  130. SDL_Event event;
  131. while (SDL_PollEvent(&event))
  132. {
  133. switch (event.type)
  134. {
  135. case SDL_QUIT:
  136. Ticker::Shutdown();
  137. break;
  138. #if 0
  139. case SDL_KEYDOWN:
  140. if (event.key.keysym.unicode)
  141. fprintf(stderr, "%c (0x%04X)\n", event.key.keysym.unicode, event.key.keysym.unicode);
  142. break;
  143. #endif
  144. case SDL_MOUSEBUTTONDOWN:
  145. case SDL_MOUSEBUTTONUP:
  146. {
  147. ivec2 newmouse = SdlInputData::GetMousePos();
  148. if (newmouse != mouse)
  149. Input::SetMousePos(mouse = newmouse);
  150. if (event.type == SDL_MOUSEBUTTONDOWN)
  151. Input::SetMouseButton(event.button.button - 1);
  152. else
  153. Input::UnsetMouseButton(event.button.button - 1);
  154. break;
  155. }
  156. # if !SDL_FORCE_POLL_JOYSTICK
  157. case SDL_JOYAXISMOTION:
  158. m_joysticks[event.jaxis.which].m2->SetAxis(event.jaxis.axis, (float)event.jaxis.value / 32768.f);
  159. break;
  160. case SDL_JOYBUTTONUP:
  161. case SDL_JOYBUTTONDOWN:
  162. m_joysticks[event.jbutton.which].m2->SetButton(event.jbutton.button, event.jbutton.state);
  163. break;
  164. # endif
  165. }
  166. }
  167. /* Send the whole keyboard state to the input system */
  168. #if 0
  169. Uint8 *keystate = SDL_GetKeyState(nullptr);
  170. for (int i = 0; i < 256; i++)
  171. if (keystate[i])
  172. Input::KeyPressed(i, seconds);
  173. #else
  174. UNUSED(seconds);
  175. #endif
  176. #endif
  177. }
  178. ivec2 SdlInputData::GetMousePos()
  179. {
  180. ivec2 ret(-1, -1);
  181. #if defined USE_SDL
  182. if (SDL_GetAppState() & SDL_APPMOUSEFOCUS)
  183. {
  184. SDL_GetMouseState(&ret.x, &ret.y);
  185. ret.y = Video::GetSize().y - 1 - ret.y;
  186. }
  187. #endif
  188. return ret;
  189. }
  190. } /* namespace lol */