Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SDLSystem.cpp 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /*!
  2. * \file src/SDLSystem.cpp
  3. * \brief SDL System interface implementation
  4. *
  5. * \author Mongoose
  6. */
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <cmath>
  11. #include <assert.h>
  12. #include "SDL_opengl.h"
  13. #include "utils/math.h"
  14. #include "SDLSystem.h"
  15. SDLSystem::SDLSystem() : System() {
  16. mWindow = 0x0;
  17. mFullscreen = false;
  18. }
  19. SDLSystem::~SDLSystem() {
  20. }
  21. #ifdef FIXME
  22. void SDLSystem::bindKeyCommand(const char *cmd, int key, int event) {
  23. if (key > 255) {
  24. printf("Currently key event mapping only handles ASCII characters\n");
  25. return;
  26. }
  27. printf("Bound command '%s' -> event %i (0x%x key)\n", cmd, event, key);
  28. keyEvents[key] = event;
  29. }
  30. #endif
  31. void SDLSystem::setGrabMouse(bool on) {
  32. SDL_SetRelativeMouseMode(on ? SDL_TRUE : SDL_FALSE);
  33. if (!on)
  34. SDL_ShowCursor(1);
  35. }
  36. void SDLSystem::initVideo(unsigned int width, unsigned int height, bool fullscreen) {
  37. int flags = 0; //, x, y;
  38. assert(width > 0);
  39. assert(height > 0);
  40. // Create GL context
  41. SDL_Init(SDL_INIT_VIDEO);
  42. printf("Created OpenGL Context\n");
  43. atexit(SDL_Quit);
  44. m_width = width;
  45. m_height = height;
  46. #ifndef __APPLE__
  47. if (!m_driver || !m_driver[0] || SDL_GL_LoadLibrary(m_driver) < 0) {
  48. SDL_ClearError();
  49. // Fallback 1
  50. if (SDL_GL_LoadLibrary("libGL.so") < 0) {
  51. SDL_ClearError();
  52. // Fallback 2
  53. if (SDL_GL_LoadLibrary("libGL.so.1") < 0) {
  54. fprintf(stderr, "initVideo> SDL_GL_LoadLibrary failed!\n");
  55. fprintf(stderr, "initVideo> Error is [%s].\n", SDL_GetError());
  56. shutdown(1);
  57. }
  58. }
  59. }
  60. #endif
  61. flags |= SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
  62. mFullscreen = fullscreen;
  63. if (mFullscreen)
  64. flags |= SDL_WINDOW_FULLSCREEN;
  65. setGrabMouse(true); // Always grab mouse!
  66. SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
  67. SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
  68. SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
  69. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
  70. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  71. mWindow = SDL_CreateWindow(VERSION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
  72. width, height, flags);
  73. mGLContext = SDL_GL_CreateContext(mWindow);
  74. // Resize context
  75. resizeGL(width, height);
  76. }
  77. void SDLSystem::resize(unsigned int width, unsigned int height) {
  78. assert(width > 0);
  79. assert(height > 0);
  80. m_width = width;
  81. m_height = height;
  82. SDL_SetWindowSize(mWindow, width, height);
  83. // Resize context
  84. resizeGL(width, height);
  85. }
  86. void SDLSystem::runGame() {
  87. SDL_Event event;
  88. unsigned int mkeys, mod, key;
  89. int btn = 0;
  90. bool specialKey;
  91. for (;;) {
  92. // Pause for 10-20 ms
  93. SDL_Delay(10);
  94. while (SDL_PollEvent(&event)) {
  95. switch (event.type) {
  96. case SDL_QUIT:
  97. shutdown(0);
  98. break;
  99. case SDL_MOUSEMOTION:
  100. // Wrap motion
  101. handleMouseMotionEvent(event.motion.xrel / 2, event.motion.yrel / 2);
  102. break;
  103. case SDL_MOUSEBUTTONDOWN:
  104. case SDL_MOUSEBUTTONUP:
  105. //handleMouseEvent(event.button.button, event.button.state,
  106. // event.button.x, event.button.y);
  107. switch (event.button.button) {
  108. case SDL_BUTTON_LEFT:
  109. btn = SYS_MOUSE_LEFT;
  110. break;
  111. case SDL_BUTTON_RIGHT:
  112. btn = SYS_MOUSE_RIGHT;
  113. break;
  114. case SDL_BUTTON_MIDDLE:
  115. btn = SYS_MOUSE_MIDDLE;
  116. break;
  117. }
  118. if (event.button.state == SDL_PRESSED) {
  119. handleKeyPressEvent(btn, 0); //! \fixme mod not used
  120. } else {
  121. handleKeyReleaseEvent(btn, 0); //! \fixme mod not used
  122. }
  123. break;
  124. case SDL_KEYUP:
  125. case SDL_KEYDOWN:
  126. //SDL_GetMouseState(&x, &y); // Get cursor pos
  127. mkeys = (unsigned int)SDL_GetModState();
  128. mod = 0;
  129. if (mkeys & KMOD_LSHIFT)
  130. mod |= SYS_MOD_KEY_LSHIFT;
  131. if (mkeys & KMOD_RSHIFT)
  132. mod |= SYS_MOD_KEY_RSHIFT;
  133. if (mkeys & KMOD_LCTRL)
  134. mod |= SYS_MOD_KEY_LCTRL;
  135. if (mkeys & KMOD_RCTRL)
  136. mod |= SYS_MOD_KEY_RCTRL;
  137. if (mkeys & KMOD_LALT)
  138. mod |= SYS_MOD_KEY_LALT;
  139. if (mkeys & KMOD_RALT)
  140. mod |= SYS_MOD_KEY_RALT;
  141. if (mkeys & KMOD_LGUI)
  142. mod |= SYS_MOD_KEY_LMETA;
  143. if (mkeys & KMOD_RGUI)
  144. mod |= SYS_MOD_KEY_RMETA;
  145. key = event.key.keysym.sym;
  146. specialKey = false;
  147. switch (key) {
  148. case SDLK_F1:
  149. key = SYS_KEY_F1;
  150. specialKey = true;
  151. break;
  152. case SDLK_F2:
  153. key = SYS_KEY_F2;
  154. specialKey = true;
  155. break;
  156. case SDLK_F3:
  157. key = SYS_KEY_F3;
  158. specialKey = true;
  159. break;
  160. case SDLK_F4:
  161. key = SYS_KEY_F4;
  162. specialKey = true;
  163. break;
  164. case SDLK_F5:
  165. key = SYS_KEY_F5;
  166. specialKey = true;
  167. break;
  168. case SDLK_F6:
  169. key = SYS_KEY_F6;
  170. specialKey = true;
  171. break;
  172. case SDLK_F7:
  173. key = SYS_KEY_F7;
  174. specialKey = true;
  175. break;
  176. case SDLK_F8:
  177. key = SYS_KEY_F8;
  178. specialKey = true;
  179. break;
  180. case SDLK_F9:
  181. key = SYS_KEY_F9;
  182. specialKey = true;
  183. break;
  184. case SDLK_F10:
  185. key = SYS_KEY_F10;
  186. specialKey = true;
  187. break;
  188. case SDLK_F11:
  189. key = SYS_KEY_F11;
  190. specialKey = true;
  191. break;
  192. case SDLK_F12:
  193. key = SYS_KEY_F12;
  194. specialKey = true;
  195. break;
  196. case SDLK_UP:
  197. key = SYS_KEY_UP;
  198. specialKey = true;
  199. break;
  200. case SDLK_DOWN:
  201. key = SYS_KEY_DOWN;
  202. specialKey = true;
  203. break;
  204. case SDLK_RIGHT:
  205. key = SYS_KEY_RIGHT;
  206. specialKey = true;
  207. break;
  208. case SDLK_LEFT:
  209. key = SYS_KEY_LEFT;
  210. specialKey = true;
  211. break;
  212. case SDLK_PAGEDOWN:
  213. key = SYS_KEY_PAGEDOWN;
  214. specialKey = true;
  215. break;
  216. case SDLK_PAGEUP:
  217. key = SYS_KEY_PAGEUP;
  218. specialKey = true;
  219. break;
  220. }
  221. #ifdef __APPLE__
  222. // Handle CMD+Q to quit in all circumstances
  223. if (key == 'q') {
  224. if (mod & SYS_MOD_KEY_LMETA) {
  225. shutdown(0);
  226. }
  227. }
  228. #endif
  229. /*! \fixme Avoid passing modifers as a key, since the
  230. * consoles using this expect text characters, add unicode
  231. * support later when they're able to handle it
  232. */
  233. if (key > 255 && key < 1000) {
  234. key = 0;
  235. }
  236. if (key == mConsoleKey) {
  237. if (event.type == SDL_KEYDOWN) {
  238. mConsoleMode = !mConsoleMode;
  239. // Tmp hack
  240. handleConsoleKeyPressEvent(mConsoleKey, 0);
  241. }
  242. } else if (mConsoleMode) { // Console keying (text input)
  243. switch (event.type) {
  244. case SDL_KEYDOWN:
  245. handleConsoleKeyPressEvent(key, mod);
  246. break;
  247. default:
  248. ;
  249. }
  250. } else if (mKeyEvents[key] != 0) { // Bound key
  251. //if (key < 255 && mKeyEvents[key] != 0)
  252. key = mKeyEvents[key];
  253. switch (event.type) {
  254. case SDL_KEYDOWN:
  255. handleBoundKeyPressEvent(key);
  256. break;
  257. default:
  258. handleBoundKeyReleaseEvent(key);
  259. }
  260. } else { // 'Classic' key event handlers
  261. switch (event.type) {
  262. case SDL_KEYDOWN:
  263. handleKeyPressEvent(key, mod);
  264. break;
  265. default:
  266. handleKeyReleaseEvent(key, mod);
  267. }
  268. }
  269. break;
  270. case SDL_WINDOWEVENT:
  271. switch(event.window.event) {
  272. case SDL_WINDOWEVENT_RESIZED:
  273. resize(event.window.data1, event.window.data2);
  274. break;
  275. }
  276. break;
  277. }
  278. }
  279. // Game frame
  280. gameFrame();
  281. }
  282. }
  283. void SDLSystem::shutdown(int i) {
  284. //SDL_QuitSubSystem(SDL_OPENGL);
  285. //SDL_Quit(); // Moved to atexit() call
  286. exit(i);
  287. }
  288. void SDLSystem::toggleFullscreen() {
  289. if (mWindow) {
  290. mFullscreen = !mFullscreen;
  291. if (mFullscreen)
  292. SDL_SetWindowFullscreen(mWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
  293. else
  294. SDL_SetWindowFullscreen(mWindow, 0);
  295. }
  296. }
  297. void SDLSystem::swapBuffersGL() {
  298. SDL_GL_SwapWindow(mWindow);
  299. }