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