InputSettingsDlg.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. // InputSettingsDlg.cpp
  19. // Project: Nostril (aka Postal)
  20. //
  21. // History:
  22. // 07/03/97 JMI Started.
  23. //
  24. // 07/03/97 JMI Checking in for work at home.
  25. //
  26. // 07/04/97 JMI Added a whole fancy (in that it's quite simple) way of
  27. // doing all the settings from one dialog with a scroll view
  28. // (a transparent listbox) but having them call together
  29. // makes the interface clunky for the mouse and the joystick.
  30. // So I'm checking this in to have it but I plan to rewrite
  31. // more the way Mike originally pictured which, as it turns
  32. // out, will probably be rather simple via the menus combined
  33. // with the current way of getting the input.
  34. //
  35. // 07/06/97 JMI Added new version that uses the menu system for most
  36. // of the interface.
  37. // Also, changed m_asPlayButtons to m_asPlayMouseButtons.
  38. // Removed EditKeySettings() and EditMouseSetings().
  39. //
  40. // 07/07/97 JMI Now checks to make sure the listen mode hasn't been
  41. // cancelled before listening for input in ListenForInput().
  42. //
  43. // 07/07/97 JMI Now InputSettingsDlg_InitMenu() sets up the 'Go back'
  44. // (cancel) menu item no matter what so that, if it aborts
  45. // the menu for some reason, the menu system knows how to
  46. // go back to the previous.
  47. //
  48. // 07/18/97 JMI Got rid of bogus immitation PlaySample functions.
  49. // Now there is one PlaySample() function. Also, you now
  50. // MUST specify a category and you don't have to specify a
  51. // SoundInstance ptr to specify a volume.
  52. //
  53. // 07/21/97 JMI Was not setting the default GUIs' font. This implied
  54. // it was relying on other things to set this. Since this
  55. // can feasibly no longer happen before this menu/dlg comes
  56. // up, it now has to set the the font itself.
  57. //
  58. // 08/10/97 JMI Now sets sEnabled in each dynamically created menu item.
  59. // Also, ASSERTs if not enough menu items.
  60. //
  61. // 08/17/97 MJR Now uses g_resmgrShell to load its gui item.
  62. //
  63. // 08/18/97 JMI Added ms_au8UnmappableKeys[] for the keys that the user
  64. // is not allowed to map to.
  65. //
  66. // 08/21/97 JMI Changed call to Update() to UpdateSystem() and occurrences
  67. // of rspUpdateDisplay() to UpdateDisplay().
  68. //
  69. // 08/22/97 JMI Changed calls to UpdateDisplay() back to rspUpdateDisplay()
  70. // since we no longer need UpdateDisplay() now that we are
  71. // using rspLock/Unlock* functions properly.
  72. //
  73. // 08/27/97 JMI Now uses g_fontPostal instead of g_fontBig.
  74. //
  75. // 08/27/97 JMI Now uses g_fontBig instead of g_fontPostal.
  76. //
  77. // 08/27/97 JMI Now does not actually create a back item but sets the
  78. // cancel item to just beyond the last item.
  79. //
  80. // 08/27/97 JMI The program no longer sets the text fore and shadow
  81. // colors (also does not set the shadow effect). Instead
  82. // uses all Artie's settings.
  83. //
  84. // 09/26/97 JMI Now uses the 'Restore defaults' string from localize.
  85. //
  86. // 10/10/97 JMI Filled in portions that poll joystick (since no event
  87. // driven stuff is yet available).
  88. //
  89. // 11/05/97 JMI Converted to new joystick API.
  90. //
  91. //////////////////////////////////////////////////////////////////////////////
  92. //
  93. // Deals with input settings dialogs. There is an interface for both the
  94. // keyboard and mouse dialogs that deals heavily with user input, and GUI
  95. // output.
  96. //
  97. //////////////////////////////////////////////////////////////////////////////
  98. //////////////////////////////////////////////////////////////////////////////
  99. // C Headers -- Must be included before RSPiX.h b/c RSPiX utilizes SHMalloc.
  100. //////////////////////////////////////////////////////////////////////////////
  101. ///////////////////////////////////////////////////////////////////////////////
  102. // RSPiX Headers.
  103. ///////////////////////////////////////////////////////////////////////////////
  104. #include "RSPiX.h"
  105. #include "game.h"
  106. #include "update.h"
  107. #include "InputSettings.h"
  108. #include "input.h"
  109. #include "keys.h"
  110. #include "menus.h"
  111. #include "InputSettingsDlg.h"
  112. #include "CompileOptions.h" // For ALLOW_JOYSTICK macro.
  113. //////////////////////////////////////////////////////////////////////////////
  114. // Module specific macros.
  115. //////////////////////////////////////////////////////////////////////////////
  116. // Determines the number of elements in the passed array at compile time.
  117. #define NUM_ELEMENTS(a) (sizeof(a) / sizeof(a[0]) )
  118. #define INPUT_ITEM_GUI "menu/InputItm.gui"
  119. #define TEXT_LISTEN_COLOR 251
  120. // How often to flash in ms.
  121. #define FLASH_TIMEOUT 250
  122. #define FONT_HEIGHT 15
  123. //////////////////////////////////////////////////////////////////////////////
  124. // Module specific typedefs.
  125. //////////////////////////////////////////////////////////////////////////////
  126. //////////////////////////////////////////////////////////////////////////////
  127. // Module specific (static) variables / Instantiate class statics.
  128. //////////////////////////////////////////////////////////////////////////////
  129. static bool ms_bListenForInput = false; // true, when listening for input
  130. // to set for current input function.
  131. static U32 ms_u32OrigTextColor;
  132. static bool ms_bMenuDone = false; // true, when the current menu
  133. // is done.
  134. static short ms_sResetItem; // Index of item that restores
  135. // the default inputs.
  136. static short ms_sResetItemOld; // Index of item that restores the old default inputs.
  137. static short ms_sMouseButtons;
  138. static short ms_sJoyButtons;
  139. static long ms_lFlashTimer;
  140. // This array contains RSP_SK_* macros for the keys that should be
  141. // inaccessible to the user when it comes to mapping the input keys.
  142. // If you are adding a key to this array, PLEASE ADD THE _SK_ VERSION (not
  143. // the _GK_ version).
  144. static U8 ms_au8UnmappableKeys[] =
  145. {
  146. RSP_SK_F1, // Next level.
  147. RSP_SK_F2, // Toggle targeting.
  148. RSP_SK_F3, // XRay all.
  149. RSP_SK_F4, // Display info.
  150. RSP_SK_F5, // Mission goal.
  151. RSP_SK_F6, // Reserved for future use.
  152. RSP_SK_F7, // Reserved for future use.
  153. RSP_SK_F8, // Reserved for future use.
  154. RSP_SK_F9, // Reserved for future use.
  155. RSP_SK_F10, // Reserved for future use.
  156. RSP_SK_F11, // Show realm statistics (editor only).
  157. RSP_SK_F12, // Reserved for future use.
  158. RSP_SK_MINUS, // Reduce display area.
  159. RSP_SK_EQUALS, // Increase display area.
  160. RSP_SK_NUMPAD_MINUS, // Reduce display area.
  161. RSP_SK_NUMPAD_PLUS, // Increase display area.
  162. RSP_SK_ENTER, // Take snap shot.
  163. RSP_SK_PAUSE, // Pause the game.
  164. RSP_SK_ESCAPE, // Abort/Menu key.
  165. RSP_SK_CAPSLOCK, // Toggle Run/Walk modages.
  166. };
  167. //////////////////////////////////////////////////////////////////////////////
  168. // Module specific (static) protos.
  169. //////////////////////////////////////////////////////////////////////////////
  170. //////////////////////////////////////////////////////////////////////////////
  171. // Internal Functions.
  172. //////////////////////////////////////////////////////////////////////////////
  173. //////////////////////////////////////////////////////////////////////////////
  174. // Externally callable functions.
  175. //////////////////////////////////////////////////////////////////////////////
  176. //////////////////////////////////////////////////////////////////////////////
  177. // Called to setup an input settings menu.
  178. //////////////////////////////////////////////////////////////////////////////
  179. extern short InputSettingsDlg_InitMenu( // Returns 0 on success.
  180. Menu* pmenu) // In: Menu to setup.
  181. {
  182. short sRes = 0; // Assume success.
  183. short sInputIndex = 0; // Safety.
  184. U32* pasPlayInputs = NULL; // Input value array.
  185. char** papszInputDescriptions = NULL; // Descriptions of input values.
  186. bool bIsJoystick = false;
  187. switch (pmenu->u32Id)
  188. {
  189. case KEYBOARD_MENU_ID:
  190. // Use keys.
  191. pasPlayInputs = g_InputSettings.m_asPlayKeys;
  192. papszInputDescriptions = g_apszKeyDescriptions;
  193. break;
  194. case MOUSE_MENU_ID:
  195. // Use mouse buttons.
  196. pasPlayInputs = g_InputSettings.m_asPlayMouseButtons;
  197. papszInputDescriptions = g_apszMouseButtonDescriptions;
  198. break;
  199. case JOYSTICK_MENU_ID:
  200. // Use joy buttons.
  201. pasPlayInputs = g_InputSettings.m_asPlayJoyButtons;
  202. papszInputDescriptions = g_apszJoyButtonDescriptions;
  203. bIsJoystick = true;
  204. break;
  205. default:
  206. TRACE("InptuSettingsDlg_InitMenu(): Unsupported menu.\n");
  207. sRes = -1;
  208. break;
  209. }
  210. // Assert we have enough room for the input functions and the 'defaults' and 'back'
  211. // menu items.
  212. ASSERT(CInputSettings::NumInputFunctions < (NUM_ELEMENTS(pmenu->ami) - 2) );
  213. // Set font for GUIs' default print.
  214. // Cell height doesn't matter since it is set by the GUIs themselves.
  215. RGuiItem::ms_print.SetFont(FONT_HEIGHT, &g_fontBig);
  216. for (sInputIndex = 0; sInputIndex < CInputSettings::NumInputFunctions && sRes == 0; sInputIndex++)
  217. {
  218. // Set text describing input function for this menu item.
  219. pmenu->ami[sInputIndex].pszText = CInputSettings::ms_ainputinfo[sInputIndex].pszDescription;
  220. // Enable item.
  221. pmenu->ami[sInputIndex].sEnabled = TRUE;
  222. // Load GUI for input method description.
  223. RGuiItem* pgui;
  224. if (rspGetResourceInstance(&g_resmgrShell, INPUT_ITEM_GUI, (RTxt**)(&pgui)) == 0)
  225. {
  226. // Let the menu know about the GUI.
  227. pmenu->ami[sInputIndex].pgui = pgui;
  228. // Set the GUIs text to the corresponding input description and recompose.
  229. if (bIsJoystick)
  230. pgui->SetText("%s", papszInputDescriptions[JoyBitfieldToIndex(pasPlayInputs[sInputIndex])]);
  231. else if (pmenu->u32Id == MOUSE_MENU_ID)
  232. pgui->SetText("%s", papszInputDescriptions[MouseBitfieldToIndex(pasPlayInputs[sInputIndex])]);
  233. else
  234. pgui->SetText("%s", papszInputDescriptions[pasPlayInputs[sInputIndex]]);
  235. // Remember associated input function index.
  236. pgui->m_ulUserData = sInputIndex;
  237. // TEMP until the GUI editor can setup shadow text.
  238. // pgui->m_sTextEffects = RGuiItem::Shadow;
  239. // pgui->m_u32TextColor = GetCurrentMenuBox()->m_u32TextColor;
  240. // pgui->m_u32TextShadowColor = GetCurrentMenuBox()->m_u32TextShadowColor;
  241. // END TEMP
  242. pgui->Compose();
  243. }
  244. else
  245. {
  246. TRACE("InputSettingsDlg_InitMenu(): LoadInstantiate() failed.\n");
  247. sRes = -1;
  248. }
  249. }
  250. // Remember the reset item index.
  251. ms_sResetItem = sInputIndex;
  252. // Add reset.
  253. pmenu->ami[sInputIndex].pszText = g_pszRotationSetupMenu_RestoreDefaults;
  254. // Enable item.
  255. pmenu->ami[sInputIndex].sEnabled = TRUE;
  256. // Next item please.
  257. sInputIndex++;
  258. // Remember the reset item index.
  259. ms_sResetItemOld = sInputIndex;
  260. // Add reset.
  261. pmenu->ami[sInputIndex].pszText = g_pszRotationSetupMenu_RestoreDefaultsOld;
  262. // Enable item.
  263. pmenu->ami[sInputIndex].sEnabled = TRUE;
  264. // Next item please.
  265. sInputIndex++;
  266. // Make the back the cancel item.
  267. pmenu->menuautoitems.sCancelItem = sInputIndex;
  268. return sRes;
  269. }
  270. //////////////////////////////////////////////////////////////////////////////
  271. // Called to clean up an input settings menu.
  272. //////////////////////////////////////////////////////////////////////////////
  273. extern short InputSettingsDlg_KillMenu( // Returns 0 on success.
  274. Menu* pmenu) // In: Menu to clean up.
  275. {
  276. short sRes = 0; // Assume success.
  277. short sInputIndex;
  278. // Delete the loaded GUIs.
  279. for (sInputIndex = 0; sInputIndex < CInputSettings::NumInputFunctions && sRes == 0; sInputIndex++)
  280. {
  281. // Clean up the GUI.
  282. rspReleaseResourceInstance(&g_resmgrShell, &pmenu->ami[sInputIndex].pgui);
  283. }
  284. // Flag the looper that we're done.
  285. ms_bMenuDone = true;
  286. return sRes;
  287. }
  288. //////////////////////////////////////////////////////////////////////////////
  289. // Called when a choice is made or a selection is changed on an input
  290. // setttings menu.
  291. //////////////////////////////////////////////////////////////////////////////
  292. void InputSettingsDlg_Choice( // Returns nothing.
  293. Menu* pmenu, // In: Current menu.
  294. short sMenuItem) // In: Menu item chosen or -1 if selection
  295. // change.
  296. {
  297. static U8* pau8KeyStatusArray = rspGetKeyStatusArray();
  298. short sError = 0;
  299. if (sMenuItem > -1)
  300. {
  301. // If the specified item has a GUI . . .
  302. if (pmenu->ami[sMenuItem].pgui)
  303. {
  304. ms_bListenForInput = true;
  305. // Clear input array for key type.
  306. memset(pau8KeyStatusArray, 0, 128);
  307. // Clear buttons status for mouse type.
  308. ms_sMouseButtons = 0;
  309. // Clear buttons tatus for joy type.
  310. ms_sJoyButtons = 0;
  311. // Get GUI.
  312. RGuiItem* pgui = pmenu->ami[sMenuItem].pgui;
  313. // Note original color.
  314. ms_u32OrigTextColor = pgui->m_u32TextColor;
  315. // Reset flash timer.
  316. ms_lFlashTimer = rspGetMilliseconds() + FLASH_TIMEOUT;
  317. switch (pmenu->u32Id)
  318. {
  319. case KEYBOARD_MENU_ID:
  320. break;
  321. case MOUSE_MENU_ID:
  322. g_InputSettings.m_asPlayMouseButtons[pgui->m_ulUserData] = ms_sMouseButtons;
  323. pgui->SetText("%s", g_apszMouseButtonDescriptions[MouseBitfieldToIndex(ms_sMouseButtons)]);
  324. pgui->Compose();
  325. break;
  326. case JOYSTICK_MENU_ID:
  327. g_InputSettings.m_asPlayJoyButtons[pgui->m_ulUserData] = JoyIndexToBitfield(ms_sJoyButtons);
  328. pgui->SetText("%s", g_apszJoyButtonDescriptions[JoyIndexToBitfield(ms_sJoyButtons)]);
  329. pgui->Compose();
  330. break;
  331. }
  332. }
  333. else
  334. {
  335. if (sMenuItem == ms_sResetItem
  336. || sMenuItem == ms_sResetItemOld)
  337. {
  338. U32* pasPlayInputs = NULL; // Input value array.
  339. char** papszInputDescriptions = NULL; // Descriptions of input values.
  340. switch (pmenu->u32Id)
  341. {
  342. case KEYBOARD_MENU_ID:
  343. // Use keys.
  344. pasPlayInputs = g_InputSettings.m_asPlayKeys;
  345. papszInputDescriptions = g_apszKeyDescriptions;
  346. break;
  347. case MOUSE_MENU_ID:
  348. // Use mouse buttons.
  349. pasPlayInputs = g_InputSettings.m_asPlayMouseButtons;
  350. papszInputDescriptions = g_apszMouseButtonDescriptions;
  351. break;
  352. case JOYSTICK_MENU_ID:
  353. // Use joy buttons.
  354. pasPlayInputs = g_InputSettings.m_asPlayJoyButtons;
  355. papszInputDescriptions = g_apszJoyButtonDescriptions;
  356. break;
  357. default:
  358. TRACE("InputSettingsDlg_Choice(): Unsupported menu.\n");
  359. sError = 1;
  360. break;
  361. }
  362. short sInputIndex;
  363. RGuiItem* pgui;
  364. for (sInputIndex = 0; sInputIndex < CInputSettings::NumInputFunctions && sError == 0; sInputIndex++)
  365. {
  366. pgui = pmenu->ami[sInputIndex].pgui;
  367. // Restore input default.
  368. switch (pmenu->u32Id)
  369. {
  370. case KEYBOARD_MENU_ID:
  371. // Use keys.
  372. pasPlayInputs[sInputIndex] = sMenuItem == ms_sResetItemOld ? CInputSettings::ms_ainputinfoOld[sInputIndex].u8DefaultKey : CInputSettings::ms_ainputinfo[sInputIndex].u8DefaultKey;
  373. break;
  374. case MOUSE_MENU_ID:
  375. // Use mouse buttons.
  376. pasPlayInputs[sInputIndex] = sMenuItem == ms_sResetItemOld ? CInputSettings::ms_ainputinfoOld[sInputIndex].sDefMouseButtons : CInputSettings::ms_ainputinfo[sInputIndex].sDefMouseButtons;
  377. break;
  378. case JOYSTICK_MENU_ID:
  379. // Use joy buttons.
  380. pasPlayInputs[sInputIndex] = sMenuItem == ms_sResetItemOld ? CInputSettings::ms_ainputinfoOld[sInputIndex].sDefJoyButtons : CInputSettings::ms_ainputinfo[sInputIndex].sDefJoyButtons;
  381. break;
  382. }
  383. // Set the GUIs text to the corresponding input description and recompose.
  384. if (pmenu->u32Id == JOYSTICK_MENU_ID)
  385. pgui->SetText("%s", g_apszJoyButtonDescriptions[JoyBitfieldToIndex(pasPlayInputs[sInputIndex])]);
  386. else if (pmenu->u32Id == MOUSE_MENU_ID)
  387. pgui->SetText("%s", g_apszMouseButtonDescriptions[MouseBitfieldToIndex(pasPlayInputs[sInputIndex])]);
  388. else
  389. pgui->SetText("%s", papszInputDescriptions[pasPlayInputs[sInputIndex]]);
  390. pgui->Compose();
  391. }
  392. }
  393. }
  394. }
  395. }
  396. //////////////////////////////////////////////////////////////////////////////
  397. // Checks is a key is mappable as an input via ms_au8UnmappableKeys[].
  398. //////////////////////////////////////////////////////////////////////////////
  399. static bool IsMappable( // Returns true, if mappable, false otherwise.
  400. U8 u8Key) // In: Key to check mappable status on.
  401. {
  402. bool bMappable = true;
  403. short sIndex;
  404. for (sIndex = 0; sIndex < NUM_ELEMENTS(ms_au8UnmappableKeys); sIndex++)
  405. {
  406. // If this is the specified key . . .
  407. if (ms_au8UnmappableKeys[sIndex] == u8Key)
  408. {
  409. // Not mappable.
  410. bMappable = false;
  411. break;
  412. }
  413. }
  414. return bMappable;
  415. }
  416. //////////////////////////////////////////////////////////////////////////////
  417. // Listens for input. If input detected, it is updated to the appropriate
  418. // input array.
  419. //////////////////////////////////////////////////////////////////////////////
  420. inline void ListenForInput( // Returns nothing.
  421. RInputEvent* pie) // In: Input event.
  422. {
  423. static U8* pau8KeyStatusArray = rspGetKeyStatusArray();
  424. RGuiItem* pgui = RGuiItem::ms_pguiFocus;
  425. bool bAffirmitiveFeedback = true; // true to play affirmitive audible
  426. // feedback, false for negative.
  427. switch (pie->type)
  428. {
  429. case RInputEvent::Key:
  430. if (pie->lKey == 27)
  431. {
  432. ms_bListenForInput = false;
  433. bAffirmitiveFeedback = false;
  434. }
  435. // Don't allow menu to respond to any key events.
  436. pie->sUsed = TRUE;
  437. break;
  438. }
  439. // If still listening . . .
  440. if (ms_bListenForInput == true)
  441. {
  442. switch (GetCurrentMenu()->u32Id)
  443. {
  444. case KEYBOARD_MENU_ID:
  445. {
  446. U8* pu8Key = pau8KeyStatusArray;
  447. short i;
  448. for (i = 0; i < 128; i++, pu8Key++)
  449. {
  450. // If pressed . . .
  451. if ((*pu8Key) & 1)
  452. {
  453. // If mappable . . .
  454. if (IsMappable(i) == true)
  455. {
  456. pgui->SetText("%s", g_apszKeyDescriptions[i]);
  457. pgui->Compose();
  458. g_InputSettings.m_asPlayKeys[pgui->m_ulUserData] = i;
  459. }
  460. else
  461. {
  462. bAffirmitiveFeedback = false;
  463. }
  464. ms_bListenForInput = false;
  465. break;
  466. }
  467. }
  468. break;
  469. }
  470. case MOUSE_MENU_ID:
  471. switch (pie->type)
  472. {
  473. case RInputEvent::Key:
  474. if (pie->lKey == '\r')
  475. {
  476. // Done with mode.
  477. ms_bListenForInput = false;
  478. g_InputSettings.m_asPlayMouseButtons[pgui->m_ulUserData] = ms_sMouseButtons;
  479. pgui->SetText("%s", g_apszMouseButtonDescriptions[ms_sMouseButtons]);
  480. pgui->Compose();
  481. }
  482. break;
  483. case RInputEvent::Mouse:
  484. // Switch on type (up or down) . . .
  485. switch (pie->sEvent)
  486. {
  487. case RSP_MB0_PRESSED:
  488. case RSP_MB1_PRESSED:
  489. case RSP_MB2_PRESSED:
  490. case 1025: // Yeah I dunno
  491. case 1027:
  492. // Stay in mode, just update status.
  493. ms_sMouseButtons |= pie->sButtons;
  494. break;
  495. case RSP_MB0_RELEASED:
  496. case RSP_MB1_RELEASED:
  497. case RSP_MB2_RELEASED:
  498. case 1026: // Yeah I dunno
  499. // Done with mode.
  500. ms_bListenForInput = false;
  501. g_InputSettings.m_asPlayMouseButtons[pgui->m_ulUserData] = ms_sMouseButtons;
  502. break;
  503. }
  504. pgui->SetText("%s", g_apszMouseButtonDescriptions[MouseBitfieldToIndex(ms_sMouseButtons)]);
  505. pgui->Compose();
  506. break;
  507. }
  508. break;
  509. case JOYSTICK_MENU_ID:
  510. switch (pie->type)
  511. {
  512. case RInputEvent::Key:
  513. if (pie->lKey == '\r')
  514. {
  515. // Done with mode.
  516. ms_bListenForInput = false;
  517. g_InputSettings.m_asPlayJoyButtons[pgui->m_ulUserData] = JoyIndexToBitfield(ms_sJoyButtons);
  518. pgui->SetText("%s", g_apszJoyButtonDescriptions[JoyIndexToBitfield(ms_sJoyButtons)]);
  519. pgui->Compose();
  520. }
  521. break;
  522. case RInputEvent::None:
  523. {
  524. #if defined(ALLOW_JOYSTICK)
  525. XInputState xis = {};
  526. GetXInputState(&xis);
  527. for (int i = 0; i < XInputButtons; i++)
  528. {
  529. // If button was released...
  530. if (xis.ButtonState[i] == XInputState::Press)
  531. {
  532. // Done with mode.
  533. ms_bListenForInput = false;
  534. g_InputSettings.m_asPlayJoyButtons[pgui->m_ulUserData] = JoyIndexToBitfield(i);
  535. pgui->SetText("%s", g_apszJoyButtonDescriptions[i]);
  536. pgui->Compose();
  537. break;
  538. }
  539. }
  540. #endif
  541. #if 0 //defined(ALLOW_JOYSTICK)
  542. // Only use one joystick.
  543. rspUpdateJoy(0);
  544. // Get prev and current status.
  545. U32 u32ButtonsPrev;
  546. U32 u32ButtonsCur;
  547. rspGetJoyPrevState(0, &u32ButtonsPrev);
  548. rspGetJoyState(0, &u32ButtonsCur);
  549. // If less buttons are down . . .
  550. if ( (u32ButtonsPrev & RSP_JOY_BUT_1) > (u32ButtonsCur & RSP_JOY_BUT_1)
  551. || (u32ButtonsPrev & RSP_JOY_BUT_2) > (u32ButtonsCur & RSP_JOY_BUT_2)
  552. || (u32ButtonsPrev & RSP_JOY_BUT_3) > (u32ButtonsCur & RSP_JOY_BUT_3)
  553. || (u32ButtonsPrev & RSP_JOY_BUT_4) > (u32ButtonsCur & RSP_JOY_BUT_4)
  554. || (u32ButtonsPrev & RSP_JOY_BUT_5) > (u32ButtonsCur & RSP_JOY_BUT_5)
  555. || (u32ButtonsPrev & RSP_JOY_BUT_6) > (u32ButtonsCur & RSP_JOY_BUT_6)
  556. || (u32ButtonsPrev & RSP_JOY_BUT_7) > (u32ButtonsCur & RSP_JOY_BUT_7)
  557. || (u32ButtonsPrev & RSP_JOY_BUT_8) > (u32ButtonsCur & RSP_JOY_BUT_8)
  558. || (u32ButtonsPrev & RSP_JOY_BUT_9) > (u32ButtonsCur & RSP_JOY_BUT_9)
  559. || (u32ButtonsPrev & RSP_JOY_BUT_10) > (u32ButtonsCur & RSP_JOY_BUT_10)
  560. || (u32ButtonsPrev & RSP_JOY_BUT_11) > (u32ButtonsCur & RSP_JOY_BUT_11)
  561. || (u32ButtonsPrev & RSP_JOY_BUT_12) > (u32ButtonsCur & RSP_JOY_BUT_12)
  562. || (u32ButtonsPrev & RSP_JOY_BUT_13) > (u32ButtonsCur & RSP_JOY_BUT_13)
  563. || (u32ButtonsPrev & RSP_JOY_BUT_14) > (u32ButtonsCur & RSP_JOY_BUT_14)
  564. || (u32ButtonsPrev & RSP_JOY_BUT_15) > (u32ButtonsCur & RSP_JOY_BUT_15)
  565. || (u32ButtonsPrev & RSP_JOY_BUT_16) > (u32ButtonsCur & RSP_JOY_BUT_16)
  566. )
  567. {
  568. // Done with mode.
  569. ms_bListenForInput = false;
  570. g_InputSettings.m_asPlayJoyButtons[pgui->m_ulUserData] = JoyIndexToBitfield(ms_sJoyButtons);
  571. }
  572. else
  573. {
  574. // Stay in mode, just update status. Limit to four buttons due to
  575. // limitations imposed when joystick interface was four buttons. Next time
  576. // we'll allow many, many buttons.
  577. //ms_sJoyButtons = (short)(u32ButtonsCur & (RSP_JOY_BUT_1 | RSP_JOY_BUT_2 | RSP_JOY_BUT_3 | RSP_JOY_BUT_4) );
  578. ms_sJoyButtons = JoyBitfieldToIndex(u32ButtonsCur);
  579. // Don't allow binding "Start" because we need it to pull up the menu.
  580. if (ms_sJoyButtons == g_InputSettings.m_sJoyStartButton)
  581. ms_sJoyButtons = 0;
  582. }
  583. // Sanity check
  584. if (ms_sJoyButtons >= 0 && ms_sJoyButtons < 16)
  585. pgui->SetText("%s", g_apszJoyButtonDescriptions[ms_sJoyButtons]);
  586. else
  587. pgui->SetText("???");
  588. pgui->Compose();
  589. #endif // defined(ALLOW_JOYSTICK)
  590. break;
  591. }
  592. }
  593. break;
  594. }
  595. }
  596. // If mode completed . . .
  597. if (ms_bListenForInput == false)
  598. {
  599. if (bAffirmitiveFeedback == true)
  600. {
  601. PlaySample(g_smidLoadedWeapon, SampleMaster::Unspecified);
  602. }
  603. else
  604. {
  605. PlaySample(g_smidEmptyWeapon, SampleMaster::Unspecified);
  606. }
  607. // Make sure text color is restored.
  608. pgui->m_u32TextColor = ms_u32OrigTextColor;
  609. pgui->Compose();
  610. }
  611. else
  612. {
  613. // If timer has expired . . .
  614. if (rspGetMilliseconds() > ms_lFlashTimer)
  615. {
  616. // Flash item.
  617. if (pgui->m_u32TextColor == ms_u32OrigTextColor)
  618. {
  619. pgui->m_u32TextColor = TEXT_LISTEN_COLOR;
  620. }
  621. else
  622. {
  623. pgui->m_u32TextColor = ms_u32OrigTextColor;
  624. }
  625. pgui->Compose();
  626. // Reset flash timer.
  627. ms_lFlashTimer = rspGetMilliseconds() + FLASH_TIMEOUT;
  628. }
  629. }
  630. }
  631. //////////////////////////////////////////////////////////////////////////////
  632. // Edit the input settings via menu.
  633. //////////////////////////////////////////////////////////////////////////////
  634. extern short EditInputSettings(void) // Returns nothing.
  635. {
  636. short sRes = 0; // Assume success.
  637. bool bDeleteKeybind = false; // If true, we want to delete the keybind we're on.
  638. // Menu is already started.
  639. // Menu is only just starting.
  640. ms_bMenuDone = false;
  641. RInputEvent ie;
  642. // Until the menu exits.
  643. while (rspGetQuitStatus() == FALSE && ms_bMenuDone == false)
  644. {
  645. // Update the system, drive the audio, blah blah blah.
  646. UpdateSystem();
  647. ie.type = RInputEvent::None;
  648. rspGetNextInputEvent(&ie);
  649. switch (ie.type)
  650. {
  651. case RInputEvent::Key:
  652. if (ie.lKey == RSP_SK_BACKSPACE)
  653. bDeleteKeybind = true;
  654. break;
  655. case RInputEvent::Mouse:
  656. switch (ie.sEvent)
  657. {
  658. case RSP_MB0_PRESSED:
  659. case RSP_MB1_PRESSED:
  660. case RSP_MB2_PRESSED:
  661. if (RGuiItem::ms_pguiFocus && ms_bListenForInput == false)
  662. {
  663. // Activate listen mode.
  664. InputSettingsDlg_Choice(
  665. GetCurrentMenu(),
  666. RGuiItem::ms_pguiFocus->m_ulUserData);
  667. }
  668. break;
  669. }
  670. break;
  671. case RInputEvent::None:
  672. #if defined(ALLOW_JOYSTICK)
  673. if (RGuiItem::ms_pguiFocus && ms_bListenForInput == false)
  674. {
  675. #if 0
  676. // Only use one joystick.
  677. rspUpdateJoy(0);
  678. // Get prev and current status.
  679. U32 u32ButtonsPrev;
  680. U32 u32ButtonsCur;
  681. rspGetJoyPrevState(0, &u32ButtonsPrev);
  682. rspGetJoyState(0, &u32ButtonsCur);
  683. // If less buttons are up . . .
  684. if ( (u32ButtonsCur & RSP_JOY_BUT_1) > (u32ButtonsPrev & RSP_JOY_BUT_1)
  685. || (u32ButtonsCur & RSP_JOY_BUT_2) > (u32ButtonsPrev & RSP_JOY_BUT_2)
  686. || (u32ButtonsCur & RSP_JOY_BUT_3) > (u32ButtonsPrev & RSP_JOY_BUT_3)
  687. || (u32ButtonsCur & RSP_JOY_BUT_4) > (u32ButtonsPrev & RSP_JOY_BUT_4)
  688. || (u32ButtonsCur & RSP_JOY_BUT_5) > (u32ButtonsPrev & RSP_JOY_BUT_5)
  689. || (u32ButtonsCur & RSP_JOY_BUT_6) > (u32ButtonsPrev & RSP_JOY_BUT_6)
  690. || (u32ButtonsCur & RSP_JOY_BUT_7) > (u32ButtonsPrev & RSP_JOY_BUT_7)
  691. || (u32ButtonsCur & RSP_JOY_BUT_8) > (u32ButtonsPrev & RSP_JOY_BUT_8)
  692. || (u32ButtonsCur & RSP_JOY_BUT_9) > (u32ButtonsPrev & RSP_JOY_BUT_9)
  693. || (u32ButtonsCur & RSP_JOY_BUT_10) > (u32ButtonsPrev & RSP_JOY_BUT_10)
  694. || (u32ButtonsCur & RSP_JOY_BUT_11) > (u32ButtonsPrev & RSP_JOY_BUT_11)
  695. || (u32ButtonsCur & RSP_JOY_BUT_12) > (u32ButtonsPrev & RSP_JOY_BUT_12)
  696. || (u32ButtonsCur & RSP_JOY_BUT_13) > (u32ButtonsPrev & RSP_JOY_BUT_13)
  697. || (u32ButtonsCur & RSP_JOY_BUT_14) > (u32ButtonsPrev & RSP_JOY_BUT_14)
  698. || (u32ButtonsCur & RSP_JOY_BUT_15) > (u32ButtonsPrev & RSP_JOY_BUT_15)
  699. || (u32ButtonsCur & RSP_JOY_BUT_16) > (u32ButtonsPrev & RSP_JOY_BUT_16)
  700. )
  701. {
  702. // Activate listen mode.
  703. InputSettingsDlg_Choice(
  704. GetCurrentMenu(),
  705. RGuiItem::ms_pguiFocus->m_ulUserData);
  706. }
  707. #endif
  708. }
  709. #endif // defined(ALLOW_JOYSTICK)
  710. break;
  711. }
  712. // If listening . . .
  713. if (ms_bListenForInput == true)
  714. {
  715. ListenForInput(&ie);
  716. }
  717. // Let menu system do its thing
  718. DoMenuInput(&ie, 1);
  719. DoMenuOutput(g_pimScreenBuf);
  720. // Joystick: erase keybind with Back button
  721. XInputState xis = {};
  722. GetLastXInputState(&xis);
  723. if (xis.ButtonState[g_InputSettings.m_sJoyMenuDeleteKeybindButton] == XInputState::Press)
  724. {
  725. bDeleteKeybind = true;
  726. GetXInputState(&xis); // throw out this state
  727. }
  728. if (bDeleteKeybind)
  729. {
  730. RGuiItem* pgui = RGuiItem::ms_pguiFocus;
  731. if (pgui)
  732. {
  733. if (GetCurrentMenu()->u32Id == KEYBOARD_MENU_ID)
  734. g_InputSettings.m_asPlayKeys[pgui->m_ulUserData] = 0;
  735. else if (GetCurrentMenu()->u32Id == MOUSE_MENU_ID)
  736. g_InputSettings.m_asPlayMouseButtons[pgui->m_ulUserData] = 0;
  737. else if (GetCurrentMenu()->u32Id == JOYSTICK_MENU_ID)
  738. g_InputSettings.m_asPlayJoyButtons[pgui->m_ulUserData] = 0;
  739. pgui->SetText("None");
  740. pgui->Compose();
  741. }
  742. bDeleteKeybind = false;
  743. }
  744. // Update the screen
  745. rspUpdateDisplay();
  746. }
  747. return sRes;
  748. }
  749. //////////////////////////////////////////////////////////////////////////////
  750. // EOF
  751. //////////////////////////////////////////////////////////////////////////////