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

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