input.c 24 KB

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