input.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156
  1. /* -*- mode: c; tab-width: 4; c-basic-offset: 4; c-file-style: "linux" -*- */
  2. //
  3. // Copyright (c) 2009-2011, Wei Mingzhi <whistler_wmz@users.sf.net>.
  4. // Copyright (c) 2011-2017, SDLPAL development team.
  5. // All rights reserved.
  6. //
  7. // This file is part of SDLPAL.
  8. //
  9. // SDLPAL is free software: you can redistribute it and/or modify
  10. // it under the terms of the GNU General Public License as published by
  11. // the Free Software Foundation, either version 3 of the License, or
  12. // (at your option) any later version.
  13. //
  14. // This program is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. // GNU General Public License for more details.
  18. //
  19. // You should have received a copy of the GNU General Public License
  20. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. //
  22. #include "main.h"
  23. #include <math.h>
  24. volatile PALINPUTSTATE g_InputState;
  25. #if PAL_HAS_JOYSTICKS
  26. static SDL_Joystick *g_pJoy = NULL;
  27. #endif
  28. #if !SDL_VERSION_ATLEAST(2,0,0)
  29. # define SDLK_KP_1 SDLK_KP1
  30. # define SDLK_KP_2 SDLK_KP2
  31. # define SDLK_KP_3 SDLK_KP3
  32. # define SDLK_KP_4 SDLK_KP4
  33. # define SDLK_KP_5 SDLK_KP5
  34. # define SDLK_KP_6 SDLK_KP6
  35. # define SDLK_KP_7 SDLK_KP7
  36. # define SDLK_KP_8 SDLK_KP8
  37. # define SDLK_KP_9 SDLK_KP9
  38. # define SDLK_KP_0 SDLK_KP0
  39. # define SDL_JoystickNameForIndex SDL_JoystickName
  40. # define SDL_GetKeyboardState SDL_GetKeyState
  41. # define SDL_GetScancodeFromKey(x) (x)
  42. #endif
  43. BOOL g_fUseJoystick = TRUE;
  44. static void _default_init_filter() {}
  45. static int _default_input_event_filter(const SDL_Event *event, volatile PALINPUTSTATE *state) { return 0; }
  46. static void _default_input_shutdown_filter() {}
  47. static void (*input_init_filter)() = _default_init_filter;
  48. static int (*input_event_filter)(const SDL_Event *, volatile PALINPUTSTATE *) = _default_input_event_filter;
  49. static void (*input_shutdown_filter)() = _default_input_shutdown_filter;
  50. static const int g_KeyMap[][2] = {
  51. { SDLK_UP, kKeyUp },
  52. { SDLK_KP_8, kKeyUp },
  53. { SDLK_DOWN, kKeyDown },
  54. { SDLK_KP_2, kKeyDown },
  55. { SDLK_LEFT, kKeyLeft },
  56. { SDLK_KP_4, kKeyLeft },
  57. { SDLK_RIGHT, kKeyRight },
  58. { SDLK_KP_6, kKeyRight },
  59. { SDLK_ESCAPE, kKeyMenu },
  60. { SDLK_INSERT, kKeyMenu },
  61. { SDLK_LALT, kKeyMenu },
  62. { SDLK_RALT, kKeyMenu },
  63. { SDLK_KP_0, kKeyMenu },
  64. { SDLK_RETURN, kKeySearch },
  65. { SDLK_SPACE, kKeySearch },
  66. { SDLK_KP_ENTER, kKeySearch },
  67. { SDLK_LCTRL, kKeySearch },
  68. { SDLK_PAGEUP, kKeyPgUp },
  69. { SDLK_KP_9, kKeyPgUp },
  70. { SDLK_PAGEDOWN, kKeyPgDn },
  71. { SDLK_KP_3, kKeyPgDn },
  72. { SDLK_HOME, kKeyHome },
  73. { SDLK_KP_7, kKeyHome },
  74. { SDLK_END, kKeyEnd },
  75. { SDLK_KP_1, kKeyEnd },
  76. { SDLK_r, kKeyRepeat },
  77. { SDLK_a, kKeyAuto },
  78. { SDLK_d, kKeyDefend },
  79. { SDLK_e, kKeyUseItem },
  80. { SDLK_w, kKeyThrowItem },
  81. { SDLK_q, kKeyFlee },
  82. { SDLK_f, kKeyForce },
  83. { SDLK_s, kKeyStatus }
  84. };
  85. static VOID
  86. PAL_KeyDown(
  87. INT key,
  88. BOOL fRepeat
  89. )
  90. /*++
  91. Purpose:
  92. Called when user pressed a key.
  93. Parameters:
  94. [IN] key - keycode of the pressed key.
  95. Return value:
  96. None.
  97. --*/
  98. {
  99. switch (key)
  100. {
  101. case kKeyUp:
  102. if (g_InputState.dir != kDirNorth && !fRepeat)
  103. {
  104. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  105. g_InputState.dir = kDirNorth;
  106. }
  107. g_InputState.dwKeyPress |= kKeyUp;
  108. break;
  109. case kKeyDown:
  110. if (g_InputState.dir != kDirSouth && !fRepeat)
  111. {
  112. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  113. g_InputState.dir = kDirSouth;
  114. }
  115. g_InputState.dwKeyPress |= kKeyDown;
  116. break;
  117. case kKeyLeft:
  118. if (g_InputState.dir != kDirWest && !fRepeat)
  119. {
  120. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  121. g_InputState.dir = kDirWest;
  122. }
  123. g_InputState.dwKeyPress |= kKeyLeft;
  124. break;
  125. case kKeyRight:
  126. if (g_InputState.dir != kDirEast && !fRepeat)
  127. {
  128. g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir);
  129. g_InputState.dir = kDirEast;
  130. }
  131. g_InputState.dwKeyPress |= kKeyRight;
  132. break;
  133. default:
  134. g_InputState.dwKeyPress |= key;
  135. break;
  136. }
  137. }
  138. static VOID
  139. PAL_KeyUp(
  140. INT key
  141. )
  142. /*++
  143. Purpose:
  144. Called when user released a key.
  145. Parameters:
  146. [IN] key - keycode of the released key.
  147. Return value:
  148. None.
  149. --*/
  150. {
  151. switch (key)
  152. {
  153. case kKeyUp:
  154. if (g_InputState.dir == kDirNorth)
  155. {
  156. g_InputState.dir = g_InputState.prevdir;
  157. }
  158. g_InputState.prevdir = kDirUnknown;
  159. break;
  160. case kKeyDown:
  161. if (g_InputState.dir == kDirSouth)
  162. {
  163. g_InputState.dir = g_InputState.prevdir;
  164. }
  165. g_InputState.prevdir = kDirUnknown;
  166. break;
  167. case kKeyLeft:
  168. if (g_InputState.dir == kDirWest)
  169. {
  170. g_InputState.dir = g_InputState.prevdir;
  171. }
  172. g_InputState.prevdir = kDirUnknown;
  173. break;
  174. case kKeyRight:
  175. if (g_InputState.dir == kDirEast)
  176. {
  177. g_InputState.dir = g_InputState.prevdir;
  178. }
  179. g_InputState.prevdir = kDirUnknown;
  180. break;
  181. default:
  182. break;
  183. }
  184. }
  185. static VOID
  186. PAL_UpdateKeyboardState(
  187. VOID
  188. )
  189. /*++
  190. Purpose:
  191. Poll & update keyboard state.
  192. Parameters:
  193. None.
  194. Return value:
  195. None.
  196. --*/
  197. {
  198. static DWORD rgdwKeyLastTime[sizeof(g_KeyMap) / sizeof(g_KeyMap[0])] = {0};
  199. LPCBYTE keyState = (LPCBYTE)SDL_GetKeyboardState(NULL);
  200. int i;
  201. DWORD dwCurrentTime = SDL_GetTicks();
  202. for (i = 0; i < sizeof(g_KeyMap) / sizeof(g_KeyMap[0]); i++)
  203. {
  204. if (keyState[SDL_GetScancodeFromKey(g_KeyMap[i][0])])
  205. {
  206. if (dwCurrentTime > rgdwKeyLastTime[i])
  207. {
  208. PAL_KeyDown(g_KeyMap[i][1], (rgdwKeyLastTime[i] != 0));
  209. rgdwKeyLastTime[i] = dwCurrentTime + (rgdwKeyLastTime[i] == 0 ? 200 : 75);
  210. }
  211. }
  212. else
  213. {
  214. if (rgdwKeyLastTime[i] != 0)
  215. {
  216. PAL_KeyUp(g_KeyMap[i][1]);
  217. rgdwKeyLastTime[i] = 0;
  218. }
  219. }
  220. }
  221. }
  222. static VOID
  223. PAL_KeyboardEventFilter(
  224. const SDL_Event *lpEvent
  225. )
  226. /*++
  227. Purpose:
  228. Handle keyboard events.
  229. Parameters:
  230. [IN] lpEvent - pointer to the event.
  231. Return value:
  232. None.
  233. --*/
  234. {
  235. if (lpEvent->type == SDL_KEYDOWN)
  236. {
  237. //
  238. // Pressed a key
  239. //
  240. if (lpEvent->key.keysym.mod & KMOD_ALT)
  241. {
  242. if (lpEvent->key.keysym.sym == SDLK_RETURN)
  243. {
  244. //
  245. // Pressed Alt+Enter (toggle fullscreen)...
  246. //
  247. VIDEO_ToggleFullscreen();
  248. return;
  249. }
  250. else if (lpEvent->key.keysym.sym == SDLK_F4)
  251. {
  252. //
  253. // Pressed Alt+F4 (Exit program)...
  254. //
  255. PAL_Shutdown(0);
  256. }
  257. }
  258. else if (lpEvent->key.keysym.sym == SDLK_p)
  259. {
  260. VIDEO_SaveScreenshot();
  261. }
  262. }
  263. }
  264. static VOID
  265. PAL_MouseEventFilter(
  266. const SDL_Event *lpEvent
  267. )
  268. /*++
  269. Purpose:
  270. Handle mouse events.
  271. Parameters:
  272. [IN] lpEvent - pointer to the event.
  273. Return value:
  274. None.
  275. --*/
  276. {
  277. #if PAL_HAS_MOUSE
  278. static short hitTest = 0; // Double click detect;
  279. const SDL_VideoInfo *vi;
  280. double screenWidth, gridWidth;
  281. double screenHeight, gridHeight;
  282. double mx, my;
  283. double thumbx;
  284. double thumby;
  285. INT gridIndex;
  286. BOOL isLeftMouseDBClick = FALSE;
  287. BOOL isLeftMouseClick = FALSE;
  288. BOOL isRightMouseClick = FALSE;
  289. static INT lastReleaseButtonTime, lastPressButtonTime, betweenTime;
  290. static INT lastPressx = 0;
  291. static INT lastPressy = 0;
  292. static INT lastReleasex = 0;
  293. static INT lastReleasey = 0;
  294. if (lpEvent->type!= SDL_MOUSEBUTTONDOWN && lpEvent->type != SDL_MOUSEBUTTONUP)
  295. return;
  296. vi = SDL_GetVideoInfo();
  297. screenWidth = vi->current_w;
  298. screenHeight = vi->current_h;
  299. gridWidth = screenWidth / 3;
  300. gridHeight = screenHeight / 3;
  301. mx = lpEvent->button.x;
  302. my = lpEvent->button.y;
  303. thumbx = ceil(mx / gridWidth);
  304. thumby = floor(my / gridHeight);
  305. gridIndex = thumbx + thumby * 3 - 1;
  306. switch (lpEvent->type)
  307. {
  308. case SDL_MOUSEBUTTONDOWN:
  309. lastPressButtonTime = SDL_GetTicks();
  310. lastPressx = lpEvent->button.x;
  311. lastPressy = lpEvent->button.y;
  312. switch (gridIndex)
  313. {
  314. case 2:
  315. g_InputState.prevdir = g_InputState.dir;
  316. g_InputState.dir = kDirNorth;
  317. break;
  318. case 6:
  319. g_InputState.prevdir = g_InputState.dir;
  320. g_InputState.dir = kDirSouth;
  321. break;
  322. case 0:
  323. g_InputState.prevdir = g_InputState.dir;
  324. g_InputState.dir = kDirWest;
  325. break;
  326. case 8:
  327. g_InputState.prevdir = g_InputState.dir;
  328. g_InputState.dir = kDirEast;
  329. break;
  330. case 1:
  331. //g_InputState.prevdir = g_InputState.dir;
  332. //g_InputState.dir = kDirNorth;
  333. g_InputState.dwKeyPress |= kKeyUp;
  334. break;
  335. case 7:
  336. //g_InputState.prevdir = g_InputState.dir;
  337. //g_InputState.dir = kDirSouth;
  338. g_InputState.dwKeyPress |= kKeyDown;
  339. break;
  340. case 3:
  341. //g_InputState.prevdir = g_InputState.dir;
  342. //g_InputState.dir = kDirWest;
  343. g_InputState.dwKeyPress |= kKeyLeft;
  344. break;
  345. case 5:
  346. //g_InputState.prevdir = g_InputState.dir;
  347. //g_InputState.dir = kDirEast;
  348. g_InputState.dwKeyPress |= kKeyRight;
  349. break;
  350. }
  351. break;
  352. case SDL_MOUSEBUTTONUP:
  353. lastReleaseButtonTime = SDL_GetTicks();
  354. lastReleasex = lpEvent->button.x;
  355. lastReleasey = lpEvent->button.y;
  356. hitTest ++;
  357. if (abs(lastPressx - lastReleasex) < 25 &&
  358. abs(lastPressy - lastReleasey) < 25)
  359. {
  360. betweenTime = lastReleaseButtonTime - lastPressButtonTime;
  361. if (betweenTime >500)
  362. {
  363. isRightMouseClick = TRUE;
  364. }
  365. else if (betweenTime >=0)
  366. {
  367. if((betweenTime < 100) && (hitTest >= 2))
  368. {
  369. isLeftMouseClick = TRUE;
  370. hitTest = 0;
  371. }
  372. else
  373. {
  374. isLeftMouseClick = TRUE;
  375. if(betweenTime > 100)
  376. {
  377. hitTest = 0;
  378. }
  379. }
  380. }
  381. }
  382. switch (gridIndex)
  383. {
  384. case 2:
  385. if( isLeftMouseDBClick )
  386. {
  387. AUDIO_IncreaseVolume();
  388. break;
  389. }
  390. case 6:
  391. case 0:
  392. if( isLeftMouseDBClick )
  393. {
  394. AUDIO_DecreaseVolume();
  395. break;
  396. }
  397. case 7:
  398. if (isRightMouseClick) //repeat attack
  399. {
  400. g_InputState.dwKeyPress |= kKeyRepeat;
  401. break;
  402. }
  403. case 8:
  404. g_InputState.dir = kDirUnknown;
  405. g_InputState.prevdir = kDirUnknown;
  406. break;
  407. case 1:
  408. if( isRightMouseClick )
  409. {
  410. g_InputState.dwKeyPress |= kKeyForce;
  411. }
  412. break;
  413. case 3:
  414. if( isRightMouseClick )
  415. {
  416. g_InputState.dwKeyPress |= kKeyAuto;
  417. }
  418. break;
  419. case 5:
  420. if( isRightMouseClick )
  421. {
  422. g_InputState.dwKeyPress |= kKeyDefend;
  423. }
  424. break;
  425. case 4:
  426. if (isRightMouseClick) // menu
  427. {
  428. g_InputState.dwKeyPress |= kKeyMenu;
  429. }
  430. else if (isLeftMouseClick) // search
  431. {
  432. g_InputState.dwKeyPress |= kKeySearch;
  433. }
  434. break;
  435. }
  436. break;
  437. }
  438. #endif
  439. }
  440. static VOID
  441. PAL_JoystickEventFilter(
  442. const SDL_Event *lpEvent
  443. )
  444. /*++
  445. Purpose:
  446. Handle joystick events.
  447. Parameters:
  448. [IN] lpEvent - pointer to the event.
  449. Return value:
  450. None.
  451. --*/
  452. {
  453. #if PAL_HAS_JOYSTICKS
  454. switch (lpEvent->type)
  455. {
  456. case SDL_JOYAXISMOTION:
  457. //
  458. // Moved an axis on joystick
  459. //
  460. switch (lpEvent->jaxis.axis)
  461. {
  462. case 0:
  463. //
  464. // X axis
  465. //
  466. if (lpEvent->jaxis.value > 20000)
  467. {
  468. if (g_InputState.dir != kDirEast)
  469. {
  470. g_InputState.dwKeyPress |= kKeyRight;
  471. }
  472. g_InputState.prevdir = g_InputState.dir;
  473. g_InputState.dir = kDirEast;
  474. }
  475. else if (lpEvent->jaxis.value < -20000)
  476. {
  477. if (g_InputState.dir != kDirWest)
  478. {
  479. g_InputState.dwKeyPress |= kKeyLeft;
  480. }
  481. g_InputState.prevdir = g_InputState.dir;
  482. g_InputState.dir = kDirWest;
  483. }
  484. else
  485. {
  486. if (g_InputState.prevdir != kDirEast &&
  487. g_InputState.prevdir != kDirWest)
  488. {
  489. g_InputState.dir = g_InputState.prevdir;
  490. }
  491. g_InputState.prevdir = kDirUnknown;
  492. }
  493. break;
  494. case 1:
  495. //
  496. // Y axis
  497. //
  498. if (lpEvent->jaxis.value > 20000)
  499. {
  500. if (g_InputState.dir != kDirSouth)
  501. {
  502. g_InputState.dwKeyPress |= kKeyDown;
  503. }
  504. g_InputState.prevdir = g_InputState.dir;
  505. g_InputState.dir = kDirSouth;
  506. }
  507. else if (lpEvent->jaxis.value < -20000)
  508. {
  509. if (g_InputState.dir != kDirNorth)
  510. {
  511. g_InputState.dwKeyPress |= kKeyUp;
  512. }
  513. g_InputState.prevdir = g_InputState.dir;
  514. g_InputState.dir = kDirNorth;
  515. }
  516. else
  517. {
  518. if (g_InputState.prevdir != kDirNorth &&
  519. g_InputState.prevdir != kDirSouth)
  520. {
  521. g_InputState.dir = g_InputState.prevdir;
  522. }
  523. g_InputState.prevdir = kDirUnknown;
  524. }
  525. break;
  526. }
  527. break;
  528. case SDL_JOYBUTTONDOWN:
  529. //
  530. // Pressed the joystick button
  531. //
  532. switch (lpEvent->jbutton.button & 1)
  533. {
  534. case 0:
  535. g_InputState.dwKeyPress |= kKeyMenu;
  536. break;
  537. case 1:
  538. g_InputState.dwKeyPress |= kKeySearch;
  539. break;
  540. }
  541. break;
  542. }
  543. #endif
  544. }
  545. #if PAL_HAS_TOUCH
  546. #define TOUCH_NONE 0
  547. #define TOUCH_UP 1
  548. #define TOUCH_DOWN 2
  549. #define TOUCH_LEFT 3
  550. #define TOUCH_RIGHT 4
  551. #define TOUCH_BUTTON1 5
  552. #define TOUCH_BUTTON2 6
  553. #define TOUCH_BUTTON3 7
  554. #define TOUCH_BUTTON4 8
  555. static float gfTouchXMin = 0.0f;
  556. static float gfTouchXMax = 1.0f;
  557. static float gfTouchYMin = 0.0f;
  558. static float gfTouchYMax = 1.0f;
  559. static SDL_TouchID gFinger1 = -1, gFinger2 = -1;
  560. static DWORD g_dwFinger1Time = 0, g_dwFinger2Time = 0;
  561. static int g_iPrevTouch1 = TOUCH_NONE;
  562. static int g_iPrevTouch2 = TOUCH_NONE;
  563. VOID
  564. PAL_SetTouchBounds(
  565. DWORD dwScreenWidth,
  566. DWORD dwScreenHeight,
  567. SDL_Rect renderRect
  568. )
  569. {
  570. gfTouchXMin = (float)renderRect.x / dwScreenWidth;
  571. gfTouchXMax = (float)(renderRect.x + renderRect.w) / dwScreenWidth;
  572. gfTouchYMin = (float)renderRect.y / dwScreenHeight;
  573. gfTouchYMax = (float)(renderRect.y + renderRect.h) / dwScreenHeight;
  574. }
  575. static int
  576. PAL_GetTouchArea(
  577. float X,
  578. float Y
  579. )
  580. {
  581. if (X < gfTouchXMin || X > gfTouchXMax || Y < 0.5f || Y > gfTouchYMax)
  582. {
  583. //
  584. // Upper area or cropped area
  585. //
  586. return TOUCH_NONE;
  587. }
  588. else
  589. {
  590. X = (X - gfTouchXMin) / (gfTouchXMax - gfTouchXMin);
  591. Y = (Y - gfTouchYMin) / (gfTouchYMax - gfTouchYMin);
  592. }
  593. if (X < 1.0f / 3)
  594. {
  595. if (Y - 0.5f < (1.0f / 6 - fabsf(X - 1.0f / 3 / 2)) * (0.5f / (1.0f / 3)))
  596. {
  597. return TOUCH_UP;
  598. }
  599. else if (Y - 0.75f > fabsf(X - 1.0f / 3 / 2) * (0.5f / (1.0f / 3)))
  600. {
  601. return TOUCH_DOWN;
  602. }
  603. else if (X < 1.0f / 3 / 2 && fabsf(Y - 0.75f) < 0.25f - X * (0.5f / (1.0f / 3)))
  604. {
  605. return TOUCH_LEFT;
  606. }
  607. else
  608. {
  609. return TOUCH_RIGHT;
  610. }
  611. }
  612. else if (X > 1.0f - 1.0f / 3)
  613. {
  614. if (X < 1.0f - (1.0f / 3 / 2))
  615. {
  616. if (Y < 0.75f)
  617. {
  618. return TOUCH_BUTTON1;
  619. }
  620. else
  621. {
  622. return TOUCH_BUTTON3;
  623. }
  624. }
  625. else
  626. {
  627. if (Y < 0.75f)
  628. {
  629. return TOUCH_BUTTON2;
  630. }
  631. else
  632. {
  633. return TOUCH_BUTTON4;
  634. }
  635. }
  636. }
  637. else
  638. {
  639. return TOUCH_NONE;
  640. }
  641. }
  642. static VOID
  643. PAL_SetTouchAction(
  644. int area
  645. )
  646. {
  647. switch (area)
  648. {
  649. case TOUCH_UP:
  650. g_InputState.dir = kDirNorth;
  651. g_InputState.dwKeyPress |= kKeyUp;
  652. break;
  653. case TOUCH_DOWN:
  654. g_InputState.dir = kDirSouth;
  655. g_InputState.dwKeyPress |= kKeyDown;
  656. break;
  657. case TOUCH_LEFT:
  658. g_InputState.dir = kDirWest;
  659. g_InputState.dwKeyPress |= kKeyLeft;
  660. break;
  661. case TOUCH_RIGHT:
  662. g_InputState.dir = kDirEast;
  663. g_InputState.dwKeyPress |= kKeyRight;
  664. break;
  665. case TOUCH_BUTTON1:
  666. g_InputState.dwKeyPress |= kKeyForce;
  667. break;
  668. case TOUCH_BUTTON2:
  669. g_InputState.dwKeyPress |= kKeyMenu;
  670. break;
  671. case TOUCH_BUTTON3:
  672. if (gpGlobals->fInBattle)
  673. {
  674. g_InputState.dwKeyPress |= kKeyRepeat;
  675. }
  676. else
  677. {
  678. g_InputState.dwKeyPress |= kKeyUseItem;
  679. }
  680. break;
  681. case TOUCH_BUTTON4:
  682. g_InputState.dwKeyPress |= kKeySearch;
  683. break;
  684. }
  685. }
  686. static VOID
  687. PAL_UnsetTouchAction(
  688. int area
  689. )
  690. {
  691. switch (area)
  692. {
  693. case TOUCH_UP:
  694. case TOUCH_DOWN:
  695. case TOUCH_LEFT:
  696. case TOUCH_RIGHT:
  697. g_InputState.dir = kDirUnknown;
  698. break;
  699. }
  700. }
  701. static VOID
  702. PAL_TouchRepeatCheck(
  703. VOID
  704. )
  705. {
  706. if (gFinger1 != -1 && SDL_GetTicks() > g_dwFinger1Time)
  707. {
  708. PAL_UnsetTouchAction(g_iPrevTouch1);
  709. PAL_SetTouchAction(g_iPrevTouch1);
  710. g_dwFinger1Time = SDL_GetTicks() + 120;
  711. }
  712. if (gFinger2 != -1 && SDL_GetTicks() > g_dwFinger2Time)
  713. {
  714. PAL_UnsetTouchAction(g_iPrevTouch2);
  715. PAL_SetTouchAction(g_iPrevTouch2);
  716. g_dwFinger2Time = SDL_GetTicks() + 120;
  717. }
  718. }
  719. #endif
  720. static VOID
  721. PAL_TouchEventFilter(
  722. const SDL_Event *lpEvent
  723. )
  724. /*++
  725. Purpose:
  726. Handle touch events.
  727. Parameters:
  728. [IN] lpEvent - pointer to the event.
  729. Return value:
  730. None.
  731. --*/
  732. {
  733. #if PAL_HAS_TOUCH
  734. switch (lpEvent->type)
  735. {
  736. case SDL_FINGERDOWN:
  737. if (gFinger1 == -1)
  738. {
  739. int area = PAL_GetTouchArea(lpEvent->tfinger.x, lpEvent->tfinger.y);
  740. gFinger1 = lpEvent->tfinger.fingerId;
  741. g_iPrevTouch1 = area;
  742. PAL_SetTouchAction(area);
  743. g_dwFinger1Time = SDL_GetTicks() + 500;
  744. }
  745. else if (gFinger2 == -1)
  746. {
  747. int area = PAL_GetTouchArea(lpEvent->tfinger.x, lpEvent->tfinger.y);
  748. gFinger2 = lpEvent->tfinger.fingerId;
  749. g_iPrevTouch2 = area;
  750. PAL_SetTouchAction(area);
  751. g_dwFinger2Time = SDL_GetTicks() + 500;
  752. }
  753. break;
  754. case SDL_FINGERUP:
  755. if (lpEvent->tfinger.fingerId == gFinger1)
  756. {
  757. PAL_UnsetTouchAction(g_iPrevTouch1);
  758. gFinger1 = -1;
  759. g_iPrevTouch1 = TOUCH_NONE;
  760. }
  761. else if (lpEvent->tfinger.fingerId == gFinger2)
  762. {
  763. PAL_UnsetTouchAction(g_iPrevTouch2);
  764. gFinger2 = -1;
  765. g_iPrevTouch2 = TOUCH_NONE;
  766. }
  767. break;
  768. case SDL_FINGERMOTION:
  769. if (lpEvent->tfinger.fingerId == gFinger1)
  770. {
  771. int area = PAL_GetTouchArea(lpEvent->tfinger.x, lpEvent->tfinger.y);
  772. if (g_iPrevTouch1 != area && area != TOUCH_NONE)
  773. {
  774. PAL_UnsetTouchAction(g_iPrevTouch1);
  775. g_iPrevTouch1 = area;
  776. PAL_SetTouchAction(area);
  777. g_dwFinger1Time = SDL_GetTicks() + 500;
  778. }
  779. }
  780. else if (lpEvent->tfinger.fingerId == gFinger2)
  781. {
  782. int area = PAL_GetTouchArea(lpEvent->tfinger.x, lpEvent->tfinger.y);
  783. if (g_iPrevTouch2 != area && area != TOUCH_NONE)
  784. {
  785. PAL_UnsetTouchAction(g_iPrevTouch2);
  786. g_iPrevTouch2 = area;
  787. PAL_SetTouchAction(area);
  788. g_dwFinger2Time = SDL_GetTicks() + 500;
  789. }
  790. }
  791. break;
  792. }
  793. #endif
  794. }
  795. static int SDLCALL
  796. PAL_EventFilter(
  797. const SDL_Event *lpEvent
  798. )
  799. /*++
  800. Purpose:
  801. SDL event filter function. A filter to process all events.
  802. Parameters:
  803. [IN] lpEvent - pointer to the event.
  804. Return value:
  805. 1 = the event will be added to the internal queue.
  806. 0 = the event will be dropped from the queue.
  807. --*/
  808. {
  809. switch (lpEvent->type)
  810. {
  811. #if SDL_VERSION_ATLEAST(2,0,0)
  812. case SDL_WINDOWEVENT:
  813. if (lpEvent->window.event == SDL_WINDOWEVENT_RESIZED)
  814. {
  815. //
  816. // resized the window
  817. //
  818. VIDEO_Resize(lpEvent->window.data1, lpEvent->window.data2);
  819. }
  820. break;
  821. case SDL_APP_WILLENTERBACKGROUND:
  822. g_bRenderPaused = TRUE;
  823. break;
  824. case SDL_APP_DIDENTERFOREGROUND:
  825. g_bRenderPaused = FALSE;
  826. VIDEO_UpdateScreen(NULL);
  827. break;
  828. #else
  829. case SDL_VIDEORESIZE:
  830. //
  831. // resized the window
  832. //
  833. VIDEO_Resize(lpEvent->resize.w, lpEvent->resize.h);
  834. break;
  835. #endif
  836. case SDL_QUIT:
  837. //
  838. // clicked on the close button of the window. Quit immediately.
  839. //
  840. PAL_Shutdown(0);
  841. }
  842. PAL_KeyboardEventFilter(lpEvent);
  843. PAL_MouseEventFilter(lpEvent);
  844. PAL_JoystickEventFilter(lpEvent);
  845. PAL_TouchEventFilter(lpEvent);
  846. //
  847. // All events are handled here; don't put anything to the internal queue
  848. //
  849. return 0;
  850. }
  851. VOID
  852. PAL_ClearKeyState(
  853. VOID
  854. )
  855. /*++
  856. Purpose:
  857. Clear the record of pressed keys.
  858. Parameters:
  859. None.
  860. Return value:
  861. None.
  862. --*/
  863. {
  864. g_InputState.dwKeyPress = 0;
  865. }
  866. VOID
  867. PAL_InitInput(
  868. VOID
  869. )
  870. /*++
  871. Purpose:
  872. Initialize the input subsystem.
  873. Parameters:
  874. None.
  875. Return value:
  876. None.
  877. --*/
  878. {
  879. memset((void *)&g_InputState, 0, sizeof(g_InputState));
  880. g_InputState.dir = kDirUnknown;
  881. g_InputState.prevdir = kDirUnknown;
  882. //
  883. // Check for joystick
  884. //
  885. #if PAL_HAS_JOYSTICKS
  886. if (SDL_NumJoysticks() > 0 && g_fUseJoystick)
  887. {
  888. int i;
  889. for (i = 0; i < SDL_NumJoysticks(); i++)
  890. {
  891. if (PAL_IS_VALID_JOYSTICK(SDL_JoystickNameForIndex(i)))
  892. {
  893. g_pJoy = SDL_JoystickOpen(i);
  894. break;
  895. }
  896. }
  897. if (g_pJoy != NULL)
  898. {
  899. SDL_JoystickEventState(SDL_ENABLE);
  900. }
  901. }
  902. #endif
  903. input_init_filter();
  904. }
  905. VOID
  906. PAL_ShutdownInput(
  907. VOID
  908. )
  909. /*++
  910. Purpose:
  911. Shutdown the input subsystem.
  912. Parameters:
  913. None.
  914. Return value:
  915. None.
  916. --*/
  917. {
  918. #if PAL_HAS_JOYSTICKS
  919. if (g_pJoy != NULL)
  920. {
  921. SDL_JoystickClose(g_pJoy);
  922. g_pJoy = NULL;
  923. }
  924. #endif
  925. input_shutdown_filter();
  926. }
  927. static int
  928. PAL_PollEvent(
  929. SDL_Event *event
  930. )
  931. /*++
  932. Purpose:
  933. Poll and process one event.
  934. Parameters:
  935. [OUT] event - Events polled from SDL.
  936. Return value:
  937. Return value of PAL_PollEvent.
  938. --*/
  939. {
  940. SDL_Event evt;
  941. int ret = SDL_PollEvent(&evt);
  942. if (ret != 0 && !input_event_filter(&evt, &g_InputState))
  943. {
  944. PAL_EventFilter(&evt);
  945. }
  946. if (event != NULL)
  947. {
  948. *event = evt;
  949. }
  950. return ret;
  951. }
  952. VOID
  953. PAL_ProcessEvent(
  954. VOID
  955. )
  956. /*++
  957. Purpose:
  958. Process all events.
  959. Parameters:
  960. None.
  961. Return value:
  962. None.
  963. --*/
  964. {
  965. while (PAL_PollEvent(NULL));
  966. PAL_UpdateKeyboardState();
  967. #if PAL_HAS_TOUCH
  968. PAL_TouchRepeatCheck();
  969. #endif
  970. }
  971. VOID
  972. PAL_RegisterInputFilter(
  973. void (*init_filter)(),
  974. int (*event_filter)(const SDL_Event *, volatile PALINPUTSTATE *),
  975. void (*shutdown_filter)()
  976. )
  977. /*++
  978. Purpose:
  979. Register caller-defined input event filter.
  980. Parameters:
  981. [IN] init_filter - Filter that will be called inside PAL_InitInput
  982. [IN] event_filter - Filter that will be called inside PAL_PollEvent,
  983. return non-zero value from this filter disables
  984. further internal event processing.
  985. [IN] shutdown_filter - Filter that will be called inside PAL_ShutdownInput
  986. Passing NULL to either parameter means the caller does not provide such filter.
  987. Return value:
  988. None.
  989. --*/
  990. {
  991. if (init_filter)
  992. input_init_filter = init_filter;
  993. if (event_filter)
  994. input_event_filter = event_filter;
  995. if (shutdown_filter)
  996. input_shutdown_filter = shutdown_filter;
  997. }