actionMap.cc 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "input/actionMap.h"
  23. #include "platform/event.h"
  24. #include "console/console.h"
  25. #include "platform/platform.h"
  26. #include "platform/platformInput.h"
  27. #include "platform/platformAssert.h"
  28. #include "io/fileStream.h"
  29. #include "io/resource/resourceManager.h"
  30. // Script bindings.
  31. #include "actionMap_ScriptBinding.h"
  32. IMPLEMENT_CONOBJECT(ActionMap);
  33. // This is used for determing keys that have ascii codes for the foreign keyboards. IsAlpha doesn't work on foreign keys.
  34. #define dIsDecentChar(c) (((char(0xa0) <= (c)) && ((c) <= char(0xff))) || (( char(0x21) <= (c)) && ((c) <= char(0x7e))) || (( char(0x91) <= (c)) && ((c) <= char(0x92))))
  35. struct CodeMapping
  36. {
  37. const char* pDescription;
  38. U8 type;
  39. U32 code;
  40. };
  41. struct AsciiMapping
  42. {
  43. const char* pDescription;
  44. U16 asciiCode;
  45. };
  46. extern CodeMapping gVirtualMap[];
  47. extern AsciiMapping gAsciiMap[];
  48. //------------------------------------------------------------------------------
  49. //-------------------------------------- Action maps
  50. //
  51. Vector<ActionMap::BreakEntry> ActionMap::smBreakTable(__FILE__, __LINE__);
  52. //------------------------------------------------------------------------------
  53. ActionMap::ActionMap()
  54. {
  55. VECTOR_SET_ASSOCIATION(mDeviceMaps);
  56. }
  57. //------------------------------------------------------------------------------
  58. ActionMap::~ActionMap()
  59. {
  60. for (U32 i = 0; i < (U32)mDeviceMaps.size(); i++)
  61. delete mDeviceMaps[i];
  62. mDeviceMaps.clear();
  63. }
  64. //------------------------------------------------------------------------------
  65. ActionMap::DeviceMap::~DeviceMap()
  66. {
  67. for(U32 i = 0; i < (U32)nodeMap.size(); i++)
  68. {
  69. dFree(nodeMap[i].makeConsoleCommand);
  70. dFree(nodeMap[i].breakConsoleCommand);
  71. }
  72. }
  73. //------------------------------------------------------------------------------
  74. bool ActionMap::onAdd()
  75. {
  76. if (Parent::onAdd() == false)
  77. return false;
  78. Sim::getActionMapGroup()->addObject(this);
  79. return true;
  80. }
  81. //--------------------------------------------------------------------------
  82. void ActionMap::dumpActionMap(const char* fileName, const bool append) const
  83. {
  84. if (fileName != NULL) {
  85. // Dump the deletion, and creation script commands, followed by all the binds
  86. // to a script.
  87. FileStream iostrm;
  88. if ( !ResourceManager->openFileForWrite( iostrm, fileName, append ? FileStream::WriteAppend : FileStream::Write ) )
  89. {
  90. Con::errorf( "Unable to open file '%s' for writing.", fileName );
  91. return;
  92. }
  93. char lineBuffer[1024];
  94. if ( append )
  95. iostrm.setPosition( iostrm.getStreamSize() );
  96. else
  97. {
  98. // IMPORTANT -- do NOT change the following line, it identifies the file as an input map file
  99. dStrcpy( lineBuffer, "// Torque Input Map File\n" );
  100. iostrm.write( dStrlen( lineBuffer ), lineBuffer );
  101. }
  102. dSprintf(lineBuffer, 1023, "if (isObject(%s)) %s.delete();\n"
  103. "new ActionMap(%s);\n", getName(), getName(), getName());
  104. iostrm.write(dStrlen(lineBuffer), lineBuffer);
  105. // Dump all the binds to the console...
  106. for (S32 i = 0; i < mDeviceMaps.size(); i++) {
  107. const DeviceMap* pDevMap = mDeviceMaps[i];
  108. char devbuffer[32];
  109. getDeviceName(pDevMap->deviceType, pDevMap->deviceInst, devbuffer);
  110. for (S32 j = 0; j < pDevMap->nodeMap.size(); j++) {
  111. const Node& rNode = pDevMap->nodeMap[j];
  112. const char* pModifierString = getModifierString(rNode.modifiers);
  113. char objectbuffer[64];
  114. if (getKeyString(rNode.action, objectbuffer) == false)
  115. continue;
  116. const char* command = (rNode.flags & Node::BindCmd) ? "bindCmd" : "bind";
  117. dSprintf(lineBuffer, 1023, "%s.%s(%s, \"%s%s\"",
  118. getName(),
  119. command,
  120. devbuffer,
  121. pModifierString, objectbuffer);
  122. if (rNode.flags & (Node::HasScale|Node::HasDeadZone|Node::Ranged|Node::Inverted)) {
  123. char buff[10];
  124. U32 curr = 0;
  125. buff[curr++] = ',';
  126. buff[curr++] = ' ';
  127. if (rNode.flags & Node::HasScale)
  128. buff[curr++] = 'S';
  129. if (rNode.flags & Node::Ranged)
  130. buff[curr++] = 'R';
  131. if (rNode.flags & Node::HasDeadZone)
  132. buff[curr++] = 'D';
  133. if (rNode.flags & Node::Inverted)
  134. buff[curr++] = 'I';
  135. buff[curr] = '\0';
  136. dStrcat(lineBuffer, buff);
  137. }
  138. if (rNode.flags & Node::HasDeadZone) {
  139. char buff[64];
  140. dSprintf(buff, 63, ", \"%g %g\"", rNode.deadZoneBegin, rNode.deadZoneEnd);
  141. dStrcat(lineBuffer, buff);
  142. }
  143. if (rNode.flags & Node::HasScale) {
  144. char buff[64];
  145. dSprintf(buff, 63, ", %g", rNode.scaleFactor);
  146. dStrcat(lineBuffer, buff);
  147. }
  148. if (rNode.flags & Node::BindCmd) {
  149. if (rNode.makeConsoleCommand) {
  150. dStrcat(lineBuffer, ", \"");
  151. U32 pos = dStrlen(lineBuffer);
  152. expandEscape(lineBuffer + pos, rNode.makeConsoleCommand);
  153. dStrcat(lineBuffer, "\"");
  154. } else {
  155. dStrcat(lineBuffer, ", \"\"");
  156. }
  157. if (rNode.breakConsoleCommand) {
  158. dStrcat(lineBuffer, ", \"");
  159. U32 pos = dStrlen(lineBuffer);
  160. expandEscape(lineBuffer + pos, rNode.breakConsoleCommand);
  161. dStrcat(lineBuffer, "\"");
  162. }
  163. else
  164. dStrcat(lineBuffer, ", \"\"");
  165. } else {
  166. dStrcat(lineBuffer, ", ");
  167. dStrcat(lineBuffer, rNode.consoleFunction);
  168. }
  169. dStrcat(lineBuffer, ");\n");
  170. iostrm.write(dStrlen(lineBuffer), lineBuffer);
  171. }
  172. }
  173. iostrm.close();
  174. }
  175. else {
  176. // Dump all the binds to the console...
  177. for (S32 i = 0; i < mDeviceMaps.size(); i++) {
  178. const DeviceMap* pDevMap = mDeviceMaps[i];
  179. char devbuffer[32];
  180. getDeviceName(pDevMap->deviceType, pDevMap->deviceInst, devbuffer);
  181. for (S32 j = 0; j < pDevMap->nodeMap.size(); j++) {
  182. const Node& rNode = pDevMap->nodeMap[j];
  183. const char* pModifierString = getModifierString(rNode.modifiers);
  184. char keybuffer[64];
  185. if (getKeyString(rNode.action, keybuffer) == false)
  186. continue;
  187. const char* command = (rNode.flags & Node::BindCmd) ? "bindCmd" : "bind";
  188. char finalBuffer[1024];
  189. dSprintf(finalBuffer, 1023, "%s.%s(%s, \"%s%s\"",
  190. getName(),
  191. command,
  192. devbuffer,
  193. pModifierString, keybuffer);
  194. if (rNode.flags & (Node::HasScale|Node::HasDeadZone|Node::Ranged|Node::Inverted)) {
  195. char buff[10];
  196. U32 curr = 0;
  197. buff[curr++] = ',';
  198. buff[curr++] = ' ';
  199. if (rNode.flags & Node::HasScale)
  200. buff[curr++] = 'S';
  201. if (rNode.flags & Node::Ranged)
  202. buff[curr++] = 'R';
  203. if (rNode.flags & Node::HasDeadZone)
  204. buff[curr++] = 'D';
  205. if (rNode.flags & Node::Inverted)
  206. buff[curr++] = 'I';
  207. buff[curr] = '\0';
  208. dStrcat(finalBuffer, buff);
  209. }
  210. if (rNode.flags & Node::HasDeadZone) {
  211. char buff[64];
  212. dSprintf(buff, 63, ", \"%g %g\"", rNode.deadZoneBegin, rNode.deadZoneEnd);
  213. dStrcat(finalBuffer, buff);
  214. }
  215. if (rNode.flags & Node::HasScale) {
  216. char buff[64];
  217. dSprintf(buff, 63, ", %g", rNode.scaleFactor);
  218. dStrcat(finalBuffer, buff);
  219. }
  220. if (rNode.flags & Node::BindCmd) {
  221. if (rNode.makeConsoleCommand) {
  222. dStrcat(finalBuffer, ", \"");
  223. dStrcat(finalBuffer, rNode.makeConsoleCommand);
  224. dStrcat(finalBuffer, "\"");
  225. } else {
  226. dStrcat(finalBuffer, ", \"\"");
  227. }
  228. if (rNode.breakConsoleCommand) {
  229. dStrcat(finalBuffer, ", \"");
  230. dStrcat(finalBuffer, rNode.breakConsoleCommand);
  231. dStrcat(finalBuffer, "\"");
  232. }
  233. else
  234. dStrcat(finalBuffer, ", \"\"");
  235. } else {
  236. dStrcat(finalBuffer, ", ");
  237. dStrcat(finalBuffer, rNode.consoleFunction);
  238. }
  239. dStrcat(finalBuffer, ");");
  240. Con::printf(finalBuffer);
  241. }
  242. }
  243. }
  244. }
  245. //--------------------------------------------------------------------------
  246. bool ActionMap::createEventDescriptor(const char* pEventString, EventDescriptor* pDescriptor)
  247. {
  248. char copyBuffer[256];
  249. dStrcpy(copyBuffer, pEventString);
  250. // Do we have modifiers?
  251. char* pSpace = dStrchr(copyBuffer, ' ');
  252. char* pObjectString;
  253. if (pSpace != NULL) {
  254. // Yes. Parse them out...
  255. //
  256. pDescriptor->flags = 0;
  257. pObjectString = pSpace + 1;
  258. pSpace[0] = '\0';
  259. char* pModifier = dStrtok(copyBuffer, "-");
  260. while (pModifier != NULL) {
  261. if (dStricmp(pModifier, "shift") == 0) {
  262. pDescriptor->flags |= SI_SHIFT;
  263. } else if (dStricmp(pModifier, "ctrl") == 0) {
  264. pDescriptor->flags |= SI_CTRL;
  265. } else if (dStricmp(pModifier, "alt") == 0) {
  266. pDescriptor->flags |= SI_ALT;
  267. } else if (dStricmp(pModifier, "cmd") == 0) {
  268. pDescriptor->flags |= SI_ALT;
  269. } else if (dStricmp(pModifier, "opt") == 0) {
  270. pDescriptor->flags |= SI_MAC_OPT;
  271. }
  272. pModifier = dStrtok(NULL, "-");
  273. }
  274. } else {
  275. // No.
  276. pDescriptor->flags = 0;
  277. pObjectString = copyBuffer;
  278. }
  279. // Now we need to map the key string to the proper KEY code from event.h
  280. //
  281. AssertFatal(dStrlen(pObjectString) != 0, "Error, no key was specified!");
  282. if (dStrlen(pObjectString) == 1)
  283. {
  284. if (dIsDecentChar(*pObjectString)) // includes foreign chars
  285. {
  286. U16 asciiCode = (*pObjectString);
  287. // clear out the FF in upper 8bits for foreign keys??
  288. asciiCode &= 0xFF;
  289. U16 keyCode = Input::getKeyCode(asciiCode);
  290. if ( keyCode >= KEY_0 )
  291. {
  292. pDescriptor->eventType = SI_KEY;
  293. pDescriptor->eventCode = keyCode;
  294. return true;
  295. }
  296. else if (dIsalpha(*pObjectString) == true)
  297. {
  298. pDescriptor->eventType = SI_KEY;
  299. pDescriptor->eventCode = KEY_A+dTolower(*pObjectString)-'a';
  300. return true;
  301. }
  302. else if (dIsdigit(*pObjectString) == true)
  303. {
  304. pDescriptor->eventType = SI_KEY;
  305. pDescriptor->eventCode = KEY_0+(*pObjectString)-'0';
  306. return true;
  307. }
  308. }
  309. return false;
  310. }
  311. else
  312. {
  313. pDescriptor->eventCode = 0;
  314. // Gotta search through the Ascii table...
  315. for (U16 i = 0; gAsciiMap[i].asciiCode != 0xFFFF; i++)
  316. {
  317. if (dStricmp(pObjectString, gAsciiMap[i].pDescription) == 0)
  318. {
  319. U16 asciiCode = gAsciiMap[i].asciiCode;
  320. U16 keyCode = Input::getKeyCode(asciiCode);
  321. if ( keyCode >= KEY_0 )
  322. {
  323. pDescriptor->eventType = SI_KEY;
  324. pDescriptor->eventCode = keyCode;
  325. return(true);
  326. }
  327. else
  328. {
  329. break;
  330. }
  331. }
  332. }
  333. // Didn't find an ascii match. Check the virtual map table
  334. for (U32 j = 0; gVirtualMap[j].code != 0xFFFFFFFF; j++)
  335. {
  336. if (dStricmp(pObjectString, gVirtualMap[j].pDescription) == 0)
  337. {
  338. pDescriptor->eventType = gVirtualMap[j].type;
  339. pDescriptor->eventCode = gVirtualMap[j].code;
  340. return true;
  341. }
  342. }
  343. }
  344. return false;
  345. }
  346. //------------------------------------------------------------------------------
  347. ActionMap::Node* ActionMap::getNode(const U32 inDeviceType, const U32 inDeviceInst,
  348. const U32 inModifiers, const U32 inAction,SimObject* object /*= NULL*/)
  349. {
  350. // DMMTODO - Slow INITIAL implementation. Replace with a faster version...
  351. //
  352. DeviceMap* pDeviceMap = NULL;
  353. U32 i;
  354. for (i = 0; i < (U32)mDeviceMaps.size(); i++)
  355. {
  356. if (mDeviceMaps[i]->deviceType == inDeviceType &&
  357. mDeviceMaps[i]->deviceInst == inDeviceInst) {
  358. pDeviceMap = mDeviceMaps[i];
  359. break;
  360. }
  361. }
  362. if (pDeviceMap == NULL)
  363. {
  364. mDeviceMaps.increment();
  365. mDeviceMaps.last() = new DeviceMap;
  366. pDeviceMap = mDeviceMaps.last();
  367. pDeviceMap->deviceInst = inDeviceInst;
  368. pDeviceMap->deviceType = inDeviceType;
  369. }
  370. for (i = 0; i < (U32)pDeviceMap->nodeMap.size(); i++)
  371. {
  372. if (pDeviceMap->nodeMap[i].modifiers == inModifiers &&
  373. pDeviceMap->nodeMap[i].action == inAction &&
  374. ( (object != NULL) ? object == pDeviceMap->nodeMap[i].object : true )) // Check for an object match if the object exists
  375. {
  376. return &pDeviceMap->nodeMap[i];
  377. }
  378. }
  379. // If we're here, the node doesn't exist. create it.
  380. pDeviceMap->nodeMap.increment();
  381. Node* pRetNode = &pDeviceMap->nodeMap.last();
  382. pRetNode->modifiers = inModifiers;
  383. pRetNode->action = inAction;
  384. pRetNode->flags = 0;
  385. pRetNode->deadZoneBegin = 0.0;
  386. pRetNode->deadZoneEnd = 0.0;
  387. pRetNode->scaleFactor = 1.0;
  388. pRetNode->consoleFunction = NULL;
  389. pRetNode->makeConsoleCommand = NULL;
  390. pRetNode->breakConsoleCommand = NULL;
  391. //[neob, 5/7/2007 - #2975]
  392. pRetNode->object = 0;
  393. return pRetNode;
  394. }
  395. //------------------------------------------------------------------------------
  396. void ActionMap::removeNode(const U32 inDeviceType, const U32 inDeviceInst, const U32 inModifiers, const U32 inAction, SimObject* object /*= NULL*/)
  397. {
  398. // DMMTODO - Slow INITIAL implementation. Replace with a faster version...
  399. //
  400. DeviceMap* pDeviceMap = NULL;
  401. U32 i;
  402. for (i = 0; i < (U32)mDeviceMaps.size(); i++) {
  403. if (mDeviceMaps[i]->deviceType == inDeviceType &&
  404. mDeviceMaps[i]->deviceInst == inDeviceInst) {
  405. pDeviceMap = mDeviceMaps[i];
  406. break;
  407. }
  408. }
  409. if (pDeviceMap == NULL)
  410. return;
  411. U32 realMods = inModifiers;
  412. if (realMods & SI_SHIFT)
  413. realMods |= SI_SHIFT;
  414. if (realMods & SI_CTRL)
  415. realMods |= SI_CTRL;
  416. if (realMods & SI_ALT)
  417. realMods |= SI_ALT;
  418. if (realMods & SI_MAC_OPT)
  419. realMods |= SI_MAC_OPT;
  420. for (i = 0; i < (U32)pDeviceMap->nodeMap.size(); i++) {
  421. if (pDeviceMap->nodeMap[i].modifiers == realMods &&
  422. pDeviceMap->nodeMap[i].action == inAction &&
  423. ( (object != NULL) ? object == pDeviceMap->nodeMap[i].object : true ))
  424. {
  425. dFree(pDeviceMap->nodeMap[i].makeConsoleCommand);
  426. dFree(pDeviceMap->nodeMap[i].breakConsoleCommand);
  427. pDeviceMap->nodeMap.erase(i);
  428. }
  429. }
  430. }
  431. //------------------------------------------------------------------------------
  432. const ActionMap::Node* ActionMap::findNode(const U32 inDeviceType, const U32 inDeviceInst,
  433. const U32 inModifiers, const U32 inAction)
  434. {
  435. // DMMTODO - Slow INITIAL implementation. Replace with a faster version...
  436. //
  437. DeviceMap* pDeviceMap = NULL;
  438. U32 i;
  439. for (i = 0; i < (U32)mDeviceMaps.size(); i++)
  440. {
  441. if (mDeviceMaps[i]->deviceType == inDeviceType && mDeviceMaps[i]->deviceInst == inDeviceInst)
  442. {
  443. pDeviceMap = mDeviceMaps[i];
  444. break;
  445. }
  446. }
  447. if (pDeviceMap == NULL)
  448. return NULL;
  449. U32 realMods = inModifiers;
  450. if (realMods & SI_SHIFT)
  451. realMods |= SI_SHIFT;
  452. if (realMods & SI_CTRL)
  453. realMods |= SI_CTRL;
  454. if (realMods & SI_ALT)
  455. realMods |= SI_ALT;
  456. if (realMods & SI_MAC_OPT)
  457. realMods |= SI_MAC_OPT;
  458. for (i = 0; i < (U32)pDeviceMap->nodeMap.size(); i++)
  459. {
  460. if (pDeviceMap->nodeMap[i].action == KEY_ANYKEY && pDeviceMap->nodeMap[i].modifiers == realMods && dIsDecentChar(inAction))
  461. return &pDeviceMap->nodeMap[i];
  462. else if (pDeviceMap->nodeMap[i].modifiers == realMods && pDeviceMap->nodeMap[i].action == inAction)
  463. return &pDeviceMap->nodeMap[i];
  464. }
  465. return NULL;
  466. }
  467. //------------------------------------------------------------------------------
  468. bool ActionMap::findBoundNode( const char* function, U32 &devMapIndex, U32 &nodeIndex )
  469. {
  470. devMapIndex = 0;
  471. nodeIndex = 0;
  472. return nextBoundNode( function, devMapIndex, nodeIndex );
  473. }
  474. bool ActionMap::nextBoundNode( const char* function, U32 &devMapIndex, U32 &nodeIndex )
  475. {
  476. // Loop through all of the existing nodes to find the one mapped to the
  477. // given function:
  478. for ( U32 i = devMapIndex; i < (U32)mDeviceMaps.size(); i++ )
  479. {
  480. const DeviceMap* dvcMap = mDeviceMaps[i];
  481. for ( U32 j = nodeIndex; j < (U32)dvcMap->nodeMap.size(); j++ )
  482. {
  483. const Node* node = &dvcMap->nodeMap[j];
  484. if ( !( node->flags & Node::BindCmd ) && ( dStricmp( function, node->consoleFunction ) == 0 ) )
  485. {
  486. devMapIndex = i;
  487. nodeIndex = j;
  488. return( true );
  489. }
  490. }
  491. nodeIndex = 0;
  492. }
  493. return( false );
  494. }
  495. //------------------------------------------------------------------------------
  496. bool ActionMap::processUnbind(const char *device, const char *action, SimObject* object /*= NULL*/)
  497. {
  498. U32 deviceType;
  499. U32 deviceInst;
  500. if(!getDeviceTypeAndInstance(device, deviceType, deviceInst))
  501. return false;
  502. EventDescriptor eventDescriptor;
  503. if (!createEventDescriptor(action, &eventDescriptor))
  504. return false;
  505. removeNode(deviceType, deviceInst, eventDescriptor.flags,eventDescriptor.eventCode, object);
  506. return true;
  507. }
  508. //------------------------------------------------------------------------------
  509. // This function is for the use of the control remapper.
  510. // It will only check against the console function (since all remappable commands are
  511. // bound using bind and not bindCmd).
  512. //
  513. const char* ActionMap::getBinding( const char* command )
  514. {
  515. char* returnString = Con::getReturnBuffer( 1024 );
  516. returnString[0] = 0;
  517. char buffer[256];
  518. char deviceBuffer[32];
  519. char keyBuffer[64];
  520. U32 devMapIndex = 0, nodeIndex = 0;
  521. while ( nextBoundNode( command, devMapIndex, nodeIndex ) )
  522. {
  523. const DeviceMap* deviceMap = mDeviceMaps[devMapIndex];
  524. if ( getDeviceName( deviceMap->deviceType, deviceMap->deviceInst, deviceBuffer ) )
  525. {
  526. const Node* node = &deviceMap->nodeMap[nodeIndex];
  527. const char* modifierString = getModifierString( node->modifiers );
  528. if ( getKeyString( node->action, keyBuffer ) )
  529. {
  530. dSprintf( buffer, sizeof( buffer ), "%s\t%s%s", deviceBuffer, modifierString, keyBuffer );
  531. if ( returnString[0] )
  532. dStrcat( returnString, "\t" );
  533. dStrcat( returnString, buffer );
  534. }
  535. }
  536. ++nodeIndex;
  537. }
  538. return returnString;
  539. }
  540. //------------------------------------------------------------------------------
  541. // This function is for the use of the control remapper.
  542. // The intent of this function is to determine if the given event descriptor is already
  543. // bound in this action map. If so, this function returns the command it is bound to.
  544. // If not, it returns NULL.
  545. //
  546. const char* ActionMap::getCommand( const char* device, const char* action )
  547. {
  548. U32 deviceType;
  549. U32 deviceInst;
  550. if ( getDeviceTypeAndInstance( device, deviceType, deviceInst ) )
  551. {
  552. EventDescriptor eventDescriptor;
  553. if ( createEventDescriptor( action, &eventDescriptor ) )
  554. {
  555. const ActionMap::Node* mapNode = findNode( deviceType, deviceInst, eventDescriptor.flags, eventDescriptor.eventCode );
  556. if ( mapNode )
  557. {
  558. if ( mapNode->flags & Node::BindCmd )
  559. {
  560. S32 bufferLen = dStrlen( mapNode->makeConsoleCommand ) + dStrlen( mapNode->breakConsoleCommand ) + 2;
  561. char* returnString = Con::getReturnBuffer( bufferLen );
  562. dSprintf( returnString, bufferLen, "%s\t%s",
  563. ( mapNode->makeConsoleCommand ? mapNode->makeConsoleCommand : "" ),
  564. ( mapNode->breakConsoleCommand ? mapNode->breakConsoleCommand : "" ) );
  565. return( returnString );
  566. }
  567. else
  568. return( mapNode->consoleFunction );
  569. }
  570. }
  571. }
  572. return( "" );
  573. }
  574. //------------------------------------------------------------------------------
  575. // This function returns whether or not the mapping specified is inverted.
  576. // Obviously, this should only be used for axes.
  577. bool ActionMap::isInverted( const char* device, const char* action )
  578. {
  579. U32 deviceType;
  580. U32 deviceInst;
  581. if ( getDeviceTypeAndInstance( device, deviceType, deviceInst ) )
  582. {
  583. EventDescriptor eventDescriptor;
  584. if ( createEventDescriptor( action, &eventDescriptor ) )
  585. {
  586. const ActionMap::Node* mapNode = findNode( deviceType, deviceInst, eventDescriptor.flags, eventDescriptor.eventCode );
  587. if ( mapNode )
  588. return( mapNode->flags & Node::Inverted );
  589. }
  590. }
  591. Con::errorf( "The input event specified by %s %s is not in this action map!", device, action );
  592. return( false );
  593. }
  594. //------------------------------------------------------------------------------
  595. F32 ActionMap::getScale( const char* device, const char* action )
  596. {
  597. U32 deviceType;
  598. U32 deviceInst;
  599. if ( getDeviceTypeAndInstance( device, deviceType, deviceInst ) )
  600. {
  601. EventDescriptor eventDescriptor;
  602. if ( createEventDescriptor( action, &eventDescriptor ) )
  603. {
  604. const ActionMap::Node* mapNode = findNode( deviceType, deviceInst, eventDescriptor.flags, eventDescriptor.eventCode );
  605. if ( mapNode )
  606. {
  607. if ( mapNode->flags & Node::HasScale )
  608. return( mapNode->scaleFactor );
  609. else
  610. return( 1.0f );
  611. }
  612. }
  613. }
  614. Con::errorf( "The input event specified by %s %s is not in this action map!", device, action );
  615. return( 1.0f );
  616. }
  617. //------------------------------------------------------------------------------
  618. const char* ActionMap::getDeadZone( const char* device, const char* action )
  619. {
  620. U32 deviceType;
  621. U32 deviceInst;
  622. if ( getDeviceTypeAndInstance( device, deviceType, deviceInst ) )
  623. {
  624. EventDescriptor eventDescriptor;
  625. if ( createEventDescriptor( action, &eventDescriptor ) )
  626. {
  627. const ActionMap::Node* mapNode = findNode( deviceType, deviceInst, eventDescriptor.flags, eventDescriptor.eventCode );
  628. if ( mapNode )
  629. {
  630. if ( mapNode->flags & Node::HasDeadZone )
  631. {
  632. char buf[64];
  633. dSprintf( buf, sizeof( buf ), "%g %g", mapNode->deadZoneBegin, mapNode->deadZoneEnd );
  634. char* returnString = Con::getReturnBuffer( dStrlen( buf ) + 1 );
  635. dStrcpy( returnString, buf );
  636. return( returnString );
  637. }
  638. else
  639. return( "0 0" );
  640. }
  641. }
  642. }
  643. Con::errorf( "The input event specified by %s %s is not in this action map!", device, action );
  644. return( "" );
  645. }
  646. //------------------------------------------------------------------------------
  647. const char* ActionMap::buildActionString( const InputEvent* event )
  648. {
  649. const char* modifierString = getModifierString( event->modifier );
  650. char objectBuffer[64];
  651. if ( !getKeyString( event->objInst, objectBuffer ) )
  652. return( "" );
  653. U32 returnLen = dStrlen( modifierString ) + dStrlen( objectBuffer ) + 2;
  654. char* returnString = Con::getReturnBuffer( returnLen );
  655. dSprintf( returnString, returnLen - 1, "%s%s", modifierString, objectBuffer );
  656. return( returnString );
  657. }
  658. //------------------------------------------------------------------------------
  659. bool ActionMap::getDeviceTypeAndInstance(const char *pDeviceName, U32 &deviceType, U32 &deviceInstance)
  660. {
  661. U32 offset = 0;
  662. if (dStrnicmp(pDeviceName, "keyboard", dStrlen("keyboard")) == 0)
  663. {
  664. deviceType = KeyboardDeviceType;
  665. offset = dStrlen("keyboard");
  666. }
  667. else if (dStrnicmp(pDeviceName, "mouse", dStrlen("mouse")) == 0)
  668. {
  669. deviceType = MouseDeviceType;
  670. offset = dStrlen("mouse");
  671. }
  672. else if (dStrnicmp(pDeviceName, "joystick", dStrlen("joystick")) == 0)
  673. {
  674. deviceType = JoystickDeviceType;
  675. offset = dStrlen("joystick");
  676. }
  677. else if (dStrnicmp(pDeviceName, "accelerometer", dStrlen("accelerometer")) == 0)
  678. {
  679. deviceType = AccelerometerDeviceType;
  680. offset = dStrlen("accelerometer");
  681. }
  682. else if (dStrnicmp(pDeviceName, "gyroscope", dStrlen("gyroscope")) == 0)
  683. {
  684. deviceType = GyroscopeDeviceType;
  685. offset = dStrlen("gyroscope");
  686. }
  687. else if (dStrnicmp(pDeviceName, "touchdevice", dStrlen("touchdevice")) == 0)
  688. {
  689. deviceType = ScreenTouchDeviceType;
  690. offset = dStrlen("touchdevice");
  691. }
  692. else
  693. return false;
  694. if (dStrlen(pDeviceName) > offset)
  695. {
  696. const char* pInst = pDeviceName + offset;
  697. S32 instNum = dAtoi(pInst);
  698. if (instNum < 0)
  699. deviceInstance = 0;
  700. else
  701. deviceInstance = instNum;
  702. }
  703. else
  704. deviceInstance = 0;
  705. return true;
  706. }
  707. //------------------------------------------------------------------------------
  708. bool ActionMap::getDeviceName(const U32 deviceType, const U32 deviceInstance, char* buffer)
  709. {
  710. switch (deviceType)
  711. {
  712. case KeyboardDeviceType:
  713. dStrcpy(buffer, "keyboard");
  714. break;
  715. case MouseDeviceType:
  716. dSprintf(buffer, 16, "mouse%d", deviceInstance);
  717. break;
  718. case JoystickDeviceType:
  719. dSprintf(buffer, 16, "joystick%d", deviceInstance);
  720. break;
  721. case AccelerometerDeviceType:
  722. dStrcpy(buffer, "accelerometer");
  723. break;
  724. case GyroscopeDeviceType:
  725. dStrcpy(buffer, "gyroscope");
  726. break;
  727. case ScreenTouchDeviceType:
  728. dStrcpy(buffer, "touchdevice");
  729. break;
  730. default:
  731. Con::errorf( "ActionMap::getDeviceName: unknown device type specified, %d (inst: %d)", deviceType, deviceInstance);
  732. return false;
  733. }
  734. return true;
  735. }
  736. //------------------------------------------------------------------------------
  737. const char* ActionMap::getModifierString(const U32 modifiers)
  738. {
  739. U32 realModifiers = modifiers;
  740. if ( modifiers & SI_LSHIFT || modifiers & SI_RSHIFT )
  741. realModifiers |= SI_SHIFT;
  742. if ( modifiers & SI_LCTRL || modifiers & SI_RCTRL )
  743. realModifiers |= SI_CTRL;
  744. if ( modifiers & SI_LALT || modifiers & SI_RALT )
  745. realModifiers |= SI_ALT;
  746. if ( modifiers & SI_MAC_LOPT || modifiers & SI_MAC_ROPT )
  747. realModifiers |= SI_MAC_OPT;
  748. switch (realModifiers & (SI_SHIFT|SI_CTRL|SI_ALT|SI_MAC_OPT)) {
  749. #if defined(TORQUE_OS_OSX)
  750. // optional code, to output alt as cmd on mac.
  751. // interpreter sees them as the same...
  752. case (SI_SHIFT|SI_CTRL|SI_ALT):
  753. return "cmd-shift-ctrl ";
  754. case (SI_SHIFT|SI_ALT):
  755. return "cmd-shift ";
  756. case (SI_CTRL|SI_ALT):
  757. return "cmd-ctrl ";
  758. case (SI_ALT):
  759. return "cmd ";
  760. #else
  761. case (SI_SHIFT|SI_CTRL|SI_ALT):
  762. return "shift-ctrl-alt ";
  763. case (SI_SHIFT|SI_ALT):
  764. return "shift-alt ";
  765. case (SI_CTRL|SI_ALT):
  766. return "ctrl-alt ";
  767. case (SI_ALT):
  768. return "alt ";
  769. #endif
  770. case (SI_SHIFT|SI_CTRL):
  771. return "shift-ctrl ";
  772. case (SI_SHIFT):
  773. return "shift ";
  774. case (SI_CTRL):
  775. return "ctrl ";
  776. // plus new mac cases:
  777. case (SI_ALT|SI_SHIFT|SI_CTRL|SI_MAC_OPT):
  778. return "cmd-shift-ctrl-opt ";
  779. case (SI_ALT|SI_SHIFT|SI_MAC_OPT):
  780. return "cmd-shift-opt ";
  781. case (SI_ALT|SI_CTRL|SI_MAC_OPT):
  782. return "cmd-ctrl-opt ";
  783. case (SI_ALT|SI_MAC_OPT):
  784. return "cmd-opt ";
  785. case (SI_SHIFT|SI_CTRL|SI_MAC_OPT):
  786. return "shift-ctrl-opt ";
  787. case (SI_SHIFT|SI_MAC_OPT):
  788. return "shift-opt ";
  789. case (SI_CTRL|SI_MAC_OPT):
  790. return "ctrl-opt ";
  791. case (SI_MAC_OPT):
  792. return "opt ";
  793. case 0:
  794. return "";
  795. default:
  796. AssertFatal(false, "Error, should never reach the default case in getModifierString");
  797. return "";
  798. }
  799. }
  800. //------------------------------------------------------------------------------
  801. bool ActionMap::getKeyString(const U32 action, char* buffer)
  802. {
  803. U16 asciiCode = Input::getAscii(action, STATE_LOWER);
  804. // if (action >= KEY_A && action <= KEY_Z) {
  805. // buffer[0] = char(action - KEY_A + 'a');
  806. // buffer[1] = '\0';
  807. // return true;
  808. // } else if (action >= KEY_0 && action <= KEY_9) {
  809. // buffer[0] = char(action - KEY_0 + '0');
  810. // buffer[1] = '\0';
  811. if ( (asciiCode != 0) && dIsDecentChar((char)asciiCode))
  812. {
  813. for (U32 i = 0; gAsciiMap[i].asciiCode != 0xFFFF; i++) {
  814. if (gAsciiMap[i].asciiCode == asciiCode)
  815. {
  816. dStrcpy(buffer, gAsciiMap[i].pDescription);
  817. return true;
  818. }
  819. }
  820. // Must not have found a string for that ascii code just record the char
  821. buffer[0] = char(asciiCode);
  822. buffer[1] = '\0';
  823. return true;
  824. }
  825. else
  826. {
  827. if (action >= KEY_A && action <= KEY_Z)
  828. {
  829. buffer[0] = char(action - KEY_A + 'a');
  830. buffer[1] = '\0';
  831. return true;
  832. }
  833. else if (action >= KEY_0 && action <= KEY_9) {
  834. buffer[0] = char(action - KEY_0 + '0');
  835. buffer[1] = '\0';
  836. return true;
  837. }
  838. for (U32 i = 0; gVirtualMap[i].code != 0xFFFFFFFF; i++) {
  839. if (gVirtualMap[i].code == action) {
  840. dStrcpy(buffer, gVirtualMap[i].pDescription);
  841. return true;
  842. }
  843. }
  844. }
  845. Con::errorf( "ActionMap::getKeyString: no string for action %d", action );
  846. return false;
  847. }
  848. //--------------------------------------------------------------------------
  849. bool ActionMap::processBindCmd(const char *device, const char *action, const char *makeCmd, const char *breakCmd)
  850. {
  851. U32 deviceType;
  852. U32 deviceInst;
  853. if(!getDeviceTypeAndInstance(device, deviceType, deviceInst))
  854. {
  855. Con::printf("processBindCmd: unknown device: %s", device);
  856. return false;
  857. }
  858. // Ok, we now have the deviceType and instance. Create an event descriptor
  859. // for the bind...
  860. //
  861. EventDescriptor eventDescriptor;
  862. if (createEventDescriptor(action, &eventDescriptor) == false) {
  863. Con::printf("Could not create a description for binding: %s", action);
  864. return false;
  865. }
  866. // SI_POV == SI_MOVE, and the POV works fine with bindCmd, so we have to add these manually.
  867. if( ( eventDescriptor.eventCode == SI_XAXIS ) ||
  868. ( eventDescriptor.eventCode == SI_YAXIS ) ||
  869. ( eventDescriptor.eventCode == SI_ZAXIS ) ||
  870. ( eventDescriptor.eventCode == SI_RXAXIS ) ||
  871. ( eventDescriptor.eventCode == SI_RYAXIS ) ||
  872. ( eventDescriptor.eventCode == SI_RZAXIS ) ||
  873. ( eventDescriptor.eventCode == SI_SLIDER ) ||
  874. ( eventDescriptor.eventCode == SI_XPOV ) ||
  875. ( eventDescriptor.eventCode == SI_YPOV ) ||
  876. ( eventDescriptor.eventCode == SI_XPOV2 ) ||
  877. ( eventDescriptor.eventCode == SI_YPOV2 ) ||
  878. ( eventDescriptor.eventCode == SI_ACCELX ) ||
  879. ( eventDescriptor.eventCode == SI_ACCELY ) ||
  880. ( eventDescriptor.eventCode == SI_ACCELZ ) ||
  881. ( eventDescriptor.eventCode == SI_GRAVX ) ||
  882. ( eventDescriptor.eventCode == SI_GRAVY ) ||
  883. ( eventDescriptor.eventCode == SI_GRAVZ ) ||
  884. ( eventDescriptor.eventCode == SI_GYROX ) ||
  885. ( eventDescriptor.eventCode == SI_GYROY ) ||
  886. ( eventDescriptor.eventCode == SI_GYROZ ) ||
  887. ( eventDescriptor.eventCode == SI_YAW ) ||
  888. ( eventDescriptor.eventCode == SI_PITCH ) ||
  889. ( eventDescriptor.eventCode == SI_ROLL ) )
  890. {
  891. Con::warnf( "ActionMap::processBindCmd - Cannot use 'bindCmd' with a move event type. Use 'bind' instead." );
  892. return false;
  893. }
  894. // Create the full bind entry, and place it in the map
  895. //
  896. // DMMTODO
  897. Node* pBindNode = getNode(deviceType, deviceInst,
  898. eventDescriptor.flags,
  899. eventDescriptor.eventCode);
  900. pBindNode->flags = Node::BindCmd;
  901. pBindNode->deadZoneBegin = 0;
  902. pBindNode->deadZoneEnd = 0;
  903. pBindNode->scaleFactor = 1;
  904. if(makeCmd[0])
  905. pBindNode->makeConsoleCommand = dStrdup(makeCmd);
  906. else
  907. pBindNode->makeConsoleCommand = dStrdup("");
  908. if(breakCmd[0])
  909. pBindNode->breakConsoleCommand = dStrdup(breakCmd);
  910. else
  911. pBindNode->breakConsoleCommand = dStrdup("");
  912. return true;
  913. }
  914. //------------------------------------------------------------------------------
  915. bool ActionMap::processBind(const U32 argc, const char** argv, SimObject* object)
  916. {
  917. // Ok, the bind will come in the following format:
  918. // [device] [key or button] <[param spec] [param] ...> [fnName]
  919. //
  920. const char* pDeviceName = argv[0];
  921. const char* pEvent = argv[1];
  922. const char* pFnName = argv[argc - 1];
  923. // Determine the device
  924. U32 deviceType;
  925. U32 deviceInst;
  926. if(!getDeviceTypeAndInstance(argv[0], deviceType, deviceInst))
  927. {
  928. Con::printf("processBind: unknown device: %s", pDeviceName);
  929. return false;
  930. }
  931. // Ok, we now have the deviceType and instance. Create an event descriptor
  932. // for the bind...
  933. //
  934. EventDescriptor eventDescriptor;
  935. if (createEventDescriptor(pEvent, &eventDescriptor) == false) {
  936. Con::printf("Could not create a description for binding: %s", pEvent);
  937. return false;
  938. }
  939. // Event has now been described, and device determined. we need now to extract
  940. // any modifiers that the action map will apply to incoming events before
  941. // calling the bound function...
  942. //
  943. // DMMTODO
  944. U32 assignedFlags = 0;
  945. F32 deadZoneBegin = 0.0f;
  946. F32 deadZoneEnd = 0.0f;
  947. F32 scaleFactor = 1.0f;
  948. if (argc != 3) {
  949. // We have the following: "[DSIR]" [deadZone] [scale]
  950. //
  951. const char* pSpec = argv[2];
  952. for (U32 i = 0; pSpec[i] != '\0'; i++) {
  953. switch (pSpec[i]) {
  954. case 'r': case 'R':
  955. assignedFlags |= Node::HasScale;
  956. break;
  957. case 's': case 'S':
  958. assignedFlags |= Node::HasScale;
  959. break;
  960. case 'd': case 'D':
  961. assignedFlags |= Node::HasDeadZone;
  962. break;
  963. case 'i': case 'I':
  964. assignedFlags |= Node::Inverted;
  965. break;
  966. default:
  967. AssertFatal(false, avar("Misunderstood specifier in bind (spec string: %s)",
  968. pSpec));
  969. }
  970. }
  971. // Ok, we have the flags. Scan the dead zone and scale, if any.
  972. //
  973. U32 curArg = 3;
  974. if (assignedFlags & Node::HasDeadZone) {
  975. dSscanf(argv[curArg], "%g %g", &deadZoneBegin, &deadZoneEnd);
  976. curArg++;
  977. }
  978. if (assignedFlags & Node::HasScale) {
  979. scaleFactor = dAtof(argv[curArg]);
  980. curArg++;
  981. }
  982. if (curArg != (argc - 1)) {
  983. AssertFatal(curArg == (argc - 1), "error in bind spec somewhere...");
  984. Con::printf("Improperly specified bind for key: %s", argv[2]);
  985. return false;
  986. }
  987. }
  988. // Ensure that the console function is properly specified?
  989. //
  990. // DMMTODO
  991. // Create the full bind entry, and place it in the map
  992. //
  993. // DMMTODO
  994. Node* pBindNode = getNode(deviceType, deviceInst,
  995. eventDescriptor.flags,
  996. eventDescriptor.eventCode, object);
  997. pBindNode->flags = assignedFlags;
  998. pBindNode->deadZoneBegin = deadZoneBegin;
  999. pBindNode->deadZoneEnd = deadZoneEnd;
  1000. pBindNode->scaleFactor = scaleFactor;
  1001. pBindNode->object = object;
  1002. pBindNode->consoleFunction = StringTable->insert(pFnName);
  1003. return true;
  1004. }
  1005. //------------------------------------------------------------------------------
  1006. bool ActionMap::processAction(const InputEvent* pEvent)
  1007. {
  1008. static const char *argv[4];
  1009. if (pEvent->action == SI_TOUCH) // Touches
  1010. {
  1011. static const char *args[4];
  1012. const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
  1013. if (pNode == NULL)
  1014. {
  1015. // Check to see if we clear the modifiers, do we find an action?
  1016. if (pEvent->modifier != 0)
  1017. pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
  1018. if (pNode == NULL)
  1019. return false;
  1020. }
  1021. // "Do nothing" bind:
  1022. if ( !pNode->consoleFunction[0] )
  1023. return( true );
  1024. // Ok, we're all set up, call the function.
  1025. args[0] = pNode->consoleFunction;
  1026. args[1] = pEvent->touchIDs; //Con::getReturnBuffer(pEvent->touchIDs);
  1027. args[2] = pEvent->touchesX; //Con::getReturnBuffer(pEvent->touchesX);
  1028. args[3] = pEvent->touchesY; //Con::getReturnBuffer(pEvent->touchesY);
  1029. if (pNode->object)
  1030. Con::executef(pNode->object, 2, args[0], args[1], args[2], args[3]);
  1031. else
  1032. Con::execute(4, args);
  1033. return true;
  1034. }
  1035. else if (pEvent->action == SI_MAKE) // KEYBOARD/BUTTON DOWN EVENT
  1036. {
  1037. const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
  1038. if (pNode == NULL)
  1039. {
  1040. // Check to see if we clear the modifiers, do we find an action?
  1041. if (pEvent->modifier != 0)
  1042. pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
  1043. if (pNode == NULL)
  1044. return false;
  1045. }
  1046. // Whadda ya know, we have this bound. Set up, and call the console
  1047. // function associated with it...
  1048. //
  1049. F32 value = pEvent->fValue;
  1050. if (pNode->flags & Node::Ranged)
  1051. {
  1052. value = (value * 2.0f) - 1.0f;
  1053. if (pNode->flags & Node::Inverted)
  1054. value *= -1.0f;
  1055. }
  1056. else
  1057. {
  1058. if (pNode->flags & Node::Inverted)
  1059. value = 1.0f - value;
  1060. }
  1061. if (pNode->flags & Node::HasScale)
  1062. value *= pNode->scaleFactor;
  1063. if (pNode->flags & Node::HasDeadZone)
  1064. if (value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd)
  1065. value = 0.0f;
  1066. // Ok, we're all set up, call the function.
  1067. if(pNode->flags & Node::BindCmd)
  1068. {
  1069. // it's a bind command
  1070. if(pNode->makeConsoleCommand)
  1071. Con::evaluate(pNode->makeConsoleCommand);
  1072. }
  1073. else if ( pNode->consoleFunction[0] )
  1074. {
  1075. argv[0] = pNode->consoleFunction;
  1076. argv[1] = Con::getFloatArg(value);
  1077. if (pNode->object)
  1078. Con::executef(pNode->object, 2, argv[0], argv[1]);
  1079. else
  1080. Con::execute(2, argv);
  1081. }
  1082. // [neo, 5/13/2007 - #3109]
  1083. // The execs/evaluate above could have called reentrant script code which made calls to
  1084. // bindCmd() etc, channging the node map underneath us. If enough nodes were added then
  1085. // the node map vector would realloc, with the result that pNode would then be pointing
  1086. // at garbage and cause a crash when passed to enterBreakEvent() below. So we just look
  1087. // it up again to be safe. This is not needed in the other cases below as we return right
  1088. // after the execs and don't use pNode again.
  1089. pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst );
  1090. if( pNode == NULL )
  1091. return true; // We already called any bound methods/functions so our job is done
  1092. //
  1093. // And enter the break into the table if this is a make event...
  1094. enterBreakEvent(pEvent, pNode);
  1095. return true;
  1096. }
  1097. else if (pEvent->action == SI_MOVE) // MOUSE/JOYSTICK MOVE EVENT
  1098. {
  1099. if (pEvent->deviceType == MouseDeviceType)
  1100. {
  1101. const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType);
  1102. if (pNode == NULL)
  1103. {
  1104. // Check to see if we clear the modifiers, do we find an action?
  1105. if (pEvent->modifier != 0)
  1106. pNode = findNode(pEvent->deviceType, pEvent->deviceInst,
  1107. 0, pEvent->objType);
  1108. if (pNode == NULL)
  1109. return false;
  1110. }
  1111. // "Do nothing" bind:
  1112. if ( !pNode->consoleFunction[0] )
  1113. return( true );
  1114. // Whadda ya know, we have this bound. Set up, and call the console
  1115. // function associated with it. Mouse events ignore range and dead
  1116. // zone params.
  1117. //
  1118. F32 value = pEvent->fValue;
  1119. if (pNode->flags & Node::Inverted)
  1120. value *= -1.0f;
  1121. if (pNode->flags & Node::HasScale)
  1122. value *= pNode->scaleFactor;
  1123. // Ok, we're all set up, call the function.
  1124. argv[0] = pNode->consoleFunction;
  1125. argv[1] = Con::getFloatArg(value);
  1126. if (pNode->object)
  1127. Con::executef(pNode->object, 2, argv[0], argv[1]);
  1128. else
  1129. Con::execute(2, argv);
  1130. return true;
  1131. }
  1132. else
  1133. {
  1134. // Joystick events...
  1135. const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst,
  1136. pEvent->modifier, pEvent->objType );
  1137. if ( pNode == NULL )
  1138. {
  1139. // Check to see if we clear the modifiers, do we find an action?
  1140. if (pEvent->modifier != 0)
  1141. pNode = findNode( pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objType );
  1142. if ( pNode == NULL )
  1143. return false;
  1144. }
  1145. // "Do nothing" bind:
  1146. if ( !pNode->consoleFunction[0] )
  1147. return( true );
  1148. // Whadda ya know, we have this bound. Set up, and call the console
  1149. // function associated with it. Joystick move events are the same as mouse
  1150. // move events except that they don't ignore dead zone.
  1151. //
  1152. F32 value = pEvent->fValue;
  1153. if ( pNode->flags & Node::Inverted )
  1154. value *= -1.0f;
  1155. if ( pNode->flags & Node::HasScale )
  1156. value *= pNode->scaleFactor;
  1157. if ( pNode->flags & Node::HasDeadZone )
  1158. if ( value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd )
  1159. value = 0.0f;
  1160. // Ok, we're all set up, call the function.
  1161. argv[0] = pNode->consoleFunction;
  1162. argv[1] = Con::getFloatArg( value );
  1163. if (pNode->object)
  1164. Con::executef(pNode->object, 2, argv[0], argv[1]);
  1165. else
  1166. Con::execute(2, argv);
  1167. return true;
  1168. }
  1169. }
  1170. else if (pEvent->action == SI_MOTION) // iOS MOTION EVENT
  1171. {
  1172. // iOS Accelerometer, Gyroscope and DeviceMotion processing
  1173. // Currently, this is identical to the joystick handling.
  1174. // This was copied over into its own section because this will
  1175. // give us a dedicated section to tweak processing based on iOS specific
  1176. // devices. No point in trying to mangle joystick code any further
  1177. const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
  1178. if ( pNode == NULL )
  1179. {
  1180. // Check to see if we clear the modifiers, do we find an action?
  1181. if (pEvent->modifier != 0)
  1182. pNode = findNode( pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objType );
  1183. if ( pNode == NULL )
  1184. return false;
  1185. }
  1186. // "Do nothing" bind:
  1187. if ( !pNode->consoleFunction[0] )
  1188. return( true );
  1189. F32 value = pEvent->fValue;
  1190. if ( pNode->flags & Node::Inverted )
  1191. value *= -1.0f;
  1192. if ( pNode->flags & Node::HasScale )
  1193. value *= pNode->scaleFactor;
  1194. if ( pNode->flags & Node::HasDeadZone )
  1195. if ( value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd )
  1196. value = 0.0f;
  1197. // Ok, we're all set up, call the function.
  1198. argv[0] = pNode->consoleFunction;
  1199. argv[1] = Con::getFloatArg( value );
  1200. if (pNode->object)
  1201. Con::executef(pNode->object, 2, argv[0], argv[1]);
  1202. else
  1203. Con::execute(2, argv);
  1204. return true;
  1205. }
  1206. else if (pEvent->action == SI_BREAK) // UP EVENT
  1207. {
  1208. return checkBreakTable(pEvent);
  1209. }
  1210. return false;
  1211. }
  1212. //------------------------------------------------------------------------------
  1213. void ActionMap::enterBreakEvent(const InputEvent* pEvent, const Node* pNode)
  1214. {
  1215. // There aren't likely to be many breaks outstanding at any one given time,
  1216. // so a simple linear search is probably sufficient. Note that the break table
  1217. // is static to the class, all breaks are directed to the action map that received
  1218. // the make.
  1219. //
  1220. S32 entry = -1;
  1221. for (U32 i = 0; i < (U32)smBreakTable.size(); i++) {
  1222. if (smBreakTable[i].deviceType == U32(pEvent->deviceType) &&
  1223. smBreakTable[i].deviceInst == U32(pEvent->deviceInst) &&
  1224. smBreakTable[i].objInst == U32(pEvent->objInst)) {
  1225. // Match.
  1226. entry = i;
  1227. break;
  1228. }
  1229. }
  1230. if (entry == -1) {
  1231. smBreakTable.increment();
  1232. entry = smBreakTable.size() - 1;
  1233. smBreakTable[entry].deviceType = pEvent->deviceType;
  1234. smBreakTable[entry].deviceInst = pEvent->deviceInst;
  1235. smBreakTable[entry].objInst = pEvent->objInst;
  1236. }
  1237. // Ok, we now have the entry, and know that the device desc. and the objInst match.
  1238. // Copy out the node information...
  1239. //
  1240. smBreakTable[entry].object = pNode->object;
  1241. // [neo, 5/7/2007 - #2975]
  1242. // object above can be deleted in between a make/break and so object will point
  1243. // to turfed memory and crash. To keep things simple we just store id as well so
  1244. // we can look it up to validate object ref.
  1245. smBreakTable[entry].objectId = pNode->object ? pNode->object->getId() : 0;
  1246. smBreakTable[entry].consoleFunction = pNode->consoleFunction;
  1247. if(pNode->breakConsoleCommand)
  1248. smBreakTable[entry].breakConsoleCommand = dStrdup(pNode->breakConsoleCommand);
  1249. else
  1250. smBreakTable[entry].breakConsoleCommand = NULL;
  1251. smBreakTable[entry].flags = pNode->flags;
  1252. smBreakTable[entry].deadZoneBegin = pNode->deadZoneBegin;
  1253. smBreakTable[entry].deadZoneEnd = pNode->deadZoneEnd;
  1254. smBreakTable[entry].scaleFactor = pNode->scaleFactor;
  1255. }
  1256. //------------------------------------------------------------------------------
  1257. bool ActionMap::checkBreakTable(const InputEvent* pEvent)
  1258. {
  1259. for (U32 i = 0; i < (U32)smBreakTable.size(); i++) {
  1260. if (smBreakTable[i].deviceType == U32(pEvent->deviceType) &&
  1261. smBreakTable[i].deviceInst == U32(pEvent->deviceInst) &&
  1262. smBreakTable[i].objInst == U32(pEvent->objInst)) {
  1263. // Match. Issue the break event...
  1264. //
  1265. F32 value = pEvent->fValue;
  1266. if (smBreakTable[i].flags & Node::Ranged) {
  1267. value = (value * 2.0f) - 1.0f;
  1268. if (smBreakTable[i].flags & Node::Inverted)
  1269. value *= -1.0f;
  1270. } else {
  1271. if (smBreakTable[i].flags & Node::Inverted)
  1272. value = 1.0f - value;
  1273. }
  1274. if (smBreakTable[i].flags & Node::HasScale)
  1275. value *= smBreakTable[i].scaleFactor;
  1276. if (smBreakTable[i].flags & Node::HasDeadZone)
  1277. if (value >= smBreakTable[i].deadZoneBegin &&
  1278. value <= smBreakTable[i].deadZoneEnd)
  1279. value = 0.0f;
  1280. // Ok, we're all set up, call the function.
  1281. if(smBreakTable[i].consoleFunction)
  1282. {
  1283. if ( smBreakTable[i].consoleFunction[0] )
  1284. {
  1285. static const char *argv[2];
  1286. argv[0] = smBreakTable[i].consoleFunction;
  1287. argv[1] = Con::getFloatArg(value);
  1288. if( smBreakTable[i].object )
  1289. {
  1290. // [neo, 5/7/2007 - #2975]
  1291. // object above can be deleted in between a make/break and so object will point
  1292. // to turfed memory and crash. To keep things simple we just store id as well so
  1293. // we can look it up to validate object ref.
  1294. if( smBreakTable[i].objectId > 0 && Sim::findObject( smBreakTable[i].objectId ) )
  1295. Con::executef(smBreakTable[i].object, 2, argv[0], argv[1]);
  1296. }
  1297. else
  1298. Con::execute(2, argv);
  1299. }
  1300. }
  1301. else if(smBreakTable[i].breakConsoleCommand)
  1302. {
  1303. Con::evaluate(smBreakTable[i].breakConsoleCommand);
  1304. dFree(smBreakTable[i].breakConsoleCommand);
  1305. }
  1306. smBreakTable.erase(i);
  1307. return true;
  1308. }
  1309. }
  1310. return false;
  1311. }
  1312. //------------------------------------------------------------------------------
  1313. bool ActionMap::handleEvent(const InputEvent* pEvent)
  1314. {
  1315. // Interate through the ActionMapSet until we get a map that
  1316. // handles the event or we run out of maps...
  1317. //
  1318. SimSet* pActionMapSet = Sim::getActiveActionMapSet();
  1319. AssertFatal(pActionMapSet && pActionMapSet->size() != 0,
  1320. "error, no ActiveMapSet or no global action map...");
  1321. for (SimSet::iterator itr = pActionMapSet->end() - 1;
  1322. itr > pActionMapSet->begin(); itr--) {
  1323. ActionMap* pMap = static_cast<ActionMap*>(*itr);
  1324. if (pMap->processAction(pEvent) == true)
  1325. return true;
  1326. }
  1327. return false;
  1328. }
  1329. //------------------------------------------------------------------------------
  1330. bool ActionMap::handleEventGlobal(const InputEvent* pEvent)
  1331. {
  1332. // Interate through the ActionMapSet until we get a map that
  1333. // handles the event or we run out of maps...
  1334. //
  1335. SimSet* pActionMapSet = Sim::getActiveActionMapSet();
  1336. AssertFatal(pActionMapSet && pActionMapSet->size() != 0,
  1337. "error, no ActiveMapSet or no global action map...");
  1338. return ((ActionMap*)pActionMapSet->first())->processAction(pEvent);
  1339. }
  1340. //------------------------------------------------------------------------------
  1341. //-------------------------------------- Key code to string mapping
  1342. // TODO: Add most obvious aliases...
  1343. //
  1344. CodeMapping gVirtualMap[] =
  1345. {
  1346. //-------------------------------------- KEYBOARD EVENTS
  1347. //
  1348. { "backspace", SI_KEY, KEY_BACKSPACE },
  1349. { "tab", SI_KEY, KEY_TAB },
  1350. { "return", SI_KEY, KEY_RETURN },
  1351. { "enter", SI_KEY, KEY_RETURN },
  1352. { "shift", SI_KEY, KEY_SHIFT },
  1353. { "ctrl", SI_KEY, KEY_CONTROL },
  1354. { "alt", SI_KEY, KEY_ALT },
  1355. { "pause", SI_KEY, KEY_PAUSE },
  1356. { "capslock", SI_KEY, KEY_CAPSLOCK },
  1357. { "escape", SI_KEY, KEY_ESCAPE },
  1358. { "space", SI_KEY, KEY_SPACE },
  1359. { "pagedown", SI_KEY, KEY_PAGE_DOWN },
  1360. { "pageup", SI_KEY, KEY_PAGE_UP },
  1361. { "end", SI_KEY, KEY_END },
  1362. { "home", SI_KEY, KEY_HOME },
  1363. { "left", SI_KEY, KEY_LEFT },
  1364. { "up", SI_KEY, KEY_UP },
  1365. { "right", SI_KEY, KEY_RIGHT },
  1366. { "down", SI_KEY, KEY_DOWN },
  1367. { "print", SI_KEY, KEY_PRINT },
  1368. { "insert", SI_KEY, KEY_INSERT },
  1369. { "delete", SI_KEY, KEY_DELETE },
  1370. { "help", SI_KEY, KEY_HELP },
  1371. { "win_lwindow", SI_KEY, KEY_WIN_LWINDOW },
  1372. { "win_rwindow", SI_KEY, KEY_WIN_RWINDOW },
  1373. { "win_apps", SI_KEY, KEY_WIN_APPS },
  1374. { "cmd", SI_KEY, KEY_ALT },
  1375. { "opt", SI_KEY, KEY_MAC_OPT },
  1376. { "lopt", SI_KEY, KEY_MAC_LOPT },
  1377. { "ropt", SI_KEY, KEY_MAC_ROPT },
  1378. { "numpad0", SI_KEY, KEY_NUMPAD0 },
  1379. { "numpad1", SI_KEY, KEY_NUMPAD1 },
  1380. { "numpad2", SI_KEY, KEY_NUMPAD2 },
  1381. { "numpad3", SI_KEY, KEY_NUMPAD3 },
  1382. { "numpad4", SI_KEY, KEY_NUMPAD4 },
  1383. { "numpad5", SI_KEY, KEY_NUMPAD5 },
  1384. { "numpad6", SI_KEY, KEY_NUMPAD6 },
  1385. { "numpad7", SI_KEY, KEY_NUMPAD7 },
  1386. { "numpad8", SI_KEY, KEY_NUMPAD8 },
  1387. { "numpad9", SI_KEY, KEY_NUMPAD9 },
  1388. { "numpadmult", SI_KEY, KEY_MULTIPLY },
  1389. { "numpadadd", SI_KEY, KEY_ADD },
  1390. { "numpadsep", SI_KEY, KEY_SEPARATOR },
  1391. { "numpadminus", SI_KEY, KEY_SUBTRACT },
  1392. { "numpaddecimal", SI_KEY, KEY_DECIMAL },
  1393. { "numpaddivide", SI_KEY, KEY_DIVIDE },
  1394. { "numpadenter", SI_KEY, KEY_NUMPADENTER },
  1395. { "f1", SI_KEY, KEY_F1 },
  1396. { "f2", SI_KEY, KEY_F2 },
  1397. { "f3", SI_KEY, KEY_F3 },
  1398. { "f4", SI_KEY, KEY_F4 },
  1399. { "f5", SI_KEY, KEY_F5 },
  1400. { "f6", SI_KEY, KEY_F6 },
  1401. { "f7", SI_KEY, KEY_F7 },
  1402. { "f8", SI_KEY, KEY_F8 },
  1403. { "f9", SI_KEY, KEY_F9 },
  1404. { "f10", SI_KEY, KEY_F10 },
  1405. { "f11", SI_KEY, KEY_F11 },
  1406. { "f12", SI_KEY, KEY_F12 },
  1407. { "f13", SI_KEY, KEY_F13 },
  1408. { "f14", SI_KEY, KEY_F14 },
  1409. { "f15", SI_KEY, KEY_F15 },
  1410. { "f16", SI_KEY, KEY_F16 },
  1411. { "f17", SI_KEY, KEY_F17 },
  1412. { "f18", SI_KEY, KEY_F18 },
  1413. { "f19", SI_KEY, KEY_F19 },
  1414. { "f20", SI_KEY, KEY_F20 },
  1415. { "f21", SI_KEY, KEY_F21 },
  1416. { "f22", SI_KEY, KEY_F22 },
  1417. { "f23", SI_KEY, KEY_F23 },
  1418. { "f24", SI_KEY, KEY_F24 },
  1419. { "numlock", SI_KEY, KEY_NUMLOCK },
  1420. { "scrolllock", SI_KEY, KEY_SCROLLLOCK },
  1421. { "lshift", SI_KEY, KEY_LSHIFT },
  1422. { "rshift", SI_KEY, KEY_RSHIFT },
  1423. { "lcontrol", SI_KEY, KEY_LCONTROL },
  1424. { "rcontrol", SI_KEY, KEY_RCONTROL },
  1425. { "lalt", SI_KEY, KEY_LALT },
  1426. { "ralt", SI_KEY, KEY_RALT },
  1427. { "tilde", SI_KEY, KEY_TILDE },
  1428. { "minus", SI_KEY, KEY_MINUS },
  1429. { "equals", SI_KEY, KEY_EQUALS },
  1430. { "lbracket", SI_KEY, KEY_LBRACKET },
  1431. { "rbracket", SI_KEY, KEY_RBRACKET },
  1432. { "backslash", SI_KEY, KEY_BACKSLASH },
  1433. { "semicolon", SI_KEY, KEY_SEMICOLON },
  1434. { "apostrophe", SI_KEY, KEY_APOSTROPHE },
  1435. { "comma", SI_KEY, KEY_COMMA },
  1436. { "period", SI_KEY, KEY_PERIOD },
  1437. { "slash", SI_KEY, KEY_SLASH },
  1438. { "lessthan", SI_KEY, KEY_OEM_102 },
  1439. //-------------------------------------- BUTTON EVENTS
  1440. // Joystick/Mouse buttons
  1441. { "button0", SI_BUTTON, KEY_BUTTON0 },
  1442. { "button1", SI_BUTTON, KEY_BUTTON1 },
  1443. { "button2", SI_BUTTON, KEY_BUTTON2 },
  1444. { "button3", SI_BUTTON, KEY_BUTTON3 },
  1445. { "button4", SI_BUTTON, KEY_BUTTON4 },
  1446. { "button5", SI_BUTTON, KEY_BUTTON5 },
  1447. { "button6", SI_BUTTON, KEY_BUTTON6 },
  1448. { "button7", SI_BUTTON, KEY_BUTTON7 },
  1449. { "button8", SI_BUTTON, KEY_BUTTON8 },
  1450. { "button9", SI_BUTTON, KEY_BUTTON9 },
  1451. { "button10", SI_BUTTON, KEY_BUTTON10 },
  1452. { "button11", SI_BUTTON, KEY_BUTTON11 },
  1453. { "button12", SI_BUTTON, KEY_BUTTON12 },
  1454. { "button13", SI_BUTTON, KEY_BUTTON13 },
  1455. { "button14", SI_BUTTON, KEY_BUTTON14 },
  1456. { "button15", SI_BUTTON, KEY_BUTTON15 },
  1457. { "button16", SI_BUTTON, KEY_BUTTON16 },
  1458. { "button17", SI_BUTTON, KEY_BUTTON17 },
  1459. { "button18", SI_BUTTON, KEY_BUTTON18 },
  1460. { "button19", SI_BUTTON, KEY_BUTTON19 },
  1461. { "button20", SI_BUTTON, KEY_BUTTON20 },
  1462. { "button21", SI_BUTTON, KEY_BUTTON21 },
  1463. { "button22", SI_BUTTON, KEY_BUTTON22 },
  1464. { "button23", SI_BUTTON, KEY_BUTTON23 },
  1465. { "button24", SI_BUTTON, KEY_BUTTON24 },
  1466. { "button25", SI_BUTTON, KEY_BUTTON25 },
  1467. { "button26", SI_BUTTON, KEY_BUTTON26 },
  1468. { "button27", SI_BUTTON, KEY_BUTTON27 },
  1469. { "button28", SI_BUTTON, KEY_BUTTON28 },
  1470. { "button29", SI_BUTTON, KEY_BUTTON29 },
  1471. { "button30", SI_BUTTON, KEY_BUTTON30 },
  1472. { "button31", SI_BUTTON, KEY_BUTTON31 },
  1473. //-------------------------------------- MOVE EVENTS
  1474. // Mouse/Joystick axes:
  1475. { "xaxis", SI_MOVE, SI_XAXIS },
  1476. { "yaxis", SI_MOVE, SI_YAXIS },
  1477. { "zaxis", SI_MOVE, SI_ZAXIS },
  1478. { "rxaxis", SI_MOVE, SI_RXAXIS },
  1479. { "ryaxis", SI_MOVE, SI_RYAXIS },
  1480. { "rzaxis", SI_MOVE, SI_RZAXIS },
  1481. { "slider", SI_MOVE, SI_SLIDER },
  1482. //-------------------------------------- POV EVENTS
  1483. // Joystick POV:
  1484. { "xpov", SI_POV, SI_XPOV },
  1485. { "ypov", SI_POV, SI_YPOV },
  1486. { "upov", SI_POV, SI_UPOV },
  1487. { "dpov", SI_POV, SI_DPOV },
  1488. { "lpov", SI_POV, SI_LPOV },
  1489. { "rpov", SI_POV, SI_RPOV },
  1490. { "xpov2", SI_POV, SI_XPOV2 },
  1491. { "ypov2", SI_POV, SI_YPOV2 },
  1492. { "upov2", SI_POV, SI_UPOV2 },
  1493. { "dpov2", SI_POV, SI_DPOV2 },
  1494. { "lpov2", SI_POV, SI_LPOV2 },
  1495. { "rpov2", SI_POV, SI_RPOV2 },
  1496. //-------------------------------------- MOTION EVENTS
  1497. // Accelerometer/Gyroscope axes:
  1498. { "accelx", SI_MOTION, SI_ACCELX },
  1499. { "accely", SI_MOTION, SI_ACCELY },
  1500. { "accelz", SI_MOTION, SI_ACCELZ },
  1501. { "gravityx", SI_MOTION, SI_GRAVX },
  1502. { "gravityy", SI_MOTION, SI_GRAVY },
  1503. { "gravityz", SI_MOTION, SI_GRAVZ },
  1504. { "gyrox", SI_MOTION, SI_GYROX },
  1505. { "gyroy", SI_MOTION, SI_GYROY },
  1506. { "gyroz", SI_MOTION, SI_GYROZ },
  1507. { "yaw", SI_MOTION, SI_YAW },
  1508. { "pitch", SI_MOTION, SI_PITCH },
  1509. { "roll", SI_MOTION, SI_ROLL },
  1510. { "touchdown", SI_TOUCH, SI_TOUCHDOWN },
  1511. { "touchup", SI_TOUCH, SI_TOUCHUP },
  1512. { "touchmove", SI_TOUCH, SI_TOUCHMOVE },
  1513. { "gesture", SI_TOUCH, SI_GESTURE },
  1514. //-------------------------------------- MISCELLANEOUS EVENTS
  1515. //
  1516. { "anykey", SI_KEY, KEY_ANYKEY },
  1517. { "nomatch", SI_UNKNOWN, 0xFFFFFFFF }
  1518. };
  1519. AsciiMapping gAsciiMap[] =
  1520. {
  1521. //--- KEYBOARD EVENTS
  1522. //
  1523. { "space", 0x0020 },
  1524. //{ "exclamation", 0x0021 },
  1525. { "doublequote", 0x0022 },
  1526. //{ "pound", 0x0023 },
  1527. //{ "ampersand", 0x0026 },
  1528. { "apostrophe", 0x0027 },
  1529. //{ "lparen", 0x0028 },
  1530. //{ "rparen", 0x0029 },
  1531. { "comma", 0x002c },
  1532. { "minus", 0x002d },
  1533. { "period", 0x002e },
  1534. //{ "slash", 0x002f },
  1535. //{ "colon", 0x003a },
  1536. //{ "semicolon", 0x003b },
  1537. //{ "lessthan", 0x003c },
  1538. //{ "equals", 0x003d },
  1539. //{ "morethan", 0x003e },
  1540. //{ "lbracket", 0x005b },
  1541. { "backslash", 0x005c },
  1542. //{ "rbracket", 0x005d },
  1543. //{ "circumflex", 0x005e },
  1544. //{ "underscore", 0x005f },
  1545. { "grave", 0x0060 },
  1546. //{ "tilde", 0x007e },
  1547. //{ "vertbar", 0x007c },
  1548. //{ "exclamdown", 0x00a1 },
  1549. //{ "cent", 0x00a2 },
  1550. //{ "sterling", 0x00a3 },
  1551. //{ "currency", 0x00a4 },
  1552. //{ "brokenbar", 0x00a6 },
  1553. //{ "ring", 0x00b0 },
  1554. //{ "plusminus", 0x00b1 },
  1555. { "super2", 0x00b2 },
  1556. { "super3", 0x00b3 },
  1557. { "acute", 0x00b4 },
  1558. //{ "mu", 0x00b5 },
  1559. //{ "ordmasculine", 0x00ba },
  1560. //{ "questiondown", 0x00bf },
  1561. //{ "gemandbls", 0x00df },
  1562. //{ "agrave", 0x00e0 },
  1563. //{ "aacute", 0x00e1 },
  1564. //{ "acircumflex", 0x00e2 },
  1565. //{ "atilde", 0x00e3 },
  1566. //{ "adieresis", 0x00e4 },
  1567. //{ "aring", 0x00e5 },
  1568. //{ "ae", 0x00e6 },
  1569. //{ "ccedille", 0x00e7 },
  1570. //{ "egrave", 0x00e8 },
  1571. //{ "eacute", 0x00e9 },
  1572. //{ "ecircumflex", 0x00ea },
  1573. //{ "edieresis", 0x00eb },
  1574. //{ "igrave", 0x00ec },
  1575. //{ "iacute", 0x00ed },
  1576. //{ "icircumflex", 0x00ee },
  1577. //{ "idieresis", 0x00ef },
  1578. //{ "ntilde", 0x00f1 },
  1579. //{ "ograve", 0x00f2 },
  1580. //{ "oacute", 0x00f3 },
  1581. //{ "ocircumflex", 0x00f4 },
  1582. //{ "otilde", 0x00f5 },
  1583. //{ "odieresis", 0x00f6 },
  1584. //{ "divide", 0x00f7 },
  1585. //{ "oslash", 0x00f8 },
  1586. //{ "ugrave", 0x00f9 },
  1587. //{ "uacute", 0x00fa },
  1588. //{ "ucircumflex", 0x00fb },
  1589. //{ "udieresis", 0x00fc },
  1590. //{ "ygrave", 0x00fd },
  1591. //{ "thorn", 0x00fe },
  1592. //{ "ydieresis", 0x00ff },
  1593. { "nomatch", 0xFFFF }
  1594. };
  1595. ////Device Event Types
  1596. //#define SI_UNKNOWN 0x01
  1597. //#define SI_BUTTON 0x02
  1598. //#define SI_POV 0x03
  1599. //#define SI_XPOV 0x04
  1600. //#define SI_YPOV 0x05
  1601. //#define SI_UPOV 0x06
  1602. //#define SI_DPOV 0x07
  1603. //#define SI_LPOV 0x08
  1604. //#define SI_RPOV 0x09
  1605. //#define SI_KEY 0x0A
  1606. //#define SI_XAXIS 0x0B
  1607. //#define SI_YAXIS 0x0C
  1608. //#define SI_ZAXIS 0x0D
  1609. //#define SI_RXAXIS 0x0E
  1610. //#define SI_RYAXIS 0x0F
  1611. //#define SI_RZAXIS 0x10
  1612. //#define SI_SLIDER 0x11