actionMap.cc 77 KB

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