events.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #ifdef USE_SDL
  21. #include "../idlib/precompiled.h"
  22. #include "../idlib/containers/List.h"
  23. #include "../idlib/Heap.h"
  24. #include "../framework/Common.h"
  25. #include "../framework/KeyInput.h"
  26. #include "../renderer/RenderSystem.h"
  27. #include "../renderer/tr_local.h"
  28. #include "../sys/sys_public.h"
  29. #ifdef __WINDOWS__
  30. #include "win32/win_local.h"
  31. #include <SDL_syswm.h>
  32. #endif
  33. extern bool g_inputGrabbed;
  34. const char *kbdNames[] = {
  35. "english", "french", "german", "italian", "spanish", "turkish", "norwegian", NULL
  36. };
  37. idCVar in_kbd("in_kbd", "english", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT, "keyboard layout", kbdNames, idCmdSystem::ArgCompletion_String<kbdNames> );
  38. struct kbd_poll_t {
  39. int key;
  40. bool state;
  41. kbd_poll_t() {
  42. }
  43. kbd_poll_t(int k, bool s) {
  44. key = k;
  45. state = s;
  46. }
  47. };
  48. struct mouse_poll_t {
  49. int action;
  50. int value;
  51. mouse_poll_t() {
  52. }
  53. mouse_poll_t(int a, int v) {
  54. action = a;
  55. value = v;
  56. }
  57. };
  58. struct joystick_poll_t {
  59. int action;
  60. int value;
  61. joystick_poll_t() {
  62. }
  63. joystick_poll_t(int a, int v) {
  64. action = a;
  65. value = v;
  66. }
  67. };
  68. static idList<kbd_poll_t> kbd_polls;
  69. static idList<mouse_poll_t> mouse_polls;
  70. static idList<joystick_poll_t> joystick_polls;
  71. static bool buttonStates[K_LAST_KEY];
  72. static int joyAxis[MAX_JOYSTICK_AXIS];
  73. static idList<sysEvent_t> event_overflow;
  74. static byte mapkey(SDL_Keycode key) {
  75. switch (key) {
  76. case SDLK_BACKSPACE:
  77. return K_BACKSPACE;
  78. case SDLK_PAUSE:
  79. return K_PAUSE;
  80. }
  81. if (key <= SDLK_z)
  82. return key & 0xff;
  83. switch (key) {
  84. case SDLK_APPLICATION:
  85. return K_COMMAND;
  86. case SDLK_CAPSLOCK:
  87. return K_CAPSLOCK;
  88. case SDLK_SCROLLLOCK:
  89. return K_SCROLL;
  90. case SDLK_POWER:
  91. return K_POWER;
  92. case SDLK_UP:
  93. return K_UPARROW;
  94. case SDLK_DOWN:
  95. return K_DOWNARROW;
  96. case SDLK_LEFT:
  97. return K_LEFTARROW;
  98. case SDLK_RIGHT:
  99. return K_RIGHTARROW;
  100. case SDLK_LGUI:
  101. return K_LWIN;
  102. case SDLK_RGUI:
  103. return K_RWIN;
  104. case SDLK_MENU:
  105. return K_MENU;
  106. case SDLK_LALT:
  107. case SDLK_RALT:
  108. return K_ALT;
  109. case SDLK_RCTRL:
  110. case SDLK_LCTRL:
  111. return K_CTRL;
  112. case SDLK_RSHIFT:
  113. case SDLK_LSHIFT:
  114. return K_SHIFT;
  115. case SDLK_INSERT:
  116. return K_INS;
  117. case SDLK_DELETE:
  118. return K_DEL;
  119. case SDLK_PAGEDOWN:
  120. return K_PGDN;
  121. case SDLK_PAGEUP:
  122. return K_PGUP;
  123. case SDLK_HOME:
  124. return K_HOME;
  125. case SDLK_END:
  126. return K_END;
  127. case SDLK_F1:
  128. return K_F1;
  129. case SDLK_F2:
  130. return K_F2;
  131. case SDLK_F3:
  132. return K_F3;
  133. case SDLK_F4:
  134. return K_F4;
  135. case SDLK_F5:
  136. return K_F5;
  137. case SDLK_F6:
  138. return K_F6;
  139. case SDLK_F7:
  140. return K_F7;
  141. case SDLK_F8:
  142. return K_F8;
  143. case SDLK_F9:
  144. return K_F9;
  145. case SDLK_F10:
  146. return K_F10;
  147. case SDLK_F11:
  148. return K_F11;
  149. case SDLK_F12:
  150. return K_F12;
  151. // K_INVERTED_EXCLAMATION;
  152. case SDLK_F13:
  153. return K_F13;
  154. case SDLK_F14:
  155. return K_F14;
  156. case SDLK_F15:
  157. return K_F15;
  158. case SDLK_KP_7:
  159. return K_KP_HOME;
  160. case SDLK_KP_8:
  161. return K_KP_UPARROW;
  162. case SDLK_KP_9:
  163. return K_KP_PGUP;
  164. case SDLK_KP_4:
  165. return K_KP_LEFTARROW;
  166. case SDLK_KP_5:
  167. return K_KP_5;
  168. case SDLK_KP_6:
  169. return K_KP_RIGHTARROW;
  170. case SDLK_KP_1:
  171. return K_KP_END;
  172. case SDLK_KP_2:
  173. return K_KP_DOWNARROW;
  174. case SDLK_KP_3:
  175. return K_KP_PGDN;
  176. case SDLK_KP_ENTER:
  177. return K_KP_ENTER;
  178. case SDLK_KP_0:
  179. return K_KP_INS;
  180. case SDLK_KP_PERIOD:
  181. return K_KP_DEL;
  182. case SDLK_KP_DIVIDE:
  183. return K_KP_SLASH;
  184. // K_SUPERSCRIPT_TWO;
  185. case SDLK_KP_MINUS:
  186. return K_KP_MINUS;
  187. // K_ACUTE_ACCENT;
  188. case SDLK_KP_PLUS:
  189. return K_KP_PLUS;
  190. case SDLK_NUMLOCKCLEAR:
  191. return K_KP_NUMLOCK;
  192. case SDLK_KP_MULTIPLY:
  193. return K_KP_STAR;
  194. case SDLK_KP_EQUALS:
  195. return K_KP_EQUALS;
  196. // K_MASCULINE_ORDINATOR;
  197. // K_GRAVE_A;
  198. // K_AUX1;
  199. // K_CEDILLA_C;
  200. // K_GRAVE_E;
  201. // K_AUX2;
  202. // K_AUX3;
  203. // K_AUX4;
  204. // K_GRAVE_I;
  205. // K_AUX5;
  206. // K_AUX6;
  207. // K_AUX7;
  208. // K_AUX8;
  209. // K_TILDE_N;
  210. // K_GRAVE_O;
  211. // K_AUX9;
  212. // K_AUX10;
  213. // K_AUX11;
  214. // K_AUX12;
  215. // K_AUX13;
  216. // K_AUX14;
  217. // K_GRAVE_U;
  218. // K_AUX15;
  219. // K_AUX16;
  220. case SDLK_PRINTSCREEN:
  221. return K_PRINT_SCR;
  222. case SDLK_MODE:
  223. return K_RIGHT_ALT;
  224. }
  225. return 0;
  226. }
  227. static sys_jEvents mapjoybutton(SDL_GameControllerButton button) {
  228. switch (button)
  229. {
  230. case SDL_CONTROLLER_BUTTON_A:
  231. return J_ACTION1;
  232. case SDL_CONTROLLER_BUTTON_B:
  233. return J_ACTION2;
  234. case SDL_CONTROLLER_BUTTON_X:
  235. return J_ACTION3;
  236. case SDL_CONTROLLER_BUTTON_Y:
  237. return J_ACTION4;
  238. case SDL_CONTROLLER_BUTTON_BACK:
  239. return J_ACTION10;
  240. case SDL_CONTROLLER_BUTTON_GUIDE:
  241. // TODO:
  242. break;
  243. case SDL_CONTROLLER_BUTTON_START:
  244. return J_ACTION9;
  245. case SDL_CONTROLLER_BUTTON_LEFTSTICK:
  246. return J_ACTION7;
  247. case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
  248. return J_ACTION8;
  249. case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
  250. return J_ACTION5;
  251. case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
  252. return J_ACTION6;
  253. case SDL_CONTROLLER_BUTTON_DPAD_UP:
  254. return J_DPAD_UP;
  255. case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
  256. return J_DPAD_DOWN;
  257. case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
  258. return J_DPAD_LEFT;
  259. case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
  260. return J_DPAD_RIGHT;
  261. default:
  262. common->Warning("unknown game controller button %u", button);
  263. break;
  264. }
  265. return MAX_JOY_EVENT;
  266. }
  267. static sys_jEvents mapjoyaxis(SDL_GameControllerAxis axis) {
  268. switch (axis)
  269. {
  270. case SDL_CONTROLLER_AXIS_LEFTX:
  271. return J_AXIS_LEFT_X;
  272. case SDL_CONTROLLER_AXIS_LEFTY:
  273. return J_AXIS_LEFT_Y;
  274. case SDL_CONTROLLER_AXIS_RIGHTX:
  275. return J_AXIS_RIGHT_X;
  276. case SDL_CONTROLLER_AXIS_RIGHTY:
  277. return J_AXIS_RIGHT_Y;
  278. case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
  279. return J_AXIS_LEFT_TRIG;
  280. case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
  281. return J_AXIS_RIGHT_TRIG;
  282. default:
  283. common->Warning("unknown game controller axis %u", axis);
  284. break;
  285. }
  286. return J_AXIS_MAX;
  287. }
  288. static void PushConsoleEvent(const char *s) {
  289. char *b;
  290. size_t len;
  291. len = strlen(s) + 1;
  292. b = (char *)Mem_Alloc(len);
  293. strcpy(b, s);
  294. SDL_Event event;
  295. event.type = SDL_USEREVENT;
  296. event.user.code = SE_CONSOLE;
  297. event.user.data1 = (void *)len;
  298. event.user.data2 = b;
  299. SDL_PushEvent(&event);
  300. }
  301. /*
  302. =================
  303. Sys_InitInput
  304. =================
  305. */
  306. void Sys_InitInput() {
  307. kbd_polls.SetGranularity(64);
  308. mouse_polls.SetGranularity(64);
  309. joystick_polls.SetGranularity(64);
  310. event_overflow.SetGranularity(64);
  311. memset( buttonStates, 0, sizeof( buttonStates ) );
  312. memset( joyAxis, 0, sizeof( joyAxis ) );
  313. in_kbd.SetModified();
  314. const int NumJoysticks = SDL_NumJoysticks();
  315. for( int i = 0; i < NumJoysticks; ++i )
  316. {
  317. SDL_GameControllerOpen( i );
  318. }
  319. }
  320. /*
  321. =================
  322. Sys_ShutdownInput
  323. =================
  324. */
  325. void Sys_ShutdownInput() {
  326. kbd_polls.Clear();
  327. mouse_polls.Clear();
  328. joystick_polls.Clear();
  329. event_overflow.Clear();
  330. }
  331. /*
  332. ===========
  333. Sys_InitScanTable
  334. ===========
  335. */
  336. // Windows has its own version due to the tools
  337. #ifndef _WIN32
  338. void Sys_InitScanTable() {
  339. }
  340. #endif
  341. /*
  342. ===============
  343. Sys_GetConsoleKey
  344. ===============
  345. */
  346. unsigned char Sys_GetConsoleKey(bool shifted) {
  347. static unsigned char keys[2] = { '`', '~' };
  348. if (in_kbd.IsModified()) {
  349. idStr lang = in_kbd.GetString();
  350. if (lang.Length()) {
  351. if (!lang.Icmp("french")) {
  352. keys[0] = '<';
  353. keys[1] = '>';
  354. } else if (!lang.Icmp("german")) {
  355. keys[0] = '^';
  356. keys[1] = 176; // °
  357. } else if (!lang.Icmp("italian")) {
  358. keys[0] = '\\';
  359. keys[1] = '|';
  360. } else if (!lang.Icmp("spanish")) {
  361. keys[0] = 186; // º
  362. keys[1] = 170; // ª
  363. } else if (!lang.Icmp("turkish")) {
  364. keys[0] = '"';
  365. keys[1] = 233; // é
  366. } else if (!lang.Icmp("norwegian")) {
  367. keys[0] = 124; // |
  368. keys[1] = 167; // §
  369. }
  370. }
  371. in_kbd.ClearModified();
  372. }
  373. return shifted ? keys[1] : keys[0];
  374. }
  375. /*
  376. ===============
  377. Sys_MapCharForKey
  378. ===============
  379. */
  380. unsigned char Sys_MapCharForKey(int key) {
  381. return key & 0xff;
  382. }
  383. /*
  384. ===============
  385. Sys_GrabMouseCursor
  386. ===============
  387. */
  388. void Sys_GrabMouseCursor(bool grabIt) {
  389. int flags;
  390. if (grabIt)
  391. flags = GRAB_ENABLE | GRAB_HIDECURSOR;
  392. else
  393. flags = 0;
  394. GLimp_GrabInput(flags);
  395. }
  396. void PushButton( int key, bool value ) {
  397. // So we don't keep sending the same SE_KEY message over and over again
  398. if ( buttonStates[key] != value ) {
  399. buttonStates[key] = value;
  400. sysEvent_t res = { SE_KEY, key, value ? 1 : 0, 0, NULL };
  401. event_overflow.Append(res);
  402. }
  403. }
  404. /*
  405. ================
  406. Sys_GetEvent
  407. ================
  408. */
  409. sysEvent_t Sys_GetEvent() {
  410. SDL_Event ev;
  411. sysEvent_t res = { };
  412. byte key;
  413. static const sysEvent_t res_none = { SE_NONE, 0, 0, 0, NULL };
  414. // process any overflow.
  415. if (event_overflow.Num() > 0)
  416. {
  417. res = event_overflow[0];
  418. event_overflow.RemoveIndex(0);
  419. return res;
  420. }
  421. // overflow text input.
  422. static char *s = NULL;
  423. static size_t s_pos = 0;
  424. if (s) {
  425. res.evType = SE_CHAR;
  426. res.evValue = s[s_pos];
  427. s_pos++;
  428. if (!s[s_pos]) {
  429. free(s);
  430. s = NULL;
  431. s_pos = 0;
  432. }
  433. return res;
  434. }
  435. static byte c = 0;
  436. if (c) {
  437. res.evType = SE_CHAR;
  438. res.evValue = c;
  439. c = 0;
  440. return res;
  441. }
  442. bool getNext = true;
  443. while (SDL_PollEvent(&ev) && getNext) {
  444. getNext = false;
  445. switch (ev.type) {
  446. #ifdef __WINDOWS__ // on windows we need to grab the hwnd.
  447. case SDL_SYSWMEVENT:
  448. if (win32.hWnd == NULL)
  449. {
  450. win32.hWnd = ev.syswm.msg->msg.win.hwnd;
  451. }
  452. getNext = true; // try to get a decent event.
  453. break;
  454. #endif
  455. case SDL_WINDOWEVENT:
  456. switch (ev.window.event) {
  457. case SDL_WINDOWEVENT_FOCUS_GAINED: {
  458. // unset modifier, in case alt-tab was used to leave window and ALT is still set
  459. // as that can cause fullscreen-toggling when pressing enter...
  460. SDL_Keymod currentmod = SDL_GetModState();
  461. int newmod = KMOD_NONE;
  462. if (currentmod & KMOD_CAPS) // preserve capslock
  463. newmod |= KMOD_CAPS;
  464. SDL_SetModState((SDL_Keymod)newmod);
  465. } // new context because visual studio complains about newmod and currentmod not initialized because of the case SDL_WINDOWEVENT_FOCUS_LOST
  466. GLimp_GrabInput(GRAB_ENABLE | GRAB_REENABLE | GRAB_HIDECURSOR);
  467. break;
  468. case SDL_WINDOWEVENT_FOCUS_LOST:
  469. GLimp_GrabInput(0);
  470. break;
  471. }
  472. return res_none;
  473. case SDL_KEYDOWN:
  474. if (ev.key.keysym.sym == SDLK_RETURN && (ev.key.keysym.mod & KMOD_ALT) > 0) {
  475. cvarSystem->SetCVarBool("r_fullscreen", !renderSystem->IsFullScreen());
  476. PushConsoleEvent("vid_restart");
  477. return res_none;
  478. }
  479. // fall through
  480. case SDL_KEYUP:
  481. key = mapkey(ev.key.keysym.sym);
  482. if(!key) {
  483. if (ev.key.keysym.scancode == SDL_SCANCODE_GRAVE) {
  484. key = Sys_GetConsoleKey(true);
  485. } else {
  486. if (ev.type == SDL_KEYDOWN) {
  487. common->Warning("unmapped SDL key %d", ev.key.keysym.sym);
  488. getNext = true; // try to get a decent event.
  489. break;
  490. }
  491. }
  492. }
  493. res.evType = SE_KEY;
  494. res.evValue = key;
  495. res.evValue2 = ev.key.state == SDL_PRESSED ? 1 : 0;
  496. kbd_polls.Append(kbd_poll_t(key, ev.key.state == SDL_PRESSED));
  497. if ( (key == K_BACKSPACE && ev.key.state == SDL_PRESSED)
  498. || SDL_GetEventState(SDL_TEXTINPUT) == SDL_DISABLE)
  499. c = key;
  500. return res;
  501. case SDL_TEXTINPUT:
  502. if (ev.text.text && *ev.text.text) {
  503. res.evType = SE_CHAR;
  504. res.evValue = *ev.text.text;
  505. // if there are more characters hold onto them for later events.
  506. if (ev.text.text[1] != 0)
  507. s = strdup(ev.text.text+1);
  508. return res;
  509. }
  510. getNext = true; // try to get a decent event.
  511. break;
  512. case SDL_MOUSEMOTION:
  513. if (g_inputGrabbed)
  514. {
  515. res.evType = SE_MOUSE;
  516. res.evValue = ev.motion.xrel;
  517. res.evValue2 = ev.motion.yrel;
  518. mouse_polls.Append(mouse_poll_t(M_DELTAX, ev.motion.xrel));
  519. mouse_polls.Append(mouse_poll_t(M_DELTAY, ev.motion.yrel));
  520. return res;
  521. }
  522. getNext = true;
  523. break;
  524. case SDL_MOUSEWHEEL:
  525. if (g_inputGrabbed)
  526. {
  527. res.evType = SE_KEY;
  528. if (ev.wheel.y > 0) {
  529. res.evValue = K_MWHEELUP;
  530. mouse_polls.Append(mouse_poll_t(M_DELTAZ, 1));
  531. } else {
  532. res.evValue = K_MWHEELDOWN;
  533. mouse_polls.Append(mouse_poll_t(M_DELTAZ, -1));
  534. }
  535. res.evValue2 = 1;
  536. return res;
  537. }
  538. getNext = true;
  539. break;
  540. case SDL_MOUSEBUTTONDOWN:
  541. case SDL_MOUSEBUTTONUP:
  542. if (g_inputGrabbed)
  543. {
  544. res.evType = SE_KEY;
  545. switch (ev.button.button) {
  546. case SDL_BUTTON_LEFT:
  547. res.evValue = K_MOUSE1;
  548. mouse_polls.Append(mouse_poll_t(M_ACTION1, ev.button.state == SDL_PRESSED ? 1 : 0));
  549. break;
  550. case SDL_BUTTON_MIDDLE:
  551. res.evValue = K_MOUSE3;
  552. mouse_polls.Append(mouse_poll_t(M_ACTION3, ev.button.state == SDL_PRESSED ? 1 : 0));
  553. break;
  554. case SDL_BUTTON_RIGHT:
  555. res.evValue = K_MOUSE2;
  556. mouse_polls.Append(mouse_poll_t(M_ACTION2, ev.button.state == SDL_PRESSED ? 1 : 0));
  557. break;
  558. }
  559. res.evValue2 = ev.button.state == SDL_PRESSED ? 1 : 0;
  560. return res;
  561. }
  562. getNext = true;
  563. break;
  564. case SDL_CONTROLLERBUTTONDOWN:
  565. case SDL_CONTROLLERBUTTONUP:
  566. {
  567. sys_jEvents jEvent = mapjoybutton( (SDL_GameControllerButton)ev.cbutton.button);
  568. joystick_polls.Append(joystick_poll_t( jEvent,
  569. ev.cbutton.state == SDL_PRESSED ? 1 : 0) );
  570. res.evType = SE_KEY;
  571. res.evValue2 = ev.cbutton.state == SDL_PRESSED ? 1 : 0;
  572. if ( ( jEvent >= J_ACTION1 ) && ( jEvent <= J_ACTION_MAX ) ) {
  573. res.evValue = K_JOY1 + ( jEvent - J_ACTION1 );
  574. return res;
  575. } else if ( ( jEvent >= J_DPAD_UP ) && ( jEvent <= J_DPAD_RIGHT ) ) {
  576. res.evValue = K_JOY_DPAD_UP + ( jEvent - J_DPAD_UP );
  577. return res;
  578. }
  579. getNext = true; // try to get a decent event.
  580. }
  581. break;
  582. case SDL_CONTROLLERAXISMOTION:
  583. {
  584. const int range = 16384;
  585. sys_jEvents jEvent = mapjoyaxis( (SDL_GameControllerAxis)ev.caxis.axis);
  586. joystick_polls.Append(joystick_poll_t( jEvent, ev.caxis.value) );
  587. if ( jEvent == J_AXIS_LEFT_X ) {
  588. PushButton( K_JOY_STICK1_LEFT, ( ev.caxis.value < -range ) );
  589. PushButton( K_JOY_STICK1_RIGHT, ( ev.caxis.value > range ) );
  590. } else if ( jEvent == J_AXIS_LEFT_Y ) {
  591. PushButton( K_JOY_STICK1_UP, ( ev.caxis.value < -range ) );
  592. PushButton( K_JOY_STICK1_DOWN, ( ev.caxis.value > range ) );
  593. } else if ( jEvent == J_AXIS_RIGHT_X ) {
  594. PushButton( K_JOY_STICK2_LEFT, ( ev.caxis.value < -range ) );
  595. PushButton( K_JOY_STICK2_RIGHT, ( ev.caxis.value > range ) );
  596. } else if ( jEvent == J_AXIS_RIGHT_Y ) {
  597. PushButton( K_JOY_STICK2_UP, ( ev.caxis.value < -range ) );
  598. PushButton( K_JOY_STICK2_DOWN, ( ev.caxis.value > range ) );
  599. } else if ( jEvent == J_AXIS_LEFT_TRIG ) {
  600. PushButton( K_JOY_TRIGGER1, ( ev.caxis.value > range ) );
  601. } else if ( jEvent == J_AXIS_RIGHT_TRIG ) {
  602. PushButton( K_JOY_TRIGGER2, ( ev.caxis.value > range ) );
  603. }
  604. if ( jEvent >= J_AXIS_MIN && jEvent <= J_AXIS_MAX ) {
  605. int axis = jEvent - J_AXIS_MIN;
  606. int percent = ( ev.caxis.value * 16 ) / range;
  607. if ( joyAxis[axis] != percent ) {
  608. joyAxis[axis] = percent;
  609. res.evType = SE_JOYSTICK;
  610. res.evValue = axis;
  611. res.evValue2 = percent;
  612. return res;
  613. }
  614. }
  615. getNext = true; // try to get a decent event.
  616. }
  617. break;
  618. case SDL_JOYDEVICEADDED:
  619. SDL_GameControllerOpen( ev.jdevice.which );
  620. // TODO: hot swapping maybe.
  621. //lbOnControllerPlugIn(event.jdevice.which);
  622. break;
  623. case SDL_JOYDEVICEREMOVED:
  624. // TODO: hot swapping maybe.
  625. //lbOnControllerUnPlug(event.jdevice.which);
  626. break;
  627. case SDL_QUIT:
  628. PushConsoleEvent("quit");
  629. return res_none;
  630. case SDL_USEREVENT:
  631. switch (ev.user.code) {
  632. case SE_CONSOLE:
  633. res.evType = SE_CONSOLE;
  634. res.evPtrLength = (intptr_t)ev.user.data1;
  635. res.evPtr = ev.user.data2;
  636. return res;
  637. default:
  638. common->Warning("unknown user event %u", ev.user.code);
  639. getNext = true; // try to get a decent event.
  640. break;
  641. }
  642. default:
  643. getNext = true; // try to get a decent event.
  644. break;
  645. }
  646. }
  647. return res_none;
  648. }
  649. /*
  650. ================
  651. Sys_ClearEvents
  652. ================
  653. */
  654. void Sys_ClearEvents() {
  655. SDL_Event ev;
  656. while (SDL_PollEvent(&ev))
  657. ;
  658. kbd_polls.SetNum(0, false);
  659. mouse_polls.SetNum(0, false);
  660. joystick_polls.SetNum(0, false);
  661. memset( buttonStates, 0, sizeof( buttonStates ) );
  662. memset( joyAxis, 0, sizeof( joyAxis ) );
  663. event_overflow.SetNum(0, false);
  664. }
  665. /*
  666. ================
  667. Sys_GenerateEvents
  668. ================
  669. */
  670. void Sys_GenerateEvents() {
  671. char *s = Sys_ConsoleInput();
  672. if (s)
  673. PushConsoleEvent(s);
  674. SDL_PumpEvents();
  675. }
  676. /*
  677. ================
  678. Sys_PollKeyboardInputEvents
  679. ================
  680. */
  681. int Sys_PollKeyboardInputEvents() {
  682. return kbd_polls.Num();
  683. }
  684. /*
  685. ================
  686. Sys_ReturnKeyboardInputEvent
  687. ================
  688. */
  689. int Sys_ReturnKeyboardInputEvent(const int n, int &key, bool &state) {
  690. if (n >= kbd_polls.Num())
  691. return 0;
  692. key = kbd_polls[n].key;
  693. state = kbd_polls[n].state;
  694. return 1;
  695. }
  696. /*
  697. ================
  698. Sys_EndKeyboardInputEvents
  699. ================
  700. */
  701. void Sys_EndKeyboardInputEvents() {
  702. kbd_polls.SetNum(0, false);
  703. }
  704. /*
  705. ================
  706. Sys_PollMouseInputEvents
  707. ================
  708. */
  709. int Sys_PollMouseInputEvents() {
  710. return mouse_polls.Num();
  711. }
  712. /*
  713. ================
  714. Sys_ReturnMouseInputEvent
  715. ================
  716. */
  717. int Sys_ReturnMouseInputEvent(const int n, int &action, int &value) {
  718. if (n >= mouse_polls.Num())
  719. return 0;
  720. action = mouse_polls[n].action;
  721. value = mouse_polls[n].value;
  722. return 1;
  723. }
  724. /*
  725. ================
  726. Sys_EndMouseInputEvents
  727. ================
  728. */
  729. void Sys_EndMouseInputEvents() {
  730. mouse_polls.SetNum(0, false);
  731. }
  732. /*
  733. ================
  734. Joystick Input Methods
  735. ================
  736. */
  737. void Sys_SetRumble( int device, int low, int hi ) {
  738. // TODO: support multiple controllers.
  739. assert(device == 0);
  740. // TODO: support rumble maybe.
  741. assert(0);
  742. }
  743. int Sys_PollJoystickInputEvents( int deviceNum ) {
  744. // TODO: support multiple controllers.
  745. assert(deviceNum == 0);
  746. return joystick_polls.Num();
  747. }
  748. int Sys_ReturnJoystickInputEvent( const int n, int &action, int &value ) {
  749. if (n >= joystick_polls.Num())
  750. return 0;
  751. action = joystick_polls[n].action;
  752. value = joystick_polls[n].value;
  753. return 1;
  754. }
  755. void Sys_EndJoystickInputEvents() {
  756. joystick_polls.SetNum(0, false);
  757. }
  758. #endif