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 12KB

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