2
0

actionMap.cc 79 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375
  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. #define CONST_E 2.7182818284590452353602874f
  33. IMPLEMENT_CONOBJECT(ActionMap);
  34. // This is used for determing keys that have ascii codes for the foreign keyboards. IsAlpha doesn't work on foreign keys.
  35. #define dIsDecentChar(c) (((char(0xa0) <= (c)) && ((c) <= char(0xff))) || (( char(0x21) <= (c)) && ((c) <= char(0x7e))) || (( char(0x91) <= (c)) && ((c) <= char(0x92))))
  36. struct CodeMapping
  37. {
  38. const char* pDescription;
  39. U8 type;
  40. U32 code;
  41. };
  42. struct AsciiMapping
  43. {
  44. const char* pDescription;
  45. U16 asciiCode;
  46. };
  47. extern CodeMapping gVirtualMap[];
  48. extern AsciiMapping gAsciiMap[];
  49. //------------------------------------------------------------------------------
  50. //-------------------------------------- Action maps
  51. //
  52. Vector<ActionMap::BreakEntry> ActionMap::smBreakTable(__FILE__, __LINE__);
  53. //------------------------------------------------------------------------------
  54. ActionMap::ActionMap()
  55. {
  56. VECTOR_SET_ASSOCIATION(mDeviceMaps);
  57. }
  58. //------------------------------------------------------------------------------
  59. ActionMap::~ActionMap()
  60. {
  61. for (U32 i = 0; i < (U32)mDeviceMaps.size(); i++)
  62. delete mDeviceMaps[i];
  63. mDeviceMaps.clear();
  64. }
  65. //------------------------------------------------------------------------------
  66. ActionMap::DeviceMap::~DeviceMap()
  67. {
  68. for(U32 i = 0; i < (U32)nodeMap.size(); i++)
  69. {
  70. dFree(nodeMap[i].makeConsoleCommand);
  71. dFree(nodeMap[i].breakConsoleCommand);
  72. }
  73. }
  74. //------------------------------------------------------------------------------
  75. bool ActionMap::onAdd()
  76. {
  77. if (Parent::onAdd() == false)
  78. return false;
  79. Sim::getActionMapGroup()->addObject(this);
  80. return true;
  81. }
  82. //--------------------------------------------------------------------------
  83. void ActionMap::dumpActionMap(const char* fileName, const bool append) const
  84. {
  85. if (fileName != NULL) {
  86. // Dump the deletion, and creation script commands, followed by all the binds
  87. // to a script.
  88. FileStream iostrm;
  89. if ( !ResourceManager->openFileForWrite( iostrm, fileName, append ? FileStream::WriteAppend : FileStream::Write ) )
  90. {
  91. Con::errorf( "Unable to open file '%s' for writing.", fileName );
  92. return;
  93. }
  94. char lineBuffer[1024];
  95. if ( append )
  96. iostrm.setPosition( iostrm.getStreamSize() );
  97. else
  98. {
  99. // IMPORTANT -- do NOT change the following line, it identifies the file as an input map file
  100. dStrcpy( lineBuffer, "// Torque Input Map File\n" );
  101. iostrm.write( dStrlen( lineBuffer ), lineBuffer );
  102. }
  103. dSprintf(lineBuffer, 1023, "if (isObject(%s)) %s.delete();\n"
  104. "new ActionMap(%s);\n", getName(), getName(), getName());
  105. iostrm.write(dStrlen(lineBuffer), lineBuffer);
  106. // Dump all the binds to the console...
  107. for (S32 i = 0; i < mDeviceMaps.size(); i++) {
  108. const DeviceMap* pDevMap = mDeviceMaps[i];
  109. char devbuffer[32];
  110. getDeviceName(pDevMap->deviceType, pDevMap->deviceInst, devbuffer);
  111. for (S32 j = 0; j < pDevMap->nodeMap.size(); j++) {
  112. const Node& rNode = pDevMap->nodeMap[j];
  113. const char* pModifierString = getModifierString(rNode.modifiers);
  114. char objectbuffer[64];
  115. if (getKeyString(rNode.action, objectbuffer) == false)
  116. continue;
  117. const char* command = (rNode.flags & Node::BindCmd) ? "bindCmd" : "bind";
  118. dSprintf(lineBuffer, 1023, "%s.%s(%s, \"%s%s\"",
  119. getName(),
  120. command,
  121. devbuffer,
  122. pModifierString, objectbuffer);
  123. if (rNode.flags & (Node::HasScale|Node::HasDeadZone|Node::Ranged|Node::Inverted)) {
  124. char buff[10];
  125. U32 curr = 0;
  126. buff[curr++] = ',';
  127. buff[curr++] = ' ';
  128. if (rNode.flags & Node::HasScale)
  129. buff[curr++] = 'S';
  130. if (rNode.flags & Node::Ranged)
  131. buff[curr++] = 'R';
  132. if (rNode.flags & Node::HasDeadZone)
  133. buff[curr++] = 'D';
  134. if (rNode.flags & Node::Inverted)
  135. buff[curr++] = 'I';
  136. buff[curr] = '\0';
  137. dStrcat(lineBuffer, buff);
  138. }
  139. if (rNode.flags & Node::HasDeadZone) {
  140. char buff[64];
  141. dSprintf(buff, 63, ", \"%g %g\"", rNode.deadZoneBegin, rNode.deadZoneEnd);
  142. dStrcat(lineBuffer, buff);
  143. }
  144. if (rNode.flags & Node::HasScale) {
  145. char buff[64];
  146. dSprintf(buff, 63, ", %g", rNode.scaleFactor);
  147. dStrcat(lineBuffer, buff);
  148. }
  149. if (rNode.flags & Node::BindCmd) {
  150. if (rNode.makeConsoleCommand) {
  151. dStrcat(lineBuffer, ", \"");
  152. U32 pos = dStrlen(lineBuffer);
  153. expandEscape(lineBuffer + pos, rNode.makeConsoleCommand);
  154. dStrcat(lineBuffer, "\"");
  155. } else {
  156. dStrcat(lineBuffer, ", \"\"");
  157. }
  158. if (rNode.breakConsoleCommand) {
  159. dStrcat(lineBuffer, ", \"");
  160. U32 pos = dStrlen(lineBuffer);
  161. expandEscape(lineBuffer + pos, rNode.breakConsoleCommand);
  162. dStrcat(lineBuffer, "\"");
  163. }
  164. else
  165. dStrcat(lineBuffer, ", \"\"");
  166. } else {
  167. dStrcat(lineBuffer, ", ");
  168. dStrcat(lineBuffer, rNode.consoleFunction);
  169. }
  170. dStrcat(lineBuffer, ");\n");
  171. iostrm.write(dStrlen(lineBuffer), lineBuffer);
  172. }
  173. }
  174. iostrm.close();
  175. }
  176. else {
  177. // Dump all the binds to the console...
  178. for (S32 i = 0; i < mDeviceMaps.size(); i++) {
  179. const DeviceMap* pDevMap = mDeviceMaps[i];
  180. char devbuffer[32];
  181. getDeviceName(pDevMap->deviceType, pDevMap->deviceInst, devbuffer);
  182. for (S32 j = 0; j < pDevMap->nodeMap.size(); j++) {
  183. const Node& rNode = pDevMap->nodeMap[j];
  184. const char* pModifierString = getModifierString(rNode.modifiers);
  185. char keybuffer[64];
  186. if (getKeyString(rNode.action, keybuffer) == false)
  187. continue;
  188. const char* command = (rNode.flags & Node::BindCmd) ? "bindCmd" : "bind";
  189. char finalBuffer[1024];
  190. dSprintf(finalBuffer, 1023, "%s.%s(%s, \"%s%s\"",
  191. getName(),
  192. command,
  193. devbuffer,
  194. pModifierString, keybuffer);
  195. if (rNode.flags & (Node::HasScale|Node::HasDeadZone|Node::Ranged|Node::Inverted)) {
  196. char buff[10];
  197. U32 curr = 0;
  198. buff[curr++] = ',';
  199. buff[curr++] = ' ';
  200. if (rNode.flags & Node::HasScale)
  201. buff[curr++] = 'S';
  202. if (rNode.flags & Node::Ranged)
  203. buff[curr++] = 'R';
  204. if (rNode.flags & Node::HasDeadZone)
  205. buff[curr++] = 'D';
  206. if (rNode.flags & Node::Inverted)
  207. buff[curr++] = 'I';
  208. buff[curr] = '\0';
  209. dStrcat(finalBuffer, buff);
  210. }
  211. if (rNode.flags & Node::HasDeadZone) {
  212. char buff[64];
  213. dSprintf(buff, 63, ", \"%g %g\"", rNode.deadZoneBegin, rNode.deadZoneEnd);
  214. dStrcat(finalBuffer, buff);
  215. }
  216. if (rNode.flags & Node::HasScale) {
  217. char buff[64];
  218. dSprintf(buff, 63, ", %g", rNode.scaleFactor);
  219. dStrcat(finalBuffer, buff);
  220. }
  221. if (rNode.flags & Node::BindCmd) {
  222. if (rNode.makeConsoleCommand) {
  223. dStrcat(finalBuffer, ", \"");
  224. dStrcat(finalBuffer, rNode.makeConsoleCommand);
  225. dStrcat(finalBuffer, "\"");
  226. } else {
  227. dStrcat(finalBuffer, ", \"\"");
  228. }
  229. if (rNode.breakConsoleCommand) {
  230. dStrcat(finalBuffer, ", \"");
  231. dStrcat(finalBuffer, rNode.breakConsoleCommand);
  232. dStrcat(finalBuffer, "\"");
  233. }
  234. else
  235. dStrcat(finalBuffer, ", \"\"");
  236. } else {
  237. dStrcat(finalBuffer, ", ");
  238. dStrcat(finalBuffer, rNode.consoleFunction);
  239. }
  240. dStrcat(finalBuffer, ");");
  241. Con::printf(finalBuffer);
  242. }
  243. }
  244. }
  245. }
  246. //--------------------------------------------------------------------------
  247. bool ActionMap::createEventDescriptor(const char* pEventString, EventDescriptor* pDescriptor)
  248. {
  249. char copyBuffer[256];
  250. dStrcpy(copyBuffer, pEventString);
  251. // Do we have modifiers?
  252. char* pSpace = dStrchr(copyBuffer, ' ');
  253. char* pObjectString;
  254. if (pSpace != NULL) {
  255. // Yes. Parse them out...
  256. //
  257. pDescriptor->flags = 0;
  258. pObjectString = pSpace + 1;
  259. pSpace[0] = '\0';
  260. char* pModifier = dStrtok(copyBuffer, "-");
  261. while (pModifier != NULL) {
  262. if (dStricmp(pModifier, "shift") == 0) {
  263. pDescriptor->flags |= SI_SHIFT;
  264. } else if (dStricmp(pModifier, "lshift") == 0) {
  265. pDescriptor->flags |= SI_LSHIFT;
  266. } else if (dStricmp(pModifier, "rshift") == 0) {
  267. pDescriptor->flags |= SI_RSHIFT;
  268. } else if (dStricmp(pModifier, "ctrl") == 0) {
  269. pDescriptor->flags |= SI_CTRL;
  270. } else if (dStricmp(pModifier, "lctrl") == 0) {
  271. pDescriptor->flags |= SI_LCTRL;
  272. } else if (dStricmp(pModifier, "rctrl") == 0) {
  273. pDescriptor->flags |= SI_RCTRL;
  274. } else if (dStricmp(pModifier, "alt") == 0) {
  275. pDescriptor->flags |= SI_ALT;
  276. } else if (dStricmp(pModifier, "lalt") == 0) {
  277. pDescriptor->flags |= SI_LALT;
  278. } else if (dStricmp(pModifier, "ralt") == 0) {
  279. pDescriptor->flags |= SI_RALT;
  280. } else if (dStricmp(pModifier, "cmd") == 0) {
  281. pDescriptor->flags |= SI_ALT;
  282. } else if (dStricmp(pModifier, "opt") == 0) {
  283. pDescriptor->flags |= SI_MAC_OPT;
  284. } else if (dStricmp(pModifier, "lopt") == 0) {
  285. pDescriptor->flags |= SI_MAC_LOPT;
  286. } else if (dStricmp(pModifier, "ropt") == 0) {
  287. pDescriptor->flags |= SI_MAC_ROPT;
  288. }
  289. pModifier = dStrtok(NULL, "-");
  290. }
  291. } else {
  292. // No.
  293. pDescriptor->flags = 0;
  294. pObjectString = copyBuffer;
  295. }
  296. // Now we need to map the key string to the proper KEY code from event.h
  297. //
  298. AssertFatal(dStrlen(pObjectString) != 0, "Error, no key was specified!");
  299. if (dStrlen(pObjectString) == 1)
  300. {
  301. if (dIsDecentChar(*pObjectString)) // includes foreign chars
  302. {
  303. U16 asciiCode = (*pObjectString);
  304. // clear out the FF in upper 8bits for foreign keys??
  305. asciiCode &= 0xFF;
  306. U16 keyCode = Input::getKeyCode(asciiCode);
  307. if ( keyCode >= KEY_0 )
  308. {
  309. pDescriptor->eventType = SI_KEY;
  310. pDescriptor->eventCode = keyCode;
  311. return true;
  312. }
  313. else if (dIsalpha(*pObjectString) == true)
  314. {
  315. pDescriptor->eventType = SI_KEY;
  316. pDescriptor->eventCode = KEY_A+dTolower(*pObjectString)-'a';
  317. return true;
  318. }
  319. else if (dIsdigit(*pObjectString) == true)
  320. {
  321. pDescriptor->eventType = SI_KEY;
  322. pDescriptor->eventCode = KEY_0+(*pObjectString)-'0';
  323. return true;
  324. }
  325. }
  326. return false;
  327. }
  328. else
  329. {
  330. pDescriptor->eventCode = 0;
  331. // Gotta search through the Ascii table...
  332. for (U16 i = 0; gAsciiMap[i].asciiCode != 0xFFFF; i++)
  333. {
  334. if (dStricmp(pObjectString, gAsciiMap[i].pDescription) == 0)
  335. {
  336. U16 asciiCode = gAsciiMap[i].asciiCode;
  337. U16 keyCode = Input::getKeyCode(asciiCode);
  338. if ( keyCode >= KEY_0 )
  339. {
  340. pDescriptor->eventType = SI_KEY;
  341. pDescriptor->eventCode = keyCode;
  342. return(true);
  343. }
  344. else
  345. {
  346. break;
  347. }
  348. }
  349. }
  350. // Didn't find an ascii match. Check the virtual map table
  351. for (U32 j = 0; gVirtualMap[j].code != 0xFFFFFFFF; j++)
  352. {
  353. if (dStricmp(pObjectString, gVirtualMap[j].pDescription) == 0)
  354. {
  355. pDescriptor->eventType = gVirtualMap[j].type;
  356. pDescriptor->eventCode = gVirtualMap[j].code;
  357. return true;
  358. }
  359. }
  360. }
  361. return false;
  362. }
  363. //------------------------------------------------------------------------------
  364. ActionMap::Node* ActionMap::getNode(const U32 inDeviceType, const U32 inDeviceInst,
  365. const U32 inModifiers, const U32 inAction,SimObject* object /*= NULL*/)
  366. {
  367. // DMMTODO - Slow INITIAL implementation. Replace with a faster version...
  368. //
  369. DeviceMap* pDeviceMap = NULL;
  370. U32 i;
  371. for (i = 0; i < (U32)mDeviceMaps.size(); i++)
  372. {
  373. if (mDeviceMaps[i]->deviceType == inDeviceType &&
  374. mDeviceMaps[i]->deviceInst == inDeviceInst) {
  375. pDeviceMap = mDeviceMaps[i];
  376. break;
  377. }
  378. }
  379. if (pDeviceMap == NULL)
  380. {
  381. mDeviceMaps.increment();
  382. mDeviceMaps.last() = new DeviceMap;
  383. pDeviceMap = mDeviceMaps.last();
  384. pDeviceMap->deviceInst = inDeviceInst;
  385. pDeviceMap->deviceType = inDeviceType;
  386. }
  387. for (i = 0; i < (U32)pDeviceMap->nodeMap.size(); i++)
  388. {
  389. if (pDeviceMap->nodeMap[i].modifiers == inModifiers &&
  390. pDeviceMap->nodeMap[i].action == inAction &&
  391. ( (object != NULL) ? object == pDeviceMap->nodeMap[i].object : true )) // Check for an object match if the object exists
  392. {
  393. return &pDeviceMap->nodeMap[i];
  394. }
  395. }
  396. // If we're here, the node doesn't exist. create it.
  397. pDeviceMap->nodeMap.increment();
  398. Node* pRetNode = &pDeviceMap->nodeMap.last();
  399. pRetNode->modifiers = inModifiers;
  400. pRetNode->action = inAction;
  401. pRetNode->flags = 0;
  402. pRetNode->deadZoneBegin = 0.0;
  403. pRetNode->deadZoneEnd = 0.0;
  404. pRetNode->scaleFactor = 1.0;
  405. pRetNode->consoleFunction = NULL;
  406. pRetNode->makeConsoleCommand = NULL;
  407. pRetNode->breakConsoleCommand = NULL;
  408. //[neob, 5/7/2007 - #2975]
  409. pRetNode->object = 0;
  410. return pRetNode;
  411. }
  412. //------------------------------------------------------------------------------
  413. void ActionMap::removeNode(const U32 inDeviceType, const U32 inDeviceInst, const U32 inModifiers, const U32 inAction, SimObject* object /*= NULL*/)
  414. {
  415. // DMMTODO - Slow INITIAL implementation. Replace with a faster version...
  416. //
  417. DeviceMap* pDeviceMap = NULL;
  418. U32 i;
  419. for (i = 0; i < (U32)mDeviceMaps.size(); i++) {
  420. if (mDeviceMaps[i]->deviceType == inDeviceType &&
  421. mDeviceMaps[i]->deviceInst == inDeviceInst) {
  422. pDeviceMap = mDeviceMaps[i];
  423. break;
  424. }
  425. }
  426. if (pDeviceMap == NULL)
  427. return;
  428. U32 realMods = inModifiers;
  429. if (realMods & SI_SHIFT)
  430. realMods |= SI_SHIFT;
  431. if (realMods & SI_CTRL)
  432. realMods |= SI_CTRL;
  433. if (realMods & SI_ALT)
  434. realMods |= SI_ALT;
  435. if (realMods & SI_MAC_OPT)
  436. realMods |= SI_MAC_OPT;
  437. for (i = 0; i < (U32)pDeviceMap->nodeMap.size(); i++) {
  438. if (pDeviceMap->nodeMap[i].modifiers == realMods &&
  439. pDeviceMap->nodeMap[i].action == inAction &&
  440. ( (object != NULL) ? object == pDeviceMap->nodeMap[i].object : true ))
  441. {
  442. dFree(pDeviceMap->nodeMap[i].makeConsoleCommand);
  443. dFree(pDeviceMap->nodeMap[i].breakConsoleCommand);
  444. pDeviceMap->nodeMap.erase(i);
  445. }
  446. }
  447. }
  448. //------------------------------------------------------------------------------
  449. const ActionMap::Node* ActionMap::findNode(const U32 inDeviceType, const U32 inDeviceInst,
  450. const U32 inModifiers, const U32 inAction)
  451. {
  452. // DMMTODO - Slow INITIAL implementation. Replace with a faster version...
  453. //
  454. DeviceMap* pDeviceMap = NULL;
  455. U32 i;
  456. for (i = 0; i < (U32)mDeviceMaps.size(); i++)
  457. {
  458. if (mDeviceMaps[i]->deviceType == inDeviceType && mDeviceMaps[i]->deviceInst == inDeviceInst)
  459. {
  460. pDeviceMap = mDeviceMaps[i];
  461. break;
  462. }
  463. }
  464. if (pDeviceMap == NULL)
  465. return NULL;
  466. U32 realMods = inModifiers;
  467. if (realMods & SI_SHIFT)
  468. realMods |= SI_SHIFT;
  469. if (realMods & SI_CTRL)
  470. realMods |= SI_CTRL;
  471. if (realMods & SI_ALT)
  472. realMods |= SI_ALT;
  473. if (realMods & SI_MAC_OPT)
  474. realMods |= SI_MAC_OPT;
  475. for (i = 0; i < (U32)pDeviceMap->nodeMap.size(); i++)
  476. {
  477. if (pDeviceMap->nodeMap[i].action == KEY_ANYKEY && pDeviceMap->nodeMap[i].modifiers == realMods && dIsDecentChar(inAction))
  478. return &pDeviceMap->nodeMap[i];
  479. else if (inModifiers == 0 && pDeviceMap->nodeMap[i].modifiers == 0 && pDeviceMap->nodeMap[i].action == inAction)
  480. return &pDeviceMap->nodeMap[i];
  481. else if (pDeviceMap->nodeMap[i].modifiers == realMods && pDeviceMap->nodeMap[i].action == inAction)
  482. return &pDeviceMap->nodeMap[i];
  483. }
  484. return NULL;
  485. }
  486. //------------------------------------------------------------------------------
  487. bool ActionMap::findBoundNode( const char* function, U32 &devMapIndex, U32 &nodeIndex )
  488. {
  489. devMapIndex = 0;
  490. nodeIndex = 0;
  491. return nextBoundNode( function, devMapIndex, nodeIndex );
  492. }
  493. bool ActionMap::nextBoundNode( const char* function, U32 &devMapIndex, U32 &nodeIndex )
  494. {
  495. // Loop through all of the existing nodes to find the one mapped to the
  496. // given function:
  497. for ( U32 i = devMapIndex; i < (U32)mDeviceMaps.size(); i++ )
  498. {
  499. const DeviceMap* dvcMap = mDeviceMaps[i];
  500. for ( U32 j = nodeIndex; j < (U32)dvcMap->nodeMap.size(); j++ )
  501. {
  502. const Node* node = &dvcMap->nodeMap[j];
  503. if ( !( node->flags & Node::BindCmd ) && ( dStricmp( function, node->consoleFunction ) == 0 ) )
  504. {
  505. devMapIndex = i;
  506. nodeIndex = j;
  507. return( true );
  508. }
  509. }
  510. nodeIndex = 0;
  511. }
  512. return( false );
  513. }
  514. //------------------------------------------------------------------------------
  515. bool ActionMap::processUnbind(const char *device, const char *action, SimObject* object /*= NULL*/)
  516. {
  517. U32 deviceType;
  518. U32 deviceInst;
  519. if(!getDeviceTypeAndInstance(device, deviceType, deviceInst))
  520. return false;
  521. EventDescriptor eventDescriptor;
  522. if (!createEventDescriptor(action, &eventDescriptor))
  523. return false;
  524. removeNode(deviceType, deviceInst, eventDescriptor.flags,eventDescriptor.eventCode, object);
  525. return true;
  526. }
  527. //------------------------------------------------------------------------------
  528. // This function is for the use of the control remapper.
  529. // It will only check against the console function (since all remappable commands are
  530. // bound using bind and not bindCmd).
  531. //
  532. const char* ActionMap::getBinding( const char* command )
  533. {
  534. char* returnString = Con::getReturnBuffer( 1024 );
  535. returnString[0] = 0;
  536. char buffer[256];
  537. char deviceBuffer[32];
  538. char keyBuffer[64];
  539. U32 devMapIndex = 0, nodeIndex = 0;
  540. while ( nextBoundNode( command, devMapIndex, nodeIndex ) )
  541. {
  542. const DeviceMap* deviceMap = mDeviceMaps[devMapIndex];
  543. if ( getDeviceName( deviceMap->deviceType, deviceMap->deviceInst, deviceBuffer ) )
  544. {
  545. const Node* node = &deviceMap->nodeMap[nodeIndex];
  546. const char* modifierString = getModifierString( node->modifiers );
  547. if ( getKeyString( node->action, keyBuffer ) )
  548. {
  549. dSprintf( buffer, sizeof( buffer ), "%s\t%s%s", deviceBuffer, modifierString, keyBuffer );
  550. if ( returnString[0] )
  551. dStrcat( returnString, "\t" );
  552. dStrcat( returnString, buffer );
  553. }
  554. }
  555. ++nodeIndex;
  556. }
  557. return returnString;
  558. }
  559. //------------------------------------------------------------------------------
  560. // This function is for the use of the control remapper.
  561. // The intent of this function is to determine if the given event descriptor is already
  562. // bound in this action map. If so, this function returns the command it is bound to.
  563. // If not, it returns NULL.
  564. //
  565. const char* ActionMap::getCommand( const char* device, const char* action )
  566. {
  567. U32 deviceType;
  568. U32 deviceInst;
  569. if ( getDeviceTypeAndInstance( device, deviceType, deviceInst ) )
  570. {
  571. EventDescriptor eventDescriptor;
  572. if ( createEventDescriptor( action, &eventDescriptor ) )
  573. {
  574. const ActionMap::Node* mapNode = findNode( deviceType, deviceInst, eventDescriptor.flags, eventDescriptor.eventCode );
  575. if ( mapNode )
  576. {
  577. if ( mapNode->flags & Node::BindCmd )
  578. {
  579. S32 bufferLen = dStrlen( mapNode->makeConsoleCommand ) + dStrlen( mapNode->breakConsoleCommand ) + 2;
  580. char* returnString = Con::getReturnBuffer( bufferLen );
  581. dSprintf( returnString, bufferLen, "%s\t%s",
  582. ( mapNode->makeConsoleCommand ? mapNode->makeConsoleCommand : "" ),
  583. ( mapNode->breakConsoleCommand ? mapNode->breakConsoleCommand : "" ) );
  584. return( returnString );
  585. }
  586. else
  587. return( mapNode->consoleFunction );
  588. }
  589. }
  590. }
  591. return( "" );
  592. }
  593. //------------------------------------------------------------------------------
  594. // This function returns whether or not the mapping specified is inverted.
  595. // Obviously, this should only be used for axes.
  596. bool ActionMap::isInverted( const char* device, const char* action )
  597. {
  598. U32 deviceType;
  599. U32 deviceInst;
  600. if ( getDeviceTypeAndInstance( device, deviceType, deviceInst ) )
  601. {
  602. EventDescriptor eventDescriptor;
  603. if ( createEventDescriptor( action, &eventDescriptor ) )
  604. {
  605. const ActionMap::Node* mapNode = findNode( deviceType, deviceInst, eventDescriptor.flags, eventDescriptor.eventCode );
  606. if ( mapNode )
  607. return( mapNode->flags & Node::Inverted );
  608. }
  609. }
  610. Con::errorf( "The input event specified by %s %s is not in this action map!", device, action );
  611. return( false );
  612. }
  613. //------------------------------------------------------------------------------
  614. F32 ActionMap::getScale( const char* device, const char* action )
  615. {
  616. U32 deviceType;
  617. U32 deviceInst;
  618. if ( getDeviceTypeAndInstance( device, deviceType, deviceInst ) )
  619. {
  620. EventDescriptor eventDescriptor;
  621. if ( createEventDescriptor( action, &eventDescriptor ) )
  622. {
  623. const ActionMap::Node* mapNode = findNode( deviceType, deviceInst, eventDescriptor.flags, eventDescriptor.eventCode );
  624. if ( mapNode )
  625. {
  626. if ( mapNode->flags & Node::HasScale )
  627. return( mapNode->scaleFactor );
  628. else
  629. return( 1.0f );
  630. }
  631. }
  632. }
  633. Con::errorf( "The input event specified by %s %s is not in this action map!", device, action );
  634. return( 1.0f );
  635. }
  636. //------------------------------------------------------------------------------
  637. const char* ActionMap::getDeadZone( const char* device, const char* action )
  638. {
  639. U32 deviceType;
  640. U32 deviceInst;
  641. if ( getDeviceTypeAndInstance( device, deviceType, deviceInst ) )
  642. {
  643. EventDescriptor eventDescriptor;
  644. if ( createEventDescriptor( action, &eventDescriptor ) )
  645. {
  646. const ActionMap::Node* mapNode = findNode( deviceType, deviceInst, eventDescriptor.flags, eventDescriptor.eventCode );
  647. if ( mapNode )
  648. {
  649. if ( mapNode->flags & Node::HasDeadZone )
  650. {
  651. char buf[64];
  652. dSprintf( buf, sizeof( buf ), "%g %g", mapNode->deadZoneBegin, mapNode->deadZoneEnd );
  653. char* returnString = Con::getReturnBuffer( dStrlen( buf ) + 1 );
  654. dStrcpy( returnString, buf );
  655. return( returnString );
  656. }
  657. else
  658. return( "0 0" );
  659. }
  660. }
  661. }
  662. Con::errorf( "The input event specified by %s %s is not in this action map!", device, action );
  663. return( "" );
  664. }
  665. //------------------------------------------------------------------------------
  666. const char* ActionMap::buildActionString( const InputEvent* event )
  667. {
  668. const char* modifierString = getModifierString( event->modifier );
  669. char objectBuffer[64];
  670. if ( !getKeyString( event->objInst, objectBuffer ) )
  671. return( "" );
  672. U32 returnLen = dStrlen( modifierString ) + dStrlen( objectBuffer ) + 2;
  673. char* returnString = Con::getReturnBuffer( returnLen );
  674. dSprintf( returnString, returnLen - 1, "%s%s", modifierString, objectBuffer );
  675. return( returnString );
  676. }
  677. //------------------------------------------------------------------------------
  678. bool ActionMap::getDeviceTypeAndInstance(const char *pDeviceName, U32 &deviceType, U32 &deviceInstance)
  679. {
  680. U32 offset = 0;
  681. if (dStrnicmp(pDeviceName, "keyboard", dStrlen("keyboard")) == 0)
  682. {
  683. deviceType = KeyboardDeviceType;
  684. offset = dStrlen("keyboard");
  685. }
  686. else if (dStrnicmp(pDeviceName, "mouse", dStrlen("mouse")) == 0)
  687. {
  688. deviceType = MouseDeviceType;
  689. offset = dStrlen("mouse");
  690. }
  691. else if (dStrnicmp(pDeviceName, "joystick", dStrlen("joystick")) == 0)
  692. {
  693. deviceType = JoystickDeviceType;
  694. offset = dStrlen("joystick");
  695. }
  696. else if (dStrnicmp(pDeviceName, "accelerometer", dStrlen("accelerometer")) == 0)
  697. {
  698. deviceType = AccelerometerDeviceType;
  699. offset = dStrlen("accelerometer");
  700. }
  701. else if (dStrnicmp(pDeviceName, "gyroscope", dStrlen("gyroscope")) == 0)
  702. {
  703. deviceType = GyroscopeDeviceType;
  704. offset = dStrlen("gyroscope");
  705. }
  706. else if (dStrnicmp(pDeviceName, "touchdevice", dStrlen("touchdevice")) == 0)
  707. {
  708. deviceType = ScreenTouchDeviceType;
  709. offset = dStrlen("touchdevice");
  710. }
  711. else if (dStrnicmp(pDeviceName, "gamepad", dStrlen("gamepad")) == 0)
  712. {
  713. deviceType = GamepadDeviceType;
  714. offset = dStrlen("gamepad");
  715. }
  716. else if (dStrnicmp(pDeviceName, "leapdevice", dStrlen("leapdevice")) == 0)
  717. {
  718. deviceType = LeapMotionDeviceType;
  719. offset = dStrlen("leapdevice");
  720. }
  721. else
  722. return false;
  723. if (dStrlen(pDeviceName) > offset)
  724. {
  725. const char* pInst = pDeviceName + offset;
  726. S32 instNum = dAtoi(pInst);
  727. if (instNum < 0)
  728. deviceInstance = 0;
  729. else
  730. deviceInstance = instNum;
  731. }
  732. else
  733. deviceInstance = 0;
  734. return true;
  735. }
  736. //------------------------------------------------------------------------------
  737. bool ActionMap::getDeviceName(const U32 deviceType, const U32 deviceInstance, char* buffer)
  738. {
  739. switch (deviceType)
  740. {
  741. case KeyboardDeviceType:
  742. dStrcpy(buffer, "keyboard");
  743. break;
  744. case MouseDeviceType:
  745. dSprintf(buffer, 16, "mouse%d", deviceInstance);
  746. break;
  747. case JoystickDeviceType:
  748. dSprintf(buffer, 16, "joystick%d", deviceInstance);
  749. break;
  750. case AccelerometerDeviceType:
  751. dStrcpy(buffer, "accelerometer");
  752. break;
  753. case GyroscopeDeviceType:
  754. dStrcpy(buffer, "gyroscope");
  755. break;
  756. case ScreenTouchDeviceType:
  757. dStrcpy(buffer, "touchdevice");
  758. break;
  759. case GamepadDeviceType:
  760. dSprintf(buffer, 16, "gamepad%d", deviceInstance);
  761. break;
  762. case LeapMotionDeviceType:
  763. dStrcpy(buffer, "leapdevice");
  764. break;
  765. default:
  766. Con::errorf( "ActionMap::getDeviceName: unknown device type specified, %d (inst: %d)", deviceType, deviceInstance);
  767. return false;
  768. }
  769. return true;
  770. }
  771. //------------------------------------------------------------------------------
  772. const char* ActionMap::getModifierString(const U32 modifiers)
  773. {
  774. U32 realModifiers = modifiers;
  775. if ( modifiers & SI_LSHIFT || modifiers & SI_RSHIFT )
  776. realModifiers |= SI_SHIFT;
  777. if ( modifiers & SI_LCTRL || modifiers & SI_RCTRL )
  778. realModifiers |= SI_CTRL;
  779. if ( modifiers & SI_LALT || modifiers & SI_RALT )
  780. realModifiers |= SI_ALT;
  781. if ( modifiers & SI_MAC_LOPT || modifiers & SI_MAC_ROPT )
  782. realModifiers |= SI_MAC_OPT;
  783. switch (realModifiers & (SI_SHIFT|SI_CTRL|SI_ALT|SI_MAC_OPT)) {
  784. #if defined(TORQUE_OS_OSX)
  785. // optional code, to output alt as cmd on mac.
  786. // interpreter sees them as the same...
  787. case (SI_SHIFT|SI_CTRL|SI_ALT):
  788. return "cmd-shift-ctrl ";
  789. case (SI_SHIFT|SI_ALT):
  790. return "cmd-shift ";
  791. case (SI_CTRL|SI_ALT):
  792. return "cmd-ctrl ";
  793. case (SI_ALT):
  794. return "cmd ";
  795. #else
  796. case (SI_SHIFT|SI_CTRL|SI_ALT):
  797. return "shift-ctrl-alt ";
  798. case (SI_SHIFT|SI_ALT):
  799. return "shift-alt ";
  800. case (SI_CTRL|SI_ALT):
  801. return "ctrl-alt ";
  802. case (SI_ALT):
  803. return "alt ";
  804. #endif
  805. case (SI_SHIFT|SI_CTRL):
  806. return "shift-ctrl ";
  807. case (SI_SHIFT):
  808. return "shift ";
  809. case (SI_CTRL):
  810. return "ctrl ";
  811. // plus new mac cases:
  812. case (SI_ALT|SI_SHIFT|SI_CTRL|SI_MAC_OPT):
  813. return "cmd-shift-ctrl-opt ";
  814. case (SI_ALT|SI_SHIFT|SI_MAC_OPT):
  815. return "cmd-shift-opt ";
  816. case (SI_ALT|SI_CTRL|SI_MAC_OPT):
  817. return "cmd-ctrl-opt ";
  818. case (SI_ALT|SI_MAC_OPT):
  819. return "cmd-opt ";
  820. case (SI_SHIFT|SI_CTRL|SI_MAC_OPT):
  821. return "shift-ctrl-opt ";
  822. case (SI_SHIFT|SI_MAC_OPT):
  823. return "shift-opt ";
  824. case (SI_CTRL|SI_MAC_OPT):
  825. return "ctrl-opt ";
  826. case (SI_MAC_OPT):
  827. return "opt ";
  828. case 0:
  829. return "";
  830. default:
  831. AssertFatal(false, "Error, should never reach the default case in getModifierString");
  832. return "";
  833. }
  834. }
  835. //------------------------------------------------------------------------------
  836. bool ActionMap::getKeyString(const U32 action, char* buffer)
  837. {
  838. U16 asciiCode = Input::getAscii(action, STATE_LOWER);
  839. // if (action >= KEY_A && action <= KEY_Z) {
  840. // buffer[0] = char(action - KEY_A + 'a');
  841. // buffer[1] = '\0';
  842. // return true;
  843. // } else if (action >= KEY_0 && action <= KEY_9) {
  844. // buffer[0] = char(action - KEY_0 + '0');
  845. // buffer[1] = '\0';
  846. if ( (asciiCode != 0) && dIsDecentChar((char)asciiCode))
  847. {
  848. for (U32 i = 0; gAsciiMap[i].asciiCode != 0xFFFF; i++) {
  849. if (gAsciiMap[i].asciiCode == asciiCode)
  850. {
  851. dStrcpy(buffer, gAsciiMap[i].pDescription);
  852. return true;
  853. }
  854. }
  855. // Must not have found a string for that ascii code just record the char
  856. buffer[0] = char(asciiCode);
  857. buffer[1] = '\0';
  858. return true;
  859. }
  860. else
  861. {
  862. if (action >= KEY_A && action <= KEY_Z)
  863. {
  864. buffer[0] = char(action - KEY_A + 'a');
  865. buffer[1] = '\0';
  866. return true;
  867. }
  868. else if (action >= KEY_0 && action <= KEY_9) {
  869. buffer[0] = char(action - KEY_0 + '0');
  870. buffer[1] = '\0';
  871. return true;
  872. }
  873. for (U32 i = 0; gVirtualMap[i].code != 0xFFFFFFFF; i++) {
  874. if (gVirtualMap[i].code == action) {
  875. dStrcpy(buffer, gVirtualMap[i].pDescription);
  876. return true;
  877. }
  878. }
  879. }
  880. Con::errorf( "ActionMap::getKeyString: no string for action %d", action );
  881. return false;
  882. }
  883. //--------------------------------------------------------------------------
  884. bool ActionMap::processBindCmd(const char *device, const char *action, const char *makeCmd, const char *breakCmd)
  885. {
  886. U32 deviceType;
  887. U32 deviceInst;
  888. if(!getDeviceTypeAndInstance(device, deviceType, deviceInst))
  889. {
  890. Con::printf("processBindCmd: unknown device: %s", device);
  891. return false;
  892. }
  893. // Ok, we now have the deviceType and instance. Create an event descriptor
  894. // for the bind...
  895. //
  896. EventDescriptor eventDescriptor;
  897. if (createEventDescriptor(action, &eventDescriptor) == false) {
  898. Con::printf("Could not create a description for binding: %s", action);
  899. return false;
  900. }
  901. // SI_POV == SI_MOVE, and the POV works fine with bindCmd, so we have to add these manually.
  902. if( ( eventDescriptor.eventCode == SI_XAXIS ) ||
  903. ( eventDescriptor.eventCode == SI_YAXIS ) ||
  904. ( eventDescriptor.eventCode == SI_ZAXIS ) ||
  905. ( eventDescriptor.eventCode == SI_RXAXIS ) ||
  906. ( eventDescriptor.eventCode == SI_RYAXIS ) ||
  907. ( eventDescriptor.eventCode == SI_RZAXIS ) ||
  908. ( eventDescriptor.eventCode == SI_SLIDER ) ||
  909. ( eventDescriptor.eventCode == SI_XPOV ) ||
  910. ( eventDescriptor.eventCode == SI_YPOV ) ||
  911. ( eventDescriptor.eventCode == SI_XPOV2 ) ||
  912. ( eventDescriptor.eventCode == SI_YPOV2 ) ||
  913. ( eventDescriptor.eventCode == SI_ACCELX ) ||
  914. ( eventDescriptor.eventCode == SI_ACCELY ) ||
  915. ( eventDescriptor.eventCode == SI_ACCELZ ) ||
  916. ( eventDescriptor.eventCode == SI_GRAVX ) ||
  917. ( eventDescriptor.eventCode == SI_GRAVY ) ||
  918. ( eventDescriptor.eventCode == SI_GRAVZ ) ||
  919. ( eventDescriptor.eventCode == SI_GYROX ) ||
  920. ( eventDescriptor.eventCode == SI_GYROY ) ||
  921. ( eventDescriptor.eventCode == SI_GYROZ ) ||
  922. ( eventDescriptor.eventCode == SI_YAW ) ||
  923. ( eventDescriptor.eventCode == SI_PITCH ) ||
  924. ( eventDescriptor.eventCode == SI_ROLL ) )
  925. {
  926. Con::warnf( "ActionMap::processBindCmd - Cannot use 'bindCmd' with a move event type. Use 'bind' instead." );
  927. return false;
  928. }
  929. // Create the full bind entry, and place it in the map
  930. //
  931. // DMMTODO
  932. Node* pBindNode = getNode(deviceType, deviceInst,
  933. eventDescriptor.flags,
  934. eventDescriptor.eventCode);
  935. pBindNode->flags = Node::BindCmd;
  936. pBindNode->deadZoneBegin = 0;
  937. pBindNode->deadZoneEnd = 0;
  938. pBindNode->scaleFactor = 1;
  939. if(makeCmd[0])
  940. pBindNode->makeConsoleCommand = dStrdup(makeCmd);
  941. else
  942. pBindNode->makeConsoleCommand = dStrdup("");
  943. if(breakCmd[0])
  944. pBindNode->breakConsoleCommand = dStrdup(breakCmd);
  945. else
  946. pBindNode->breakConsoleCommand = dStrdup("");
  947. return true;
  948. }
  949. //------------------------------------------------------------------------------
  950. bool ActionMap::processBind(const U32 argc, const char** argv, SimObject* object)
  951. {
  952. // Ok, the bind will come in the following format:
  953. // [device] [key or button] <[param spec] [param] ...> [fnName]
  954. //
  955. const char* pDeviceName = argv[0];
  956. const char* pEvent = argv[1];
  957. const char* pFnName = argv[argc - 1];
  958. // Determine the device
  959. U32 deviceType;
  960. U32 deviceInst;
  961. if(!getDeviceTypeAndInstance(argv[0], deviceType, deviceInst))
  962. {
  963. Con::printf("processBind: unknown device: %s", pDeviceName);
  964. return false;
  965. }
  966. // Ok, we now have the deviceType and instance. Create an event descriptor
  967. // for the bind...
  968. //
  969. EventDescriptor eventDescriptor;
  970. if (createEventDescriptor(pEvent, &eventDescriptor) == false) {
  971. Con::printf("Could not create a description for binding: %s", pEvent);
  972. return false;
  973. }
  974. // Event has now been described, and device determined. we need now to extract
  975. // any modifiers that the action map will apply to incoming events before
  976. // calling the bound function...
  977. //
  978. // DMMTODO
  979. U32 assignedFlags = 0;
  980. F32 deadZoneBegin = 0.0f;
  981. F32 deadZoneEnd = 0.0f;
  982. F32 scaleFactor = 1.0f;
  983. if (argc != 3) {
  984. // We have the following: "[DSIR]" [deadZone] [scale]
  985. //
  986. const char* pSpec = argv[2];
  987. for (U32 i = 0; pSpec[i] != '\0'; i++) {
  988. switch (pSpec[i]) {
  989. case 'r': case 'R':
  990. assignedFlags |= Node::HasScale;
  991. break;
  992. case 's': case 'S':
  993. assignedFlags |= Node::HasScale;
  994. break;
  995. case 'd': case 'D':
  996. assignedFlags |= Node::HasDeadZone;
  997. break;
  998. case 'i': case 'I':
  999. assignedFlags |= Node::Inverted;
  1000. break;
  1001. case 'n': case 'N':
  1002. assignedFlags |= Node::NonLinear;
  1003. break;
  1004. default:
  1005. AssertFatal(false, avar("Misunderstood specifier in bind (spec string: %s)",
  1006. pSpec));
  1007. }
  1008. }
  1009. // Ok, we have the flags. Scan the dead zone and scale, if any.
  1010. //
  1011. U32 curArg = 3;
  1012. if (assignedFlags & Node::HasDeadZone) {
  1013. dSscanf(argv[curArg], "%g %g", &deadZoneBegin, &deadZoneEnd);
  1014. curArg++;
  1015. }
  1016. if (assignedFlags & Node::HasScale) {
  1017. scaleFactor = dAtof(argv[curArg]);
  1018. curArg++;
  1019. }
  1020. if (curArg != (argc - 1)) {
  1021. AssertFatal(curArg == (argc - 1), "error in bind spec somewhere...");
  1022. Con::printf("Improperly specified bind for key: %s", argv[2]);
  1023. return false;
  1024. }
  1025. }
  1026. // Ensure that the console function is properly specified?
  1027. //
  1028. // DMMTODO
  1029. // Create the full bind entry, and place it in the map
  1030. //
  1031. // DMMTODO
  1032. Node* pBindNode = getNode(deviceType, deviceInst,
  1033. eventDescriptor.flags,
  1034. eventDescriptor.eventCode, object);
  1035. pBindNode->flags = assignedFlags;
  1036. pBindNode->deadZoneBegin = deadZoneBegin;
  1037. pBindNode->deadZoneEnd = deadZoneEnd;
  1038. pBindNode->scaleFactor = scaleFactor;
  1039. pBindNode->object = object;
  1040. pBindNode->consoleFunction = StringTable->insert(pFnName);
  1041. return true;
  1042. }
  1043. //------------------------------------------------------------------------------
  1044. bool ActionMap::processLeap(const InputEvent* pEvent)
  1045. {
  1046. static const char *argv[5];
  1047. char buffer[64];
  1048. const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
  1049. if (pNode == NULL)
  1050. {
  1051. // Check to see if we clear the modifiers, do we find an action?
  1052. if (pEvent->modifier != 0)
  1053. pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
  1054. if (pNode == NULL)
  1055. return false;
  1056. }
  1057. // "Do nothing" bind:
  1058. if ( !pNode->consoleFunction[0] )
  1059. return( true );
  1060. argv[0] = pNode->consoleFunction;
  1061. float values[3];
  1062. values[0] = pEvent->fValues[0];
  1063. values[1] = pEvent->fValues[1];
  1064. values[2] = pEvent->fValues[2];
  1065. if ( pNode->flags & Node::HasDeadZone )
  1066. {
  1067. if ( pEvent->fValues[0] >= pNode->deadZoneBegin && pEvent->fValues[0] <= pNode->deadZoneEnd )
  1068. values[0] = 0.0f;
  1069. if ( pEvent->fValues[1] >= pNode->deadZoneBegin && pEvent->fValues[1] <= pNode->deadZoneEnd )
  1070. values[1] = 0.0f;
  1071. if ( pEvent->fValues[2] >= pNode->deadZoneBegin && pEvent->fValues[2] <= pNode->deadZoneEnd )
  1072. values[2] = 0.0f;
  1073. // All values are all null, so don't bother executing the function
  1074. if (!values[0] && !values[1] && !values[2])
  1075. return true;
  1076. }
  1077. switch(pEvent->objType)
  1078. {
  1079. case LM_HANDPOS:
  1080. // ID
  1081. argv[1] = Con::getIntArg(pEvent->iValue);
  1082. // Position
  1083. dSprintf(buffer, sizeof(buffer), "%f %f %f", values[0], values[1], values[2]);
  1084. argv[2] = buffer;
  1085. if (pNode->object)
  1086. Con::executef(pNode->object, 3, argv[0], argv[1], argv[2]);
  1087. else
  1088. Con::execute(3, argv);
  1089. break;
  1090. case LM_HANDROT:
  1091. // ID
  1092. argv[1] = Con::getIntArg(pEvent->iValue);
  1093. // Rotation
  1094. dSprintf(buffer, sizeof(buffer), "%f %f %f", values[0], values[1], values[2]);
  1095. argv[2] = buffer;
  1096. if (pNode->object)
  1097. Con::executef(pNode->object, 3, argv[0], argv[1], argv[2]);
  1098. else
  1099. Con::execute(3, argv);
  1100. break;
  1101. case LM_FINGERPOS:
  1102. // IDs
  1103. argv[1] = pEvent->fingerIDs;
  1104. // X-coordinates
  1105. argv[2] = pEvent->fingersX;
  1106. // Y-coordinates
  1107. argv[3] = pEvent->fingersY;
  1108. // Z-coordinates
  1109. argv[4] = pEvent->fingersZ;
  1110. if (pNode->object)
  1111. Con::executef(pNode->object, 5, argv[0], argv[1], argv[2], argv[3], argv[4]);
  1112. else
  1113. Con::execute(5, argv);
  1114. break;
  1115. case LM_HANDAXIS:
  1116. default:
  1117. return false;
  1118. }
  1119. return true;
  1120. }
  1121. //------------------------------------------------------------------------------
  1122. bool ActionMap::processGesture(const InputEvent* pEvent)
  1123. {
  1124. static const char *argv[6];
  1125. char buffer[64];
  1126. const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
  1127. if (pNode == NULL)
  1128. {
  1129. // Check to see if we clear the modifiers, do we find an action?
  1130. if (pEvent->modifier != 0)
  1131. pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
  1132. if (pNode == NULL)
  1133. return false;
  1134. }
  1135. // "Do nothing" bind:
  1136. if ( !pNode->consoleFunction[0] )
  1137. return( true );
  1138. // Function
  1139. argv[0] = pNode->consoleFunction;
  1140. switch(pEvent->objType)
  1141. {
  1142. case SI_CIRCLE_GESTURE:
  1143. // ID
  1144. argv[1] = Con::getIntArg(pEvent->iValue);
  1145. // Progress
  1146. argv[2] = Con::getFloatArg(pEvent->fValues[0]);
  1147. // Radius
  1148. argv[3] = Con::getFloatArg(pEvent->fValues[1]);
  1149. // Direction (1 clockwise, 0 counter-clockwise)
  1150. argv[4] = Con::getFloatArg(pEvent->fValues[2]);
  1151. // State
  1152. argv[5] = Con::getFloatArg(pEvent->fValues[3]);
  1153. if (pNode->object)
  1154. Con::executef(pNode->object, 6, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
  1155. else
  1156. Con::execute(6, argv);
  1157. break;
  1158. case SI_SWIPE_GESTURE:
  1159. // ID
  1160. argv[1] = Con::getIntArg(pEvent->iValue);
  1161. // State
  1162. argv[2] = Con::getFloatArg(pEvent->fValues[0]);
  1163. // Direction
  1164. dSprintf(buffer, sizeof(buffer), "%f %f %f", pEvent->fValues[1], pEvent->fValues[2], pEvent->fValues[3]);
  1165. argv[3] = buffer;
  1166. // Speed
  1167. argv[4] = Con::getFloatArg(pEvent->fValues[4]);
  1168. if (pNode->object)
  1169. Con::executef(pNode->object, 5, argv[0], argv[1], argv[2], argv[3], argv[4]);
  1170. else
  1171. Con::execute(5, argv);
  1172. break;
  1173. case SI_KEYTAP_GESTURE:
  1174. case SI_SCREENTAP_GESTURE:
  1175. // ID
  1176. argv[1] = Con::getIntArg(pEvent->iValue);
  1177. // Position
  1178. dSprintf(buffer, sizeof(buffer), "%f %f %f", pEvent->fValues[0], pEvent->fValues[1], pEvent->fValues[2]);
  1179. argv[2] = buffer;
  1180. // Direction
  1181. dSprintf(buffer, sizeof(buffer), "%f %f %f", pEvent->fValues[3], pEvent->fValues[4], pEvent->fValues[5]);
  1182. argv[3] = buffer;
  1183. if (pNode->object)
  1184. Con::executef(pNode->object, 4, argv[0], argv[1], argv[2], argv[3]);
  1185. else
  1186. Con::execute(5, argv);
  1187. break;
  1188. case SI_PINCH_GESTURE:
  1189. case SI_SCALE_GESTURE:
  1190. default:
  1191. return true;
  1192. }
  1193. return true;
  1194. }
  1195. //------------------------------------------------------------------------------
  1196. bool ActionMap::processTouch(const InputEvent* pEvent)
  1197. {
  1198. static const char *argv[4];
  1199. const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
  1200. if (pNode == NULL)
  1201. {
  1202. // Check to see if we clear the modifiers, do we find an action?
  1203. if (pEvent->modifier != 0)
  1204. pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
  1205. if (pNode == NULL)
  1206. return false;
  1207. }
  1208. // "Do nothing" bind:
  1209. if ( !pNode->consoleFunction[0] )
  1210. return( true );
  1211. // Ok, we're all set up, call the function.
  1212. argv[0] = pNode->consoleFunction;
  1213. argv[1] = pEvent->fingerIDs;
  1214. argv[2] = pEvent->fingersX;
  1215. argv[3] = pEvent->fingersY;
  1216. if (pNode->object)
  1217. Con::executef(pNode->object, 4, argv[0], argv[1], argv[2], argv[3]);
  1218. else
  1219. Con::execute(4, argv);
  1220. return true;
  1221. }
  1222. //------------------------------------------------------------------------------
  1223. bool ActionMap::processButton(const InputEvent* pEvent)
  1224. {
  1225. static const char *argv[2];
  1226. const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
  1227. if (pNode == NULL)
  1228. {
  1229. // Check to see if we clear the modifiers, do we find an action?
  1230. if (pEvent->modifier != 0)
  1231. pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
  1232. if (pNode == NULL)
  1233. return false;
  1234. }
  1235. // Whadda ya know, we have this bound. Set up, and call the console
  1236. // function associated with it...
  1237. //
  1238. F32 value = pEvent->fValues[0];
  1239. if (pNode->flags & Node::Ranged)
  1240. {
  1241. value = (value * 2.0f) - 1.0f;
  1242. if (pNode->flags & Node::Inverted)
  1243. value *= -1.0f;
  1244. }
  1245. else
  1246. {
  1247. if (pNode->flags & Node::Inverted)
  1248. value = 1.0f - value;
  1249. }
  1250. if (pNode->flags & Node::HasScale)
  1251. value *= pNode->scaleFactor;
  1252. if (pNode->flags & Node::HasDeadZone)
  1253. {
  1254. if (value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd)
  1255. value = 0.0f;
  1256. else
  1257. {
  1258. if( value > 0 )
  1259. value = ( value - pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
  1260. else
  1261. value = ( value + pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
  1262. }
  1263. }
  1264. if( pNode->flags & Node::NonLinear )
  1265. value = ( value < 0.f ? -1.f : 1.f ) * mPow( mFabs( value ), CONST_E );
  1266. // Ok, we're all set up, call the function.
  1267. if(pNode->flags & Node::BindCmd)
  1268. {
  1269. // it's a bind command
  1270. if(pNode->makeConsoleCommand)
  1271. Con::evaluate(pNode->makeConsoleCommand);
  1272. }
  1273. else if ( pNode->consoleFunction[0] )
  1274. {
  1275. argv[0] = pNode->consoleFunction;
  1276. argv[1] = Con::getFloatArg(value);
  1277. if (pNode->object)
  1278. Con::executef(pNode->object, 2, argv[0], argv[1]);
  1279. else
  1280. Con::execute(2, argv);
  1281. }
  1282. // [neo, 5/13/2007 - #3109]
  1283. // The execs/evaluate above could have called reentrant script code which made calls to
  1284. // bindCmd() etc, channging the node map underneath us. If enough nodes were added then
  1285. // the node map vector would realloc, with the result that pNode would then be pointing
  1286. // at garbage and cause a crash when passed to enterBreakEvent() below. So we just look
  1287. // it up again to be safe. This is not needed in the other cases below as we return right
  1288. // after the execs and don't use pNode again.
  1289. pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst );
  1290. if (pNode == NULL)
  1291. {
  1292. if (pEvent->modifier != 0)
  1293. {
  1294. // Check to see if we clear the modifiers, do we find an action?
  1295. pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objInst);
  1296. if (pNode == NULL)
  1297. {
  1298. // We already called any bound methods/functions so our job is done
  1299. return true;
  1300. }
  1301. }
  1302. }
  1303. // And enter the break into the table if this is a make event...
  1304. enterBreakEvent(pEvent, pNode);
  1305. return true;
  1306. }
  1307. //------------------------------------------------------------------------------
  1308. bool ActionMap::processMove(const InputEvent* pEvent)
  1309. {
  1310. static const char *argv[4];
  1311. if (pEvent->deviceType == MouseDeviceType)
  1312. {
  1313. const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType);
  1314. if (pNode == NULL)
  1315. {
  1316. // Check to see if we clear the modifiers, do we find an action?
  1317. if (pEvent->modifier != 0)
  1318. pNode = findNode(pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objType);
  1319. if (pNode == NULL)
  1320. return false;
  1321. }
  1322. // "Do nothing" bind:
  1323. if ( !pNode->consoleFunction[0] )
  1324. return( true );
  1325. // Whadda ya know, we have this bound. Set up, and call the console
  1326. // function associated with it. Mouse events ignore range and dead
  1327. // zone params.
  1328. //
  1329. F32 value = pEvent->fValues[0];
  1330. if (pNode->flags & Node::Inverted)
  1331. value *= -1.0f;
  1332. if (pNode->flags & Node::HasScale)
  1333. value *= pNode->scaleFactor;
  1334. // Ok, we're all set up, call the function.
  1335. argv[0] = pNode->consoleFunction;
  1336. argv[1] = Con::getFloatArg(value);
  1337. if (pNode->object)
  1338. Con::executef(pNode->object, 2, argv[0], argv[1]);
  1339. else
  1340. Con::execute(2, argv);
  1341. return true;
  1342. }
  1343. else if ( (pEvent->objType == XI_POS || pEvent->objType == XI_FLOAT || pEvent->objType == XI_ROT || pEvent->objType == XI_INT) )
  1344. {
  1345. const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst);
  1346. if( pNode == NULL )
  1347. return false;
  1348. // Ok, we're all set up, call the function.
  1349. argv[0] = pNode->consoleFunction;
  1350. S32 argc = 1;
  1351. if (pEvent->objType == XI_INT)
  1352. {
  1353. // Handle the integer as some sort of motion such as a
  1354. // single component to an absolute position
  1355. argv[1] = Con::getIntArg( pEvent->iValue );
  1356. argc += 1;
  1357. }
  1358. else if (pEvent->objType == XI_FLOAT)
  1359. {
  1360. // Handle float as some sort of motion such as a
  1361. // single component to an absolute position
  1362. argv[1] = Con::getFloatArg( pEvent->fValues[0] );
  1363. argc += 1;
  1364. }
  1365. else if (pEvent->objType == XI_POS)
  1366. {
  1367. // Handle Point3F type position
  1368. argv[1] = Con::getFloatArg( pEvent->fValues[0] );
  1369. argv[2] = Con::getFloatArg( pEvent->fValues[1] );
  1370. argv[3] = Con::getFloatArg( pEvent->fValues[2] );
  1371. argc += 3;
  1372. }
  1373. if (pNode->object)
  1374. {
  1375. Con::execute(pNode->object, argc, argv);
  1376. }
  1377. else
  1378. {
  1379. Con::execute(argc, argv);
  1380. }
  1381. return true;
  1382. }
  1383. else if ( pEvent->deviceType == JoystickDeviceType )
  1384. {
  1385. // Joystick events...
  1386. const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
  1387. if( pNode == NULL )
  1388. return false;
  1389. // "Do nothing" bind:
  1390. if ( !pNode->consoleFunction[0] )
  1391. return( true );
  1392. // Whadda ya know, we have this bound. Set up, and call the console
  1393. // function associated with it. Joystick move events are the same as mouse
  1394. // move events except that they don't ignore dead zone.
  1395. //
  1396. F32 value = pEvent->fValues[0];
  1397. if ( pNode->flags & Node::Inverted )
  1398. value *= -1.0f;
  1399. if ( pNode->flags & Node::HasScale )
  1400. value *= pNode->scaleFactor;
  1401. if ( pNode->flags & Node::HasDeadZone )
  1402. {
  1403. if ( value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd )
  1404. {
  1405. value = 0.0f;
  1406. }
  1407. else
  1408. {
  1409. if( value > 0 )
  1410. value = ( value - pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
  1411. else
  1412. value = ( value + pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
  1413. }
  1414. }
  1415. if( pNode->flags & Node::NonLinear )
  1416. value = ( value < 0.f ? -1.f : 1.f ) * mPow( mFabs( value ), CONST_E );
  1417. // Ok, we're all set up, call the function.
  1418. argv[0] = pNode->consoleFunction;
  1419. argv[1] = Con::getFloatArg( value );
  1420. if (pNode->object)
  1421. Con::executef(pNode->object, 2, argv[0], argv[1]);
  1422. else
  1423. Con::execute(2, argv);
  1424. return true;
  1425. }
  1426. else if ( pEvent->deviceType == GamepadDeviceType )
  1427. {
  1428. // Joystick events...
  1429. const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst );
  1430. if( pNode == NULL )
  1431. return false;
  1432. // "Do nothing" bind:
  1433. if ( !pNode->consoleFunction[0] )
  1434. return( true );
  1435. // Whadda ya know, we have this bound. Set up, and call the console
  1436. // function associated with it. Joystick move events are the same as mouse
  1437. // move events except that they don't ignore dead zone.
  1438. //
  1439. F32 value = pEvent->fValues[0];
  1440. if ( pNode->flags & Node::Inverted )
  1441. value *= -1.0f;
  1442. if ( pNode->flags & Node::HasScale )
  1443. value *= pNode->scaleFactor;
  1444. if ( pNode->flags & Node::HasDeadZone )
  1445. {
  1446. if ( value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd )
  1447. {
  1448. value = 0.0f;
  1449. }
  1450. else
  1451. {
  1452. if( value > 0 )
  1453. value = ( value - pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
  1454. else
  1455. value = ( value + pNode->deadZoneBegin ) * ( 1.f / ( 1.f - pNode->deadZoneBegin ) );
  1456. }
  1457. }
  1458. if( pNode->flags & Node::NonLinear )
  1459. value = ( value < 0.f ? -1.f : 1.f ) * mPow( mFabs( value ), CONST_E );
  1460. // Ok, we're all set up, call the function.
  1461. argv[0] = pNode->consoleFunction;
  1462. argv[1] = Con::getFloatArg( value );
  1463. if (pNode->object)
  1464. Con::executef(pNode->object, 2, argv[0], argv[1]);
  1465. else
  1466. Con::execute(2, argv);
  1467. return true;
  1468. }
  1469. return false;
  1470. }
  1471. //------------------------------------------------------------------------------
  1472. bool ActionMap::processMotion(const InputEvent* pEvent)
  1473. {
  1474. static const char *argv[2];
  1475. // iOS Accelerometer, Gyroscope and DeviceMotion processing
  1476. // Currently, this is identical to the joystick handling.
  1477. // This was copied over into its own section because this will
  1478. // give us a dedicated section to tweak processing based on iOS specific
  1479. // devices. No point in trying to mangle joystick code any further
  1480. const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
  1481. if ( pNode == NULL )
  1482. {
  1483. // Check to see if we clear the modifiers, do we find an action?
  1484. if (pEvent->modifier != 0)
  1485. pNode = findNode( pEvent->deviceType, pEvent->deviceInst, 0, pEvent->objType );
  1486. if ( pNode == NULL )
  1487. return false;
  1488. }
  1489. // "Do nothing" bind:
  1490. if ( !pNode->consoleFunction[0] )
  1491. return( true );
  1492. F32 value = pEvent->fValues[0];
  1493. if ( pNode->flags & Node::Inverted )
  1494. value *= -1.0f;
  1495. if ( pNode->flags & Node::HasScale )
  1496. value *= pNode->scaleFactor;
  1497. if ( pNode->flags & Node::HasDeadZone )
  1498. {
  1499. if ( value >= pNode->deadZoneBegin && value <= pNode->deadZoneEnd )
  1500. value = 0.0f;
  1501. }
  1502. // Ok, we're all set up, call the function.
  1503. argv[0] = pNode->consoleFunction;
  1504. argv[1] = Con::getFloatArg( value );
  1505. if (pNode->object)
  1506. Con::executef(pNode->object, 2, argv[0], argv[1]);
  1507. else
  1508. Con::execute(2, argv);
  1509. return true;
  1510. }
  1511. //------------------------------------------------------------------------------
  1512. bool ActionMap::processXInput(const InputEvent* pEvent)
  1513. {
  1514. static const char *argv[2];
  1515. if ((pEvent->objType == XI_FLOAT || pEvent->objType == XI_INT))
  1516. {
  1517. const Node* pNode = findNode( pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objType );
  1518. if (pNode == NULL )
  1519. return false;
  1520. // Ok, we're all set up, call the function.
  1521. argv[0] = pNode->consoleFunction;
  1522. S32 argc = 1;
  1523. if (pEvent->objType == XI_INT)
  1524. {
  1525. // Handle the integer as some sort of motion such as a
  1526. // single component to an absolute position
  1527. argv[1] = Con::getIntArg( pEvent->iValue );
  1528. argc += 1;
  1529. }
  1530. else if (pEvent->objType == XI_FLOAT)
  1531. {
  1532. // Handle float as some sort of motion such as a
  1533. // single component to an absolute position
  1534. argv[1] = Con::getFloatArg( pEvent->fValues[0] );
  1535. argc += 1;
  1536. }
  1537. if (pNode->object)
  1538. {
  1539. Con::execute(pNode->object, argc, argv);
  1540. }
  1541. else
  1542. {
  1543. Con::execute(argc, argv);
  1544. }
  1545. }
  1546. return true;
  1547. }
  1548. //------------------------------------------------------------------------------
  1549. bool ActionMap::processAction(const InputEvent* pEvent)
  1550. {
  1551. switch(pEvent->action)
  1552. {
  1553. case SI_LEAP:
  1554. return processLeap(pEvent);
  1555. break;
  1556. case SI_GESTURE:
  1557. return processGesture(pEvent);
  1558. break;
  1559. case SI_TOUCH:
  1560. return processTouch(pEvent);
  1561. break;
  1562. case SI_MAKE:
  1563. return processButton(pEvent);
  1564. break;
  1565. case SI_MOVE:
  1566. return processMove(pEvent);
  1567. break;
  1568. case SI_MOTION:
  1569. return processMotion(pEvent);
  1570. break;
  1571. case SI_BREAK:
  1572. return checkBreakTable(pEvent);
  1573. break;
  1574. case SI_VALUE:
  1575. return processXInput(pEvent);
  1576. }
  1577. return false;
  1578. }
  1579. //------------------------------------------------------------------------------
  1580. void ActionMap::enterBreakEvent(const InputEvent* pEvent, const Node* pNode)
  1581. {
  1582. // There aren't likely to be many breaks outstanding at any one given time,
  1583. // so a simple linear search is probably sufficient. Note that the break table
  1584. // is static to the class, all breaks are directed to the action map that received
  1585. // the make.
  1586. //
  1587. S32 entry = -1;
  1588. for (U32 i = 0; i < (U32)smBreakTable.size(); i++) {
  1589. if (smBreakTable[i].deviceType == U32(pEvent->deviceType) &&
  1590. smBreakTable[i].deviceInst == U32(pEvent->deviceInst) &&
  1591. smBreakTable[i].objInst == U32(pEvent->objInst)) {
  1592. // Match.
  1593. entry = i;
  1594. break;
  1595. }
  1596. }
  1597. if (entry == -1) {
  1598. smBreakTable.increment();
  1599. entry = smBreakTable.size() - 1;
  1600. smBreakTable[entry].deviceType = pEvent->deviceType;
  1601. smBreakTable[entry].deviceInst = pEvent->deviceInst;
  1602. smBreakTable[entry].objInst = pEvent->objInst;
  1603. }
  1604. // Ok, we now have the entry, and know that the device desc. and the objInst match.
  1605. // Copy out the node information...
  1606. //
  1607. smBreakTable[entry].object = pNode->object;
  1608. // [neo, 5/7/2007 - #2975]
  1609. // object above can be deleted in between a make/break and so object will point
  1610. // to turfed memory and crash. To keep things simple we just store id as well so
  1611. // we can look it up to validate object ref.
  1612. smBreakTable[entry].objectId = pNode->object ? pNode->object->getId() : 0;
  1613. smBreakTable[entry].consoleFunction = pNode->consoleFunction;
  1614. if(pNode->breakConsoleCommand)
  1615. smBreakTable[entry].breakConsoleCommand = dStrdup(pNode->breakConsoleCommand);
  1616. else
  1617. smBreakTable[entry].breakConsoleCommand = NULL;
  1618. smBreakTable[entry].flags = pNode->flags;
  1619. smBreakTable[entry].deadZoneBegin = pNode->deadZoneBegin;
  1620. smBreakTable[entry].deadZoneEnd = pNode->deadZoneEnd;
  1621. smBreakTable[entry].scaleFactor = pNode->scaleFactor;
  1622. }
  1623. //------------------------------------------------------------------------------
  1624. bool ActionMap::checkBreakTable(const InputEvent* pEvent)
  1625. {
  1626. for (U32 i = 0; i < (U32)smBreakTable.size(); i++) {
  1627. if (smBreakTable[i].deviceType == U32(pEvent->deviceType) &&
  1628. smBreakTable[i].deviceInst == U32(pEvent->deviceInst) &&
  1629. smBreakTable[i].objInst == U32(pEvent->objInst)) {
  1630. // Match. Issue the break event...
  1631. //
  1632. F32 value = pEvent->fValues[0];
  1633. if (smBreakTable[i].flags & Node::Ranged) {
  1634. value = (value * 2.0f) - 1.0f;
  1635. if (smBreakTable[i].flags & Node::Inverted)
  1636. value *= -1.0f;
  1637. } else {
  1638. if (smBreakTable[i].flags & Node::Inverted)
  1639. value = 1.0f - value;
  1640. }
  1641. if (smBreakTable[i].flags & Node::HasScale)
  1642. value *= smBreakTable[i].scaleFactor;
  1643. if (smBreakTable[i].flags & Node::HasDeadZone)
  1644. if (value >= smBreakTable[i].deadZoneBegin &&
  1645. value <= smBreakTable[i].deadZoneEnd)
  1646. value = 0.0f;
  1647. // Ok, we're all set up, call the function.
  1648. if(smBreakTable[i].consoleFunction)
  1649. {
  1650. if ( smBreakTable[i].consoleFunction[0] )
  1651. {
  1652. static const char *argv[2];
  1653. argv[0] = smBreakTable[i].consoleFunction;
  1654. argv[1] = Con::getFloatArg(value);
  1655. if( smBreakTable[i].object )
  1656. {
  1657. // [neo, 5/7/2007 - #2975]
  1658. // object above can be deleted in between a make/break and so object will point
  1659. // to turfed memory and crash. To keep things simple we just store id as well so
  1660. // we can look it up to validate object ref.
  1661. if( smBreakTable[i].objectId > 0 && Sim::findObject( smBreakTable[i].objectId ) )
  1662. Con::executef(smBreakTable[i].object, 2, argv[0], argv[1]);
  1663. }
  1664. else
  1665. Con::execute(2, argv);
  1666. }
  1667. }
  1668. else if(smBreakTable[i].breakConsoleCommand)
  1669. {
  1670. Con::evaluate(smBreakTable[i].breakConsoleCommand);
  1671. dFree(smBreakTable[i].breakConsoleCommand);
  1672. }
  1673. smBreakTable.erase(i);
  1674. return true;
  1675. }
  1676. }
  1677. return false;
  1678. }
  1679. //------------------------------------------------------------------------------
  1680. bool ActionMap::handleEvent(const InputEvent* pEvent)
  1681. {
  1682. // Interate through the ActionMapSet until we get a map that
  1683. // handles the event or we run out of maps...
  1684. //
  1685. SimSet* pActionMapSet = Sim::getActiveActionMapSet();
  1686. AssertFatal(pActionMapSet && pActionMapSet->size() != 0,
  1687. "error, no ActiveMapSet or no global action map...");
  1688. for (SimSet::iterator itr = pActionMapSet->end() - 1;
  1689. itr > pActionMapSet->begin(); itr--) {
  1690. ActionMap* pMap = static_cast<ActionMap*>(*itr);
  1691. if (pMap->processAction(pEvent) == true)
  1692. return true;
  1693. }
  1694. return false;
  1695. }
  1696. //------------------------------------------------------------------------------
  1697. bool ActionMap::handleEventGlobal(const InputEvent* pEvent)
  1698. {
  1699. // Interate through the ActionMapSet until we get a map that
  1700. // handles the event or we run out of maps...
  1701. //
  1702. SimSet* pActionMapSet = Sim::getActiveActionMapSet();
  1703. AssertFatal(pActionMapSet && pActionMapSet->size() != 0,
  1704. "error, no ActiveMapSet or no global action map...");
  1705. return ((ActionMap*)pActionMapSet->first())->processAction(pEvent);
  1706. }
  1707. //------------------------------------------------------------------------------
  1708. //-------------------------------------- Key code to string mapping
  1709. // TODO: Add most obvious aliases...
  1710. //
  1711. CodeMapping gVirtualMap[] =
  1712. {
  1713. //-------------------------------------- KEYBOARD EVENTS
  1714. //
  1715. { "backspace", SI_KEY, KEY_BACKSPACE },
  1716. { "tab", SI_KEY, KEY_TAB },
  1717. { "return", SI_KEY, KEY_RETURN },
  1718. { "enter", SI_KEY, KEY_RETURN },
  1719. { "shift", SI_KEY, KEY_SHIFT },
  1720. { "ctrl", SI_KEY, KEY_CONTROL },
  1721. { "alt", SI_KEY, KEY_ALT },
  1722. { "pause", SI_KEY, KEY_PAUSE },
  1723. { "capslock", SI_KEY, KEY_CAPSLOCK },
  1724. { "escape", SI_KEY, KEY_ESCAPE },
  1725. { "space", SI_KEY, KEY_SPACE },
  1726. { "pagedown", SI_KEY, KEY_PAGE_DOWN },
  1727. { "pageup", SI_KEY, KEY_PAGE_UP },
  1728. { "end", SI_KEY, KEY_END },
  1729. { "home", SI_KEY, KEY_HOME },
  1730. { "left", SI_KEY, KEY_LEFT },
  1731. { "up", SI_KEY, KEY_UP },
  1732. { "right", SI_KEY, KEY_RIGHT },
  1733. { "down", SI_KEY, KEY_DOWN },
  1734. { "print", SI_KEY, KEY_PRINT },
  1735. { "insert", SI_KEY, KEY_INSERT },
  1736. { "delete", SI_KEY, KEY_DELETE },
  1737. { "help", SI_KEY, KEY_HELP },
  1738. { "win_lwindow", SI_KEY, KEY_WIN_LWINDOW },
  1739. { "win_rwindow", SI_KEY, KEY_WIN_RWINDOW },
  1740. { "win_apps", SI_KEY, KEY_WIN_APPS },
  1741. { "cmd", SI_KEY, KEY_ALT },
  1742. { "opt", SI_KEY, KEY_MAC_OPT },
  1743. { "lopt", SI_KEY, KEY_MAC_LOPT },
  1744. { "ropt", SI_KEY, KEY_MAC_ROPT },
  1745. { "numpad0", SI_KEY, KEY_NUMPAD0 },
  1746. { "numpad1", SI_KEY, KEY_NUMPAD1 },
  1747. { "numpad2", SI_KEY, KEY_NUMPAD2 },
  1748. { "numpad3", SI_KEY, KEY_NUMPAD3 },
  1749. { "numpad4", SI_KEY, KEY_NUMPAD4 },
  1750. { "numpad5", SI_KEY, KEY_NUMPAD5 },
  1751. { "numpad6", SI_KEY, KEY_NUMPAD6 },
  1752. { "numpad7", SI_KEY, KEY_NUMPAD7 },
  1753. { "numpad8", SI_KEY, KEY_NUMPAD8 },
  1754. { "numpad9", SI_KEY, KEY_NUMPAD9 },
  1755. { "numpadmult", SI_KEY, KEY_MULTIPLY },
  1756. { "numpadadd", SI_KEY, KEY_ADD },
  1757. { "numpadsep", SI_KEY, KEY_SEPARATOR },
  1758. { "numpadminus", SI_KEY, KEY_SUBTRACT },
  1759. { "numpaddecimal", SI_KEY, KEY_DECIMAL },
  1760. { "numpaddivide", SI_KEY, KEY_DIVIDE },
  1761. { "numpadenter", SI_KEY, KEY_NUMPADENTER },
  1762. { "f1", SI_KEY, KEY_F1 },
  1763. { "f2", SI_KEY, KEY_F2 },
  1764. { "f3", SI_KEY, KEY_F3 },
  1765. { "f4", SI_KEY, KEY_F4 },
  1766. { "f5", SI_KEY, KEY_F5 },
  1767. { "f6", SI_KEY, KEY_F6 },
  1768. { "f7", SI_KEY, KEY_F7 },
  1769. { "f8", SI_KEY, KEY_F8 },
  1770. { "f9", SI_KEY, KEY_F9 },
  1771. { "f10", SI_KEY, KEY_F10 },
  1772. { "f11", SI_KEY, KEY_F11 },
  1773. { "f12", SI_KEY, KEY_F12 },
  1774. { "f13", SI_KEY, KEY_F13 },
  1775. { "f14", SI_KEY, KEY_F14 },
  1776. { "f15", SI_KEY, KEY_F15 },
  1777. { "f16", SI_KEY, KEY_F16 },
  1778. { "f17", SI_KEY, KEY_F17 },
  1779. { "f18", SI_KEY, KEY_F18 },
  1780. { "f19", SI_KEY, KEY_F19 },
  1781. { "f20", SI_KEY, KEY_F20 },
  1782. { "f21", SI_KEY, KEY_F21 },
  1783. { "f22", SI_KEY, KEY_F22 },
  1784. { "f23", SI_KEY, KEY_F23 },
  1785. { "f24", SI_KEY, KEY_F24 },
  1786. { "numlock", SI_KEY, KEY_NUMLOCK },
  1787. { "scrolllock", SI_KEY, KEY_SCROLLLOCK },
  1788. { "lshift", SI_KEY, KEY_LSHIFT },
  1789. { "rshift", SI_KEY, KEY_RSHIFT },
  1790. { "lcontrol", SI_KEY, KEY_LCONTROL },
  1791. { "rcontrol", SI_KEY, KEY_RCONTROL },
  1792. { "lalt", SI_KEY, KEY_LALT },
  1793. { "ralt", SI_KEY, KEY_RALT },
  1794. { "tilde", SI_KEY, KEY_TILDE },
  1795. { "minus", SI_KEY, KEY_MINUS },
  1796. { "equals", SI_KEY, KEY_EQUALS },
  1797. { "lbracket", SI_KEY, KEY_LBRACKET },
  1798. { "rbracket", SI_KEY, KEY_RBRACKET },
  1799. { "backslash", SI_KEY, KEY_BACKSLASH },
  1800. { "semicolon", SI_KEY, KEY_SEMICOLON },
  1801. { "apostrophe", SI_KEY, KEY_APOSTROPHE },
  1802. { "comma", SI_KEY, KEY_COMMA },
  1803. { "period", SI_KEY, KEY_PERIOD },
  1804. { "slash", SI_KEY, KEY_SLASH },
  1805. { "lessthan", SI_KEY, KEY_OEM_102 },
  1806. //-------------------------------------- BUTTON EVENTS
  1807. // Joystick/Mouse buttons
  1808. { "button0", SI_BUTTON, KEY_BUTTON0 },
  1809. { "button1", SI_BUTTON, KEY_BUTTON1 },
  1810. { "button2", SI_BUTTON, KEY_BUTTON2 },
  1811. { "button3", SI_BUTTON, KEY_BUTTON3 },
  1812. { "button4", SI_BUTTON, KEY_BUTTON4 },
  1813. { "button5", SI_BUTTON, KEY_BUTTON5 },
  1814. { "button6", SI_BUTTON, KEY_BUTTON6 },
  1815. { "button7", SI_BUTTON, KEY_BUTTON7 },
  1816. { "button8", SI_BUTTON, KEY_BUTTON8 },
  1817. { "button9", SI_BUTTON, KEY_BUTTON9 },
  1818. { "button10", SI_BUTTON, KEY_BUTTON10 },
  1819. { "button11", SI_BUTTON, KEY_BUTTON11 },
  1820. { "button12", SI_BUTTON, KEY_BUTTON12 },
  1821. { "button13", SI_BUTTON, KEY_BUTTON13 },
  1822. { "button14", SI_BUTTON, KEY_BUTTON14 },
  1823. { "button15", SI_BUTTON, KEY_BUTTON15 },
  1824. { "button16", SI_BUTTON, KEY_BUTTON16 },
  1825. { "button17", SI_BUTTON, KEY_BUTTON17 },
  1826. { "button18", SI_BUTTON, KEY_BUTTON18 },
  1827. { "button19", SI_BUTTON, KEY_BUTTON19 },
  1828. { "button20", SI_BUTTON, KEY_BUTTON20 },
  1829. { "button21", SI_BUTTON, KEY_BUTTON21 },
  1830. { "button22", SI_BUTTON, KEY_BUTTON22 },
  1831. { "button23", SI_BUTTON, KEY_BUTTON23 },
  1832. { "button24", SI_BUTTON, KEY_BUTTON24 },
  1833. { "button25", SI_BUTTON, KEY_BUTTON25 },
  1834. { "button26", SI_BUTTON, KEY_BUTTON26 },
  1835. { "button27", SI_BUTTON, KEY_BUTTON27 },
  1836. { "button28", SI_BUTTON, KEY_BUTTON28 },
  1837. { "button29", SI_BUTTON, KEY_BUTTON29 },
  1838. { "button30", SI_BUTTON, KEY_BUTTON30 },
  1839. { "button31", SI_BUTTON, KEY_BUTTON31 },
  1840. //-------------------------------------- MOVE EVENTS
  1841. // Mouse/Joystick axes:
  1842. { "xaxis", SI_MOVE, SI_XAXIS },
  1843. { "yaxis", SI_MOVE, SI_YAXIS },
  1844. { "zaxis", SI_MOVE, SI_ZAXIS },
  1845. { "rxaxis", SI_MOVE, SI_RXAXIS },
  1846. { "ryaxis", SI_MOVE, SI_RYAXIS },
  1847. { "rzaxis", SI_MOVE, SI_RZAXIS },
  1848. { "slider", SI_MOVE, SI_SLIDER },
  1849. //-------------------------------------- POV EVENTS
  1850. // Joystick POV:
  1851. { "xpov", SI_POV, SI_XPOV },
  1852. { "ypov", SI_POV, SI_YPOV },
  1853. { "upov", SI_POV, SI_UPOV },
  1854. { "dpov", SI_POV, SI_DPOV },
  1855. { "lpov", SI_POV, SI_LPOV },
  1856. { "rpov", SI_POV, SI_RPOV },
  1857. { "xpov2", SI_POV, SI_XPOV2 },
  1858. { "ypov2", SI_POV, SI_YPOV2 },
  1859. { "upov2", SI_POV, SI_UPOV2 },
  1860. { "dpov2", SI_POV, SI_DPOV2 },
  1861. { "lpov2", SI_POV, SI_LPOV2 },
  1862. { "rpov2", SI_POV, SI_RPOV2 },
  1863. #if defined( TORQUE_OS_WIN32 ) || defined( TORQUE_OS_XENON )
  1864. //-------------------------------------- XINPUT EVENTS
  1865. // Controller connect / disconnect:
  1866. { "connect", XI_BUTTON, XI_CONNECT },
  1867. // L & R Thumbsticks:
  1868. { "thumblx", XI_AXIS, XI_THUMBLX },
  1869. { "thumbly", XI_AXIS, XI_THUMBLY },
  1870. { "thumbrx", XI_AXIS, XI_THUMBRX },
  1871. { "thumbry", XI_AXIS, XI_THUMBRY },
  1872. // L & R Triggers:
  1873. { "triggerl", XI_AXIS, XI_LEFT_TRIGGER },
  1874. { "triggerr", XI_AXIS, XI_RIGHT_TRIGGER },
  1875. // DPAD Buttons:
  1876. { "dpadu", XI_BUTTON, SI_UPOV },
  1877. { "dpadd", XI_BUTTON, SI_DPOV },
  1878. { "dpadl", XI_BUTTON, SI_LPOV },
  1879. { "dpadr", XI_BUTTON, SI_RPOV },
  1880. // START & BACK Buttons:
  1881. { "btn_start", XI_BUTTON, XI_START },
  1882. { "btn_back", XI_BUTTON, XI_BACK },
  1883. // L & R Thumbstick Buttons:
  1884. { "btn_lt", XI_BUTTON, XI_LEFT_THUMB },
  1885. { "btn_rt", XI_BUTTON, XI_RIGHT_THUMB },
  1886. // L & R Shoulder Buttons:
  1887. { "btn_l", XI_BUTTON, XI_LEFT_SHOULDER },
  1888. { "btn_r", XI_BUTTON, XI_RIGHT_SHOULDER },
  1889. // Primary buttons:
  1890. { "btn_a", XI_BUTTON, XI_A },
  1891. { "btn_b", XI_BUTTON, XI_B },
  1892. { "btn_x", XI_BUTTON, XI_X },
  1893. { "btn_y", XI_BUTTON, XI_Y },
  1894. #endif
  1895. //-------------------------------------- MOTION EVENTS
  1896. // Accelerometer/Gyroscope axes:
  1897. { "accelx", SI_MOTION, SI_ACCELX },
  1898. { "accely", SI_MOTION, SI_ACCELY },
  1899. { "accelz", SI_MOTION, SI_ACCELZ },
  1900. { "gravityx", SI_MOTION, SI_GRAVX },
  1901. { "gravityy", SI_MOTION, SI_GRAVY },
  1902. { "gravityz", SI_MOTION, SI_GRAVZ },
  1903. { "gyrox", SI_MOTION, SI_GYROX },
  1904. { "gyroy", SI_MOTION, SI_GYROY },
  1905. { "gyroz", SI_MOTION, SI_GYROZ },
  1906. { "yaw", SI_MOTION, SI_YAW },
  1907. { "pitch", SI_MOTION, SI_PITCH },
  1908. { "roll", SI_MOTION, SI_ROLL },
  1909. //-------------------------------------- TOUCH EVENTS
  1910. // Touch events:
  1911. { "touchdown", SI_TOUCH, SI_TOUCHDOWN },
  1912. { "touchup", SI_TOUCH, SI_TOUCHUP },
  1913. { "touchmove", SI_TOUCH, SI_TOUCHMOVE },
  1914. //-------------------------------------- GESTURE EVENTS
  1915. // Preset gesture events:
  1916. { "circleGesture", SI_GESTURE, SI_CIRCLE_GESTURE },
  1917. { "swipeGesture", SI_GESTURE, SI_SWIPE_GESTURE },
  1918. { "screenTapGesture", SI_GESTURE, SI_SCREENTAP_GESTURE },
  1919. { "keyTapGesture", SI_GESTURE, SI_KEYTAP_GESTURE },
  1920. { "pinchGesture", SI_GESTURE, SI_PINCH_GESTURE },
  1921. { "scaleGesture", SI_GESTURE, SI_SCALE_GESTURE },
  1922. //-------------------------------------- GESTURE EVENTS
  1923. // Preset gesture events:
  1924. { "leapHandAxis", SI_LEAP, LM_HANDAXIS },
  1925. { "leapHandPos", SI_LEAP, LM_HANDPOS },
  1926. { "leapHandRot", SI_LEAP, LM_HANDROT },
  1927. { "leapFingerPos", SI_LEAP, LM_FINGERPOS },
  1928. //-------------------------------------- MISCELLANEOUS EVENTS
  1929. //
  1930. { "anykey", SI_KEY, KEY_ANYKEY },
  1931. { "nomatch", SI_UNKNOWN, 0xFFFFFFFF }
  1932. };
  1933. AsciiMapping gAsciiMap[] =
  1934. {
  1935. //--- KEYBOARD EVENTS
  1936. //
  1937. { "space", 0x0020 },
  1938. //{ "exclamation", 0x0021 },
  1939. { "doublequote", 0x0022 },
  1940. //{ "pound", 0x0023 },
  1941. //{ "ampersand", 0x0026 },
  1942. { "apostrophe", 0x0027 },
  1943. //{ "lparen", 0x0028 },
  1944. //{ "rparen", 0x0029 },
  1945. { "comma", 0x002c },
  1946. { "minus", 0x002d },
  1947. { "period", 0x002e },
  1948. //{ "slash", 0x002f },
  1949. //{ "colon", 0x003a },
  1950. //{ "semicolon", 0x003b },
  1951. //{ "lessthan", 0x003c },
  1952. //{ "equals", 0x003d },
  1953. //{ "morethan", 0x003e },
  1954. //{ "lbracket", 0x005b },
  1955. { "backslash", 0x005c },
  1956. //{ "rbracket", 0x005d },
  1957. //{ "circumflex", 0x005e },
  1958. //{ "underscore", 0x005f },
  1959. { "grave", 0x0060 },
  1960. //{ "tilde", 0x007e },
  1961. //{ "vertbar", 0x007c },
  1962. //{ "exclamdown", 0x00a1 },
  1963. //{ "cent", 0x00a2 },
  1964. //{ "sterling", 0x00a3 },
  1965. //{ "currency", 0x00a4 },
  1966. //{ "brokenbar", 0x00a6 },
  1967. //{ "ring", 0x00b0 },
  1968. //{ "plusminus", 0x00b1 },
  1969. { "super2", 0x00b2 },
  1970. { "super3", 0x00b3 },
  1971. { "acute", 0x00b4 },
  1972. //{ "mu", 0x00b5 },
  1973. //{ "ordmasculine", 0x00ba },
  1974. //{ "questiondown", 0x00bf },
  1975. //{ "gemandbls", 0x00df },
  1976. //{ "agrave", 0x00e0 },
  1977. //{ "aacute", 0x00e1 },
  1978. //{ "acircumflex", 0x00e2 },
  1979. //{ "atilde", 0x00e3 },
  1980. //{ "adieresis", 0x00e4 },
  1981. //{ "aring", 0x00e5 },
  1982. //{ "ae", 0x00e6 },
  1983. //{ "ccedille", 0x00e7 },
  1984. //{ "egrave", 0x00e8 },
  1985. //{ "eacute", 0x00e9 },
  1986. //{ "ecircumflex", 0x00ea },
  1987. //{ "edieresis", 0x00eb },
  1988. //{ "igrave", 0x00ec },
  1989. //{ "iacute", 0x00ed },
  1990. //{ "icircumflex", 0x00ee },
  1991. //{ "idieresis", 0x00ef },
  1992. //{ "ntilde", 0x00f1 },
  1993. //{ "ograve", 0x00f2 },
  1994. //{ "oacute", 0x00f3 },
  1995. //{ "ocircumflex", 0x00f4 },
  1996. //{ "otilde", 0x00f5 },
  1997. //{ "odieresis", 0x00f6 },
  1998. //{ "divide", 0x00f7 },
  1999. //{ "oslash", 0x00f8 },
  2000. //{ "ugrave", 0x00f9 },
  2001. //{ "uacute", 0x00fa },
  2002. //{ "ucircumflex", 0x00fb },
  2003. //{ "udieresis", 0x00fc },
  2004. //{ "ygrave", 0x00fd },
  2005. //{ "thorn", 0x00fe },
  2006. //{ "ydieresis", 0x00ff },
  2007. { "nomatch", 0xFFFF }
  2008. };
  2009. ////Device Event Types
  2010. //#define SI_UNKNOWN 0x01
  2011. //#define SI_BUTTON 0x02
  2012. //#define SI_POV 0x03
  2013. //#define SI_XPOV 0x04
  2014. //#define SI_YPOV 0x05
  2015. //#define SI_UPOV 0x06
  2016. //#define SI_DPOV 0x07
  2017. //#define SI_LPOV 0x08
  2018. //#define SI_RPOV 0x09
  2019. //#define SI_KEY 0x0A
  2020. //#define SI_XAXIS 0x0B
  2021. //#define SI_YAXIS 0x0C
  2022. //#define SI_ZAXIS 0x0D
  2023. //#define SI_RXAXIS 0x0E
  2024. //#define SI_RYAXIS 0x0F
  2025. //#define SI_RZAXIS 0x10
  2026. //#define SI_SLIDER 0x11