winDInputDevice.cpp 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 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. #ifndef INITGUID
  23. #define INITGUID
  24. #endif
  25. #include "platform/platform.h"
  26. #include "platformWin32/winDInputDevice.h"
  27. #include "math/mMath.h"
  28. #include "console/console.h"
  29. #include "core/strings/unicode.h"
  30. #include "windowManager/platformWindowMgr.h"
  31. // Static class data:
  32. LPDIRECTINPUT8 DInputDevice::smDInputInterface;
  33. U8 DInputDevice::smDeviceCount[ NUM_INPUT_DEVICE_TYPES ];
  34. bool DInputDevice::smInitialized = false;
  35. #ifdef LOG_INPUT
  36. const char* getKeyName( U16 key );
  37. #endif
  38. //------------------------------------------------------------------------------
  39. DInputDevice::DInputDevice( const DIDEVICEINSTANCE* dii )
  40. {
  41. mDeviceInstance = *dii;
  42. mDevice = NULL;
  43. mAcquired = false;
  44. mNeedSync = false;
  45. mObjInstance = NULL;
  46. mObjFormat = NULL;
  47. mObjInfo = NULL;
  48. mObjBuffer1 = NULL;
  49. mObjBuffer2 = NULL;
  50. mPrevObjBuffer = NULL;
  51. mForceFeedbackEffect = NULL;
  52. mNumForceFeedbackAxes = 0;
  53. mForceFeedbackAxes[0] = 0;
  54. mForceFeedbackAxes[1] = 0;
  55. const char* deviceTypeName = "unknown";
  56. U8 deviceType = UnknownDeviceType;
  57. switch ( GET_DIDEVICE_TYPE( mDeviceInstance.dwDevType ) )
  58. {
  59. // [rene, 12/09/2008] why do we turn a gamepad into a joystick here?
  60. case DI8DEVTYPE_DRIVING:
  61. case DI8DEVTYPE_GAMEPAD:
  62. case DI8DEVTYPE_JOYSTICK:
  63. deviceTypeName = "joystick";
  64. deviceType = JoystickDeviceType;
  65. break;
  66. case DI8DEVTYPE_KEYBOARD:
  67. deviceTypeName = "keyboard";
  68. deviceType = KeyboardDeviceType;
  69. break;
  70. case DI8DEVTYPE_MOUSE:
  71. deviceTypeName = "mouse";
  72. deviceType = MouseDeviceType;
  73. break;
  74. }
  75. mDeviceType = deviceType;
  76. mDeviceID = smDeviceCount[ deviceType ] ++;
  77. dSprintf( mName, 29, "%s%d", deviceTypeName, mDeviceID );
  78. }
  79. //------------------------------------------------------------------------------
  80. DInputDevice::~DInputDevice()
  81. {
  82. destroy();
  83. }
  84. //------------------------------------------------------------------------------
  85. void DInputDevice::init()
  86. {
  87. // Reset all of the static variables:
  88. smDInputInterface = NULL;
  89. dMemset( smDeviceCount, 0, sizeof( smDeviceCount ) );
  90. }
  91. //------------------------------------------------------------------------------
  92. bool DInputDevice::create()
  93. {
  94. HRESULT result;
  95. if ( smDInputInterface )
  96. {
  97. result = smDInputInterface->CreateDevice( mDeviceInstance.guidInstance, &mDevice, NULL );
  98. if ( result == DI_OK )
  99. {
  100. mDeviceCaps.dwSize = sizeof( DIDEVCAPS );
  101. if ( FAILED( mDevice->GetCapabilities( &mDeviceCaps ) ) )
  102. {
  103. Con::errorf( " Failed to get the capabilities of the %s input device.", mName );
  104. #ifdef LOG_INPUT
  105. Input::log( "Failed to get the capabilities of &s!\n", mName );
  106. #endif
  107. return false;
  108. }
  109. #ifdef LOG_INPUT
  110. Input::log( "%s detected, created as %s (%s).\n", mDeviceInstance.tszProductName, mName, ( isPolled() ? "polled" : "asynchronous" ) );
  111. #endif
  112. if ( enumerateObjects() )
  113. {
  114. // Set the device's data format:
  115. DIDATAFORMAT dataFormat;
  116. dMemset( &dataFormat, 0, sizeof( DIDATAFORMAT ) );
  117. dataFormat.dwSize = sizeof( DIDATAFORMAT );
  118. dataFormat.dwObjSize = sizeof( DIOBJECTDATAFORMAT );
  119. dataFormat.dwFlags = ( mDeviceType == MouseDeviceType ) ? DIDF_RELAXIS : DIDF_ABSAXIS;
  120. dataFormat.dwDataSize = mObjBufferSize;
  121. dataFormat.dwNumObjs = mObjCount;
  122. dataFormat.rgodf = mObjFormat;
  123. result = mDevice->SetDataFormat( &dataFormat );
  124. if ( FAILED( result ) )
  125. {
  126. Con::errorf( " Failed to set the data format for the %s input device.", mName );
  127. #ifdef LOG_INPUT
  128. Input::log( "Failed to set the data format for %s!\n", mName );
  129. #endif
  130. return false;
  131. }
  132. // Set up the data buffer for buffered input:
  133. DIPROPDWORD prop;
  134. prop.diph.dwSize = sizeof( DIPROPDWORD );
  135. prop.diph.dwHeaderSize = sizeof( DIPROPHEADER );
  136. prop.diph.dwObj = 0;
  137. prop.diph.dwHow = DIPH_DEVICE;
  138. if ( isPolled() )
  139. prop.dwData = mObjBufferSize;
  140. else
  141. prop.dwData = QUEUED_BUFFER_SIZE;
  142. result = mDevice->SetProperty( DIPROP_BUFFERSIZE, &prop.diph );
  143. if ( FAILED( result ) )
  144. {
  145. Con::errorf( " Failed to set the buffer size property for the %s input device.", mName );
  146. #ifdef LOG_INPUT
  147. Input::log( "Failed to set the buffer size property for %s!\n", mName );
  148. #endif
  149. return false;
  150. }
  151. // If this device is a mouse, set it to relative axis mode:
  152. if ( mDeviceType == MouseDeviceType )
  153. {
  154. prop.diph.dwObj = 0;
  155. prop.diph.dwHow = DIPH_DEVICE;
  156. prop.dwData = DIPROPAXISMODE_REL;
  157. result = mDevice->SetProperty( DIPROP_AXISMODE, &prop.diph );
  158. if ( FAILED( result ) )
  159. {
  160. Con::errorf( " Failed to set relative axis mode for the %s input device.", mName );
  161. #ifdef LOG_INPUT
  162. Input::log( "Failed to set relative axis mode for %s!\n", mName );
  163. #endif
  164. return false;
  165. }
  166. }
  167. }
  168. }
  169. else
  170. {
  171. #ifdef LOG_INPUT
  172. switch ( result )
  173. {
  174. case DIERR_DEVICENOTREG:
  175. Input::log( "CreateDevice failed -- The device or device instance is not registered with DirectInput.\n" );
  176. break;
  177. case DIERR_INVALIDPARAM:
  178. Input::log( "CreateDevice failed -- Invalid parameter.\n" );
  179. break;
  180. case DIERR_NOINTERFACE:
  181. Input::log( "CreateDevice failed -- The specified interface is not supported by the object.\n" );
  182. break;
  183. case DIERR_OUTOFMEMORY:
  184. Input::log( "CreateDevice failed -- Out of memory.\n" );
  185. break;
  186. default:
  187. Input::log( "CreateDevice failed -- Unknown error.\n" );
  188. break;
  189. };
  190. #endif // LOG_INPUT
  191. Con::printf( " CreateDevice failed for the %s input device!", mName );
  192. return false;
  193. }
  194. }
  195. Con::printf( " %s input device created.", mName );
  196. return true;
  197. }
  198. //------------------------------------------------------------------------------
  199. void DInputDevice::destroy()
  200. {
  201. if ( mDevice )
  202. {
  203. unacquire();
  204. // Tear down our forcefeedback.
  205. if (mForceFeedbackEffect)
  206. {
  207. mForceFeedbackEffect->Release();
  208. mForceFeedbackEffect = NULL;
  209. mNumForceFeedbackAxes = 0;
  210. #ifdef LOG_INPUT
  211. Input::log("DInputDevice::destroy - releasing constant force feeback effect\n");
  212. #endif
  213. }
  214. mDevice->Release();
  215. mDevice = NULL;
  216. delete [] mObjInstance;
  217. delete [] mObjFormat;
  218. delete [] mObjInfo;
  219. delete [] mObjBuffer1;
  220. delete [] mObjBuffer2;
  221. mObjInstance = NULL;
  222. mObjFormat = NULL;
  223. mObjInfo = NULL;
  224. mObjBuffer1 = NULL;
  225. mObjBuffer2 = NULL;
  226. mPrevObjBuffer = NULL;
  227. mName[0] = 0;
  228. }
  229. }
  230. //------------------------------------------------------------------------------
  231. bool DInputDevice::acquire()
  232. {
  233. if ( mDevice )
  234. {
  235. if ( mAcquired )
  236. return( true );
  237. bool result = false;
  238. // Set the cooperative level:
  239. // (do this here so that we have a valid app window)
  240. DWORD coopLevel = DISCL_BACKGROUND;
  241. if ( mDeviceType == JoystickDeviceType
  242. // #ifndef DEBUG
  243. // || mDeviceType == MouseDeviceType
  244. // #endif
  245. )
  246. // Exclusive access is required in order to perform force feedback
  247. coopLevel = DISCL_EXCLUSIVE | DISCL_FOREGROUND;
  248. else
  249. coopLevel |= DISCL_NONEXCLUSIVE;
  250. result = mDevice->SetCooperativeLevel( getWin32WindowHandle(), coopLevel );
  251. if ( FAILED( result ) )
  252. {
  253. Con::errorf( "Failed to set the cooperative level for the %s input device.", mName );
  254. #ifdef LOG_INPUT
  255. Input::log( "Failed to set the cooperative level for %s!\n", mName );
  256. #endif
  257. return false;
  258. }
  259. // Enumerate joystick axes to enable force feedback
  260. if ( NULL == mForceFeedbackEffect && JoystickDeviceType == mDeviceType)
  261. {
  262. // Since we will be playing force feedback effects, we should disable the auto-centering spring.
  263. DIPROPDWORD dipdw;
  264. dipdw.diph.dwSize = sizeof(DIPROPDWORD);
  265. dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  266. dipdw.diph.dwObj = 0;
  267. dipdw.diph.dwHow = DIPH_DEVICE;
  268. dipdw.dwData = FALSE;
  269. if( FAILED( result = mDevice->SetProperty( DIPROP_AUTOCENTER, &dipdw.diph ) ) )
  270. return false;
  271. }
  272. S32 code = mDevice->Acquire();
  273. result = SUCCEEDED( code );
  274. if ( result )
  275. {
  276. Con::printf( "%s input device acquired.", mName );
  277. #ifdef LOG_INPUT
  278. Input::log( "%s acquired.\n", mName );
  279. #endif
  280. mAcquired = true;
  281. // If we were previously playing a force feedback effect, before
  282. // losing acquisition, we do not automatically restart it. This is
  283. // where you could call mForceFeedbackEffect->Start( INFINITE, 0 );
  284. // if you want that behavior.
  285. // Update all of the key states:
  286. if ( !isPolled() )
  287. mNeedSync = true;
  288. }
  289. else
  290. {
  291. const char* reason;
  292. switch ( code )
  293. {
  294. case DIERR_INVALIDPARAM: reason = "Invalid parameter" ; break;
  295. case DIERR_NOTINITIALIZED: reason = "Not initialized"; break;
  296. case DIERR_OTHERAPPHASPRIO: reason = "Other app has priority"; break;
  297. case S_FALSE: reason = "Already acquired"; break;
  298. default: reason = "Unknown error"; break;
  299. }
  300. Con::warnf( "%s input device NOT acquired: %s", mName, reason );
  301. #ifdef LOG_INPUT
  302. Input::log( "Failed to acquire %s: %s\n", mName, reason );
  303. #endif
  304. }
  305. return( result );
  306. }
  307. return( false );
  308. }
  309. //------------------------------------------------------------------------------
  310. bool DInputDevice::unacquire()
  311. {
  312. if ( mDevice )
  313. {
  314. if ( !mAcquired )
  315. return( true );
  316. bool result = false;
  317. result = SUCCEEDED( mDevice->Unacquire() );
  318. if ( result )
  319. {
  320. Con::printf( "%s input device unacquired.", mName );
  321. #ifdef LOG_INPUT
  322. Input::log( "%s unacquired.\n", mName );
  323. #endif
  324. mAcquired = false;
  325. }
  326. else
  327. {
  328. Con::warnf( ConsoleLogEntry::General, "%s input device NOT unacquired.", mName );
  329. #ifdef LOG_INPUT
  330. Input::log( "Failed to unacquire %s!\n", mName );
  331. #endif
  332. }
  333. return( result );
  334. }
  335. return( false );
  336. }
  337. //------------------------------------------------------------------------------
  338. BOOL CALLBACK DInputDevice::EnumObjectsProc( const DIDEVICEOBJECTINSTANCE* doi, LPVOID pvRef )
  339. {
  340. // Don't enumerate unknown types:
  341. if ( doi->guidType == GUID_Unknown )
  342. return (DIENUM_CONTINUE);
  343. // Reduce a couple pointers:
  344. DInputDevice* diDevice = (DInputDevice*) pvRef;
  345. DIDEVICEOBJECTINSTANCE* objInstance = &diDevice->mObjInstance[diDevice->mObjEnumCount];
  346. DIOBJECTDATAFORMAT* objFormat = &diDevice->mObjFormat[diDevice->mObjEnumCount];
  347. // Fill in the object instance structure:
  348. *objInstance = *doi;
  349. // DWORD objects must be DWORD aligned:
  350. if ( !(objInstance->dwType & DIDFT_BUTTON ) )
  351. diDevice->mObjBufferOfs = ( diDevice->mObjBufferOfs + 3 ) & ~3;
  352. objInstance->dwOfs = diDevice->mObjBufferOfs;
  353. // Fill in the object data format structure:
  354. objFormat->pguid = &objInstance->guidType;
  355. objFormat->dwType = objInstance->dwType;
  356. objFormat->dwFlags= 0;
  357. objFormat->dwOfs = diDevice->mObjBufferOfs;
  358. // Advance the enumeration counters:
  359. if ( objFormat->dwType & DIDFT_BUTTON )
  360. diDevice->mObjBufferOfs += SIZEOF_BUTTON;
  361. else
  362. diDevice->mObjBufferOfs += SIZEOF_AXIS;
  363. diDevice->mObjEnumCount++;
  364. return (DIENUM_CONTINUE);
  365. }
  366. //------------------------------------------------------------------------------
  367. bool DInputDevice::enumerateObjects()
  368. {
  369. if ( !mDevice )
  370. return false;
  371. // Calculate the needed buffer sizes and allocate them:
  372. mObjCount = ( mDeviceCaps.dwAxes + mDeviceCaps.dwButtons + mDeviceCaps.dwPOVs );
  373. mObjBufferSize = mObjCount * sizeof( DWORD );
  374. mObjInstance = new DIDEVICEOBJECTINSTANCE[mObjCount];
  375. mObjFormat = new DIOBJECTDATAFORMAT[mObjCount];
  376. mObjInfo = new ObjInfo[mObjCount];
  377. if ( isPolled() )
  378. {
  379. mObjBuffer1 = new U8[mObjBufferSize];
  380. dMemset( mObjBuffer1, 0, mObjBufferSize );
  381. mObjBuffer2 = new U8[mObjBufferSize];
  382. dMemset( mObjBuffer2, 0, mObjBufferSize );
  383. }
  384. mObjEnumCount = 0;
  385. mObjBufferOfs = 0;
  386. // We are about to enumerate, clear the axes we claim to know about
  387. mNumForceFeedbackAxes = 0;
  388. // Enumerate all of the 'objects' detected on the device:
  389. if ( FAILED( mDevice->EnumObjects( EnumObjectsProc, this, DIDFT_ALL ) ) )
  390. return false;
  391. // We only supports one or two axis joysticks
  392. if( mNumForceFeedbackAxes > 2 )
  393. mNumForceFeedbackAxes = 2;
  394. // if we enumerated fewer objects than are supposedly available, reset the
  395. // object count
  396. if (mObjEnumCount < mObjCount)
  397. mObjCount = mObjEnumCount;
  398. mObjBufferSize = ( mObjBufferSize + 3 ) & ~3; // Fill in the actual size to nearest DWORD
  399. U32 buttonCount = 0;
  400. U32 povCount = 0;
  401. U32 keyCount = 0;
  402. U32 unknownCount = 0;
  403. // Fill in the device object's info structure:
  404. for ( U32 i = 0; i < mObjCount; i++ )
  405. {
  406. if ( mObjInstance[i].guidType == GUID_Button )
  407. {
  408. mObjInfo[i].mType = SI_BUTTON;
  409. mObjInfo[i].mInst = (InputObjectInstances)(KEY_BUTTON0 + buttonCount++);
  410. }
  411. else if ( mObjInstance[i].guidType == GUID_POV )
  412. {
  413. // This is actually intentional - the POV handling code lower down
  414. // takes the instance number and converts everything to button events.
  415. mObjInfo[i].mType = SI_POV;
  416. mObjInfo[i].mInst = (InputObjectInstances)povCount++;
  417. }
  418. else if ( mObjInstance[i].guidType == GUID_XAxis )
  419. {
  420. mObjInfo[i].mType = SI_AXIS;
  421. mObjInfo[i].mInst = SI_XAXIS;
  422. if (mObjInstance[i].dwFFMaxForce > 0)
  423. mForceFeedbackAxes[mNumForceFeedbackAxes++] = mObjInstance[i].dwOfs;
  424. }
  425. else if ( mObjInstance[i].guidType == GUID_YAxis )
  426. {
  427. mObjInfo[i].mType = SI_AXIS;
  428. mObjInfo[i].mInst = SI_YAXIS;
  429. if (mObjInstance[i].dwFFMaxForce > 0)
  430. mForceFeedbackAxes[mNumForceFeedbackAxes++] = mObjInstance[i].dwOfs;
  431. }
  432. else if ( mObjInstance[i].guidType == GUID_ZAxis )
  433. {
  434. mObjInfo[i].mType = SI_AXIS;
  435. mObjInfo[i].mInst = SI_ZAXIS;
  436. }
  437. else if ( mObjInstance[i].guidType == GUID_RxAxis )
  438. {
  439. mObjInfo[i].mType = SI_AXIS;
  440. mObjInfo[i].mInst = SI_RXAXIS;
  441. }
  442. else if ( mObjInstance[i].guidType == GUID_RyAxis )
  443. {
  444. mObjInfo[i].mType = SI_AXIS;
  445. mObjInfo[i].mInst = SI_RYAXIS;
  446. }
  447. else if ( mObjInstance[i].guidType == GUID_RzAxis )
  448. {
  449. mObjInfo[i].mType = SI_AXIS;
  450. mObjInfo[i].mInst = SI_RZAXIS;
  451. }
  452. else if ( mObjInstance[i].guidType == GUID_Slider )
  453. {
  454. mObjInfo[i].mType = SI_AXIS;
  455. mObjInfo[i].mInst = SI_SLIDER;
  456. }
  457. else if ( mObjInstance[i].guidType == GUID_Key )
  458. {
  459. mObjInfo[i].mType = SI_KEY;
  460. mObjInfo[i].mInst = DIK_to_Key( DIDFT_GETINSTANCE( mObjFormat[i].dwType ) );
  461. keyCount++;
  462. }
  463. else
  464. {
  465. mObjInfo[i].mType = SI_UNKNOWN;
  466. mObjInfo[i].mInst = (InputObjectInstances)unknownCount++;
  467. }
  468. // Set the device object's min and max values:
  469. if ( mObjInstance[i].guidType == GUID_Button
  470. || mObjInstance[i].guidType == GUID_Key
  471. || mObjInstance[i].guidType == GUID_POV )
  472. {
  473. mObjInfo[i].mMin = DIPROPRANGE_NOMIN;
  474. mObjInfo[i].mMax = DIPROPRANGE_NOMAX;
  475. }
  476. else
  477. {
  478. // This is an axis or a slider, so find out its range:
  479. DIPROPRANGE pr;
  480. pr.diph.dwSize = sizeof( pr );
  481. pr.diph.dwHeaderSize = sizeof( pr.diph );
  482. pr.diph.dwHow = DIPH_BYID;
  483. pr.diph.dwObj = mObjFormat[i].dwType;
  484. if ( SUCCEEDED( mDevice->GetProperty( DIPROP_RANGE, &pr.diph ) ) )
  485. {
  486. mObjInfo[i].mMin = pr.lMin;
  487. mObjInfo[i].mMax = pr.lMax;
  488. }
  489. else
  490. {
  491. mObjInfo[i].mMin = DIPROPRANGE_NOMIN;
  492. mObjInfo[i].mMax = DIPROPRANGE_NOMAX;
  493. }
  494. }
  495. }
  496. #ifdef LOG_INPUT
  497. Input::log( " %d total objects detected.\n", mObjCount );
  498. if ( buttonCount )
  499. Input::log( " %d buttons.\n", buttonCount );
  500. if ( povCount )
  501. Input::log( " %d POVs.\n", povCount );
  502. if ( keyCount )
  503. Input::log( " %d keys.\n", keyCount );
  504. if ( unknownCount )
  505. Input::log( " %d unknown objects.\n", unknownCount );
  506. Input::log( "\n" );
  507. #endif
  508. return true;
  509. }
  510. //------------------------------------------------------------------------------
  511. const char* DInputDevice::getName()
  512. {
  513. #ifdef UNICODE
  514. static UTF8 buf[512];
  515. convertUTF16toUTF8(mDeviceInstance.tszInstanceName, buf);
  516. return (const char *)buf;
  517. #else
  518. return mDeviceInstance.tszInstanceName;
  519. #endif
  520. }
  521. //------------------------------------------------------------------------------
  522. const char* DInputDevice::getProductName()
  523. {
  524. #ifdef UNICODE
  525. static UTF8 buf[512];
  526. convertUTF16toUTF8(mDeviceInstance.tszProductName, buf);
  527. return (const char *)buf;
  528. #else
  529. return mDeviceInstance.tszProductName;
  530. #endif
  531. }
  532. //------------------------------------------------------------------------------
  533. bool DInputDevice::process()
  534. {
  535. if ( mAcquired )
  536. {
  537. if ( isPolled() )
  538. return processImmediate();
  539. else
  540. return processAsync();
  541. }
  542. return false;
  543. }
  544. //------------------------------------------------------------------------------
  545. bool DInputDevice::processAsync()
  546. {
  547. DIDEVICEOBJECTDATA eventBuffer[QUEUED_BUFFER_SIZE];
  548. DWORD numEvents = QUEUED_BUFFER_SIZE;
  549. HRESULT result;
  550. if ( !mDevice )
  551. return false;
  552. do
  553. {
  554. result = mDevice->GetDeviceData( sizeof( DIDEVICEOBJECTDATA ), eventBuffer, &numEvents, 0 );
  555. if ( !SUCCEEDED( result ) )
  556. {
  557. switch ( result )
  558. {
  559. case DIERR_INPUTLOST:
  560. // Data stream was interrupted, so try to reacquire the device:
  561. mAcquired = false;
  562. acquire();
  563. break;
  564. case DIERR_INVALIDPARAM:
  565. Con::errorf( "DInputDevice::processAsync -- Invalid parameter passed to GetDeviceData of the %s input device!", mName );
  566. #ifdef LOG_INPUT
  567. Input::log( "Invalid parameter passed to GetDeviceData for %s!\n", mName );
  568. #endif
  569. break;
  570. case DIERR_NOTACQUIRED:
  571. // We can't get the device, so quit:
  572. mAcquired = false;
  573. // Don't error out - this is actually a natural occurrence...
  574. //Con::errorf( "DInputDevice::processAsync -- GetDeviceData called when %s input device is not acquired!", mName );
  575. #ifdef LOG_INPUT
  576. Input::log( "GetDeviceData called when %s is not acquired!\n", mName );
  577. #endif
  578. break;
  579. }
  580. return false;
  581. }
  582. // We have buffered input, so act on it:
  583. for ( DWORD i = 0; i < numEvents; i++ )
  584. buildEvent( findObjInstance( eventBuffer[i].dwOfs ), eventBuffer[i].dwData, eventBuffer[i].dwData );
  585. // Check for buffer overflow:
  586. if ( result == DI_BUFFEROVERFLOW )
  587. {
  588. // This is a problem, but we can keep going...
  589. Con::errorf( "DInputDevice::processAsync -- %s input device's event buffer overflowed!", mName );
  590. #ifdef LOG_INPUT
  591. Input::log( "%s event buffer overflowed!\n", mName );
  592. #endif
  593. mNeedSync = true; // Let it know to resync next time through...
  594. }
  595. }
  596. while ( numEvents );
  597. return true;
  598. }
  599. //------------------------------------------------------------------------------
  600. bool DInputDevice::processImmediate()
  601. {
  602. if ( !mDevice )
  603. return false;
  604. mDevice->Poll();
  605. U8* buffer = ( mPrevObjBuffer == mObjBuffer1 ) ? mObjBuffer2 : mObjBuffer1;
  606. HRESULT result = mDevice->GetDeviceState( mObjBufferSize, buffer );
  607. if ( !SUCCEEDED( result ) )
  608. {
  609. switch ( result )
  610. {
  611. case DIERR_INPUTLOST:
  612. // Data stream was interrupted, so try to reacquire the device:
  613. mAcquired = false;
  614. acquire();
  615. break;
  616. case DIERR_INVALIDPARAM:
  617. Con::errorf( "DInputDevice::processPolled -- invalid parameter passed to GetDeviceState on %s input device!", mName );
  618. #ifdef LOG_INPUT
  619. Input::log( "Invalid parameter passed to GetDeviceState on %s.\n", mName );
  620. #endif
  621. break;
  622. case DIERR_NOTACQUIRED:
  623. Con::errorf( "DInputDevice::processPolled -- GetDeviceState called when %s input device is not acquired!", mName );
  624. #ifdef LOG_INPUT
  625. Input::log( "GetDeviceState called when %s is not acquired!\n", mName );
  626. #endif
  627. break;
  628. case E_PENDING:
  629. Con::warnf( "DInputDevice::processPolled -- Data not yet available for the %s input device!", mName );
  630. #ifdef LOG_INPUT
  631. Input::log( "Data pending for %s.", mName );
  632. #endif
  633. break;
  634. }
  635. return false;
  636. }
  637. // Loop through all of the objects and produce events where
  638. // the states have changed:
  639. // (oldData = 0 prevents a crashing bug in Torque. There is a case where
  640. // Torque accessed oldData without it ever being set.)
  641. S32 newData, oldData = 0;
  642. for ( DWORD i = 0; i < mObjCount; i++ )
  643. {
  644. if ( mObjFormat[i].dwType & DIDFT_BUTTON )
  645. {
  646. if ( mPrevObjBuffer )
  647. {
  648. newData = *( (U8*) ( buffer + mObjFormat[i].dwOfs ) );
  649. oldData = *( (U8*) ( mPrevObjBuffer + mObjFormat[i].dwOfs ) );
  650. if ( newData == oldData )
  651. continue;
  652. }
  653. else
  654. continue;
  655. }
  656. else if ( mObjFormat[i].dwType & DIDFT_POV )
  657. {
  658. if ( mPrevObjBuffer )
  659. {
  660. newData = *( (S32*) ( buffer + mObjFormat[i].dwOfs ) );
  661. oldData = *( (S32*) ( mPrevObjBuffer + mObjFormat[i].dwOfs ) );
  662. if ( LOWORD( newData ) == LOWORD( oldData ) )
  663. continue;
  664. }
  665. else
  666. continue;
  667. }
  668. else
  669. {
  670. // report normal axes every time through the loop:
  671. newData = *( (S32*) ( buffer + mObjFormat[i].dwOfs ) );
  672. }
  673. // Build an event:
  674. buildEvent( i, newData, oldData );
  675. }
  676. mPrevObjBuffer = buffer;
  677. return true;
  678. }
  679. //------------------------------------------------------------------------------
  680. DWORD DInputDevice::findObjInstance( DWORD offset )
  681. {
  682. DIDEVICEOBJECTINSTANCE *inst = mObjInstance;
  683. for ( U32 i = 0; i < mObjCount; i++, inst++ )
  684. {
  685. if ( inst->dwOfs == offset )
  686. return i;
  687. }
  688. AssertFatal( false, "DInputDevice::findObjInstance -- failed to locate object instance." );
  689. return 0;
  690. }
  691. //------------------------------------------------------------------------------
  692. enum Win32POVDirBits
  693. {
  694. POV_up = 1 << 0,
  695. POV_right = 1 << 1,
  696. POV_down = 1 << 2,
  697. POV_left = 1 << 3,
  698. };
  699. enum Win32POVDirsInQuadrant
  700. {
  701. POVq_center = 0,
  702. POVq_up = POV_up,
  703. POVq_upright = POV_up | POV_right,
  704. POVq_right = POV_right,
  705. POVq_downright = POV_down | POV_right,
  706. POVq_down = POV_down,
  707. POVq_downleft = POV_down | POV_left,
  708. POVq_left = POV_left,
  709. POVq_upleft = POV_up | POV_left,
  710. };
  711. static const U32 Win32POVQuadrantMap[] =
  712. {
  713. POVq_up, POVq_upright,
  714. POVq_right, POVq_downright,
  715. POVq_down, POVq_downleft,
  716. POVq_left, POVq_upleft
  717. };
  718. static U32 _Win32GetPOVDirs(U32 data)
  719. {
  720. U32 quadrant = (data / 4500) % 8;
  721. U32 dirs = (data == 0xffff) ? POVq_center : Win32POVQuadrantMap[quadrant];
  722. return dirs;
  723. }
  724. #if defined(LOG_INPUT)
  725. static void _Win32LogPOVInput(InputEventInfo &newEvent)
  726. {
  727. U32 inst = 0xffff;
  728. const char* sstate = ( newEvent.action == SI_MAKE ) ? "pressed" : "released";
  729. const char* dir = "";
  730. switch( newEvent.objInst )
  731. {
  732. case SI_UPOV:
  733. case SI_UPOV2:
  734. dir = "Up"; inst = (newEvent.objInst == SI_UPOV) ? 1 : 2; break;
  735. case SI_RPOV:
  736. case SI_RPOV2:
  737. dir = "Right"; inst = (newEvent.objInst == SI_RPOV) ? 1 : 2; break;
  738. case SI_DPOV:
  739. case SI_DPOV2:
  740. dir = "Down"; inst = (newEvent.objInst == SI_DPOV) ? 1 : 2; break;
  741. case SI_LPOV:
  742. case SI_LPOV2:
  743. dir = "Left"; inst = (newEvent.objInst == SI_LPOV) ? 1 : 2; break;
  744. }
  745. Con::printf( "EVENT (DInput): %s POV %d %s.\n", dir, inst, sstate);
  746. }
  747. #else
  748. #define _Win32LogPOVInput( a )
  749. #endif
  750. //------------------------------------------------------------------------------
  751. bool DInputDevice::buildEvent( DWORD offset, S32 newData, S32 oldData )
  752. {
  753. ObjInfo &objInfo = mObjInfo[offset];
  754. if ( objInfo.mType == SI_UNKNOWN )
  755. return false;
  756. InputEventInfo newEvent;
  757. newEvent.deviceType = (InputDeviceTypes)mDeviceType;
  758. newEvent.deviceInst = mDeviceID;
  759. newEvent.objType = objInfo.mType;
  760. newEvent.objInst = objInfo.mInst;
  761. newEvent.modifier = (InputModifiers)0;
  762. switch ( newEvent.objType )
  763. {
  764. case SI_AXIS:
  765. newEvent.action = SI_MOVE;
  766. if ( newEvent.deviceType == MouseDeviceType )
  767. {
  768. newEvent.fValue = float( newData );
  769. #ifdef LOG_INPUT
  770. #ifdef LOG_MOUSEMOVE
  771. if ( newEvent.objInst == SI_XAXIS )
  772. Input::log( "EVENT (DInput): %s move (%.1f, 0.0).\n", mName, newEvent.fValue );
  773. else if ( newEvent.objInst == SI_YAXIS )
  774. Input::log( "EVENT (DInput): %s move (0.0, %.1f).\n", mName, newEvent.fValue );
  775. else
  776. #endif
  777. if ( newEvent.objInst == SI_ZAXIS )
  778. Input::log( "EVENT (DInput): %s wheel move %.1f.\n", mName, newEvent.fValue );
  779. #endif
  780. }
  781. else // Joystick or other device:
  782. {
  783. // Scale to the range -1.0 to 1.0:
  784. if ( objInfo.mMin != DIPROPRANGE_NOMIN && objInfo.mMax != DIPROPRANGE_NOMAX )
  785. {
  786. F32 range = F32( objInfo.mMax - objInfo.mMin );
  787. newEvent.fValue = F32( ( 2 * newData ) - objInfo.mMax - objInfo.mMin ) / range;
  788. }
  789. else
  790. newEvent.fValue = (F32)newData;
  791. #ifdef LOG_INPUT
  792. // Keep this commented unless you REALLY want these messages for something--
  793. // they come once per each iteration of the main game loop.
  794. //switch ( newEvent.objType )
  795. //{
  796. //case SI_XAXIS:
  797. //if ( newEvent.fValue < -0.01f || newEvent.fValue > 0.01f )
  798. //Input::log( "EVENT (DInput): %s X-axis move %.2f.\n", mName, newEvent.fValue );
  799. //break;
  800. //case SI_YAXIS:
  801. //if ( newEvent.fValue < -0.01f || newEvent.fValue > 0.01f )
  802. //Input::log( "EVENT (DInput): %s Y-axis move %.2f.\n", mName, newEvent.fValue );
  803. //break;
  804. //case SI_ZAXIS:
  805. //Input::log( "EVENT (DInput): %s Z-axis move %.1f.\n", mName, newEvent.fValue );
  806. //break;
  807. //case SI_RXAXIS:
  808. //Input::log( "EVENT (DInput): %s R-axis move %.1f.\n", mName, newEvent.fValue );
  809. //break;
  810. //case SI_RYAXIS:
  811. //Input::log( "EVENT (DInput): %s U-axis move %.1f.\n", mName, newEvent.fValue );
  812. //break;
  813. //case SI_RZAXIS:
  814. //Input::log( "EVENT (DInput): %s V-axis move %.1f.\n", mName, newEvent.fValue );
  815. //break;
  816. //case SI_SLIDER:
  817. //Input::log( "EVENT (DInput): %s slider move %.1f.\n", mName, newEvent.fValue );
  818. //break;
  819. //};
  820. #endif
  821. }
  822. newEvent.postToSignal(Input::smInputEvent);
  823. break;
  824. case SI_BUTTON:
  825. newEvent.action = ( newData & 0x80 ) ? SI_MAKE : SI_BREAK;
  826. newEvent.fValue = ( newEvent.action == SI_MAKE ) ? 1.0f : 0.0f;
  827. #ifdef LOG_INPUT
  828. if ( newEvent.action == SI_MAKE )
  829. Input::log( "EVENT (DInput): %s button%d pressed.\n", mName, newEvent.objInst - KEY_BUTTON0 );
  830. else
  831. Input::log( "EVENT (DInput): %s button%d released.\n", mName, newEvent.objInst - KEY_BUTTON0 );
  832. #endif
  833. newEvent.postToSignal(Input::smInputEvent);
  834. break;
  835. case SI_POV:
  836. // Handle artificial POV up/down/left/right buttons
  837. // If we're not a polling device, oldData and newData are the same, so "fake" transitions
  838. if(!isPolled()) {
  839. oldData = mPrevPOVPos;
  840. mPrevPOVPos = newData;
  841. }
  842. newData = LOWORD( newData );
  843. oldData = LOWORD( oldData );
  844. newData = _Win32GetPOVDirs(newData);
  845. oldData = _Win32GetPOVDirs(oldData);
  846. U32 setkeys = newData & (~oldData);
  847. U32 clearkeys = oldData & (~newData);
  848. U32 objInst = newEvent.objInst;
  849. if ( setkeys || clearkeys )
  850. {
  851. if ( clearkeys )
  852. {
  853. newEvent.action = SI_BREAK;
  854. newEvent.fValue = 0.0f;
  855. // post events for all buttons that need to be cleared.
  856. if( clearkeys & POV_up)
  857. {
  858. newEvent.objInst = ( objInst == 0 ) ? SI_UPOV : SI_UPOV2;
  859. _Win32LogPOVInput(newEvent);
  860. newEvent.postToSignal(Input::smInputEvent);
  861. }
  862. if( clearkeys & POV_right)
  863. {
  864. newEvent.objInst = ( objInst == 0 ) ? SI_RPOV : SI_RPOV2;
  865. _Win32LogPOVInput(newEvent);
  866. newEvent.postToSignal(Input::smInputEvent);
  867. }
  868. if( clearkeys & POV_down)
  869. {
  870. newEvent.objInst = ( objInst == 0 ) ? SI_DPOV : SI_DPOV2;
  871. _Win32LogPOVInput(newEvent);
  872. newEvent.postToSignal(Input::smInputEvent);
  873. }
  874. if( clearkeys & POV_left)
  875. {
  876. newEvent.objInst = ( objInst == 0 ) ? SI_LPOV : SI_LPOV2;
  877. _Win32LogPOVInput(newEvent);
  878. newEvent.postToSignal(Input::smInputEvent);
  879. }
  880. } // clear keys
  881. if ( setkeys )
  882. {
  883. newEvent.action = SI_MAKE;
  884. newEvent.fValue = 1.0f;
  885. // post events for all buttons that need to be set.
  886. if( setkeys & POV_up)
  887. {
  888. newEvent.objInst = ( objInst == 0 ) ? SI_UPOV : SI_UPOV2;
  889. _Win32LogPOVInput(newEvent);
  890. newEvent.postToSignal(Input::smInputEvent);
  891. }
  892. if( setkeys & POV_right)
  893. {
  894. newEvent.objInst = ( objInst == 0 ) ? SI_RPOV : SI_RPOV2;
  895. _Win32LogPOVInput(newEvent);
  896. newEvent.postToSignal(Input::smInputEvent);
  897. }
  898. if( setkeys & POV_down)
  899. {
  900. newEvent.objInst = ( objInst == 0 ) ? SI_DPOV : SI_DPOV2;
  901. _Win32LogPOVInput(newEvent);
  902. newEvent.postToSignal(Input::smInputEvent);
  903. }
  904. if( setkeys & POV_left)
  905. {
  906. newEvent.objInst = ( objInst == 0 ) ? SI_LPOV : SI_LPOV2;
  907. _Win32LogPOVInput(newEvent);
  908. newEvent.postToSignal(Input::smInputEvent);
  909. }
  910. } // set keys
  911. }
  912. break;
  913. }
  914. return true;
  915. }
  916. void DInputDevice::rumble(F32 x, F32 y)
  917. {
  918. LONG rglDirection[2] = { 0, 0 };
  919. DICONSTANTFORCE cf = { 0 };
  920. HRESULT result;
  921. // Now set the new parameters and start the effect immediately.
  922. if (!mForceFeedbackEffect)
  923. {
  924. #ifdef LOG_INPUT
  925. Input::log("DInputDevice::rumbleJoystick - creating constant force feeback effect\n");
  926. #endif
  927. DIEFFECT eff;
  928. ZeroMemory( &eff, sizeof(eff) );
  929. eff.dwSize = sizeof(DIEFFECT);
  930. eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
  931. eff.dwDuration = INFINITE;
  932. eff.dwSamplePeriod = 0;
  933. eff.dwGain = DI_FFNOMINALMAX;
  934. eff.dwTriggerButton = DIEB_NOTRIGGER;
  935. eff.dwTriggerRepeatInterval = 0;
  936. eff.cAxes = mNumForceFeedbackAxes;
  937. eff.rgdwAxes = mForceFeedbackAxes;
  938. eff.rglDirection = rglDirection;
  939. eff.lpEnvelope = 0;
  940. eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
  941. eff.lpvTypeSpecificParams = &cf;
  942. eff.dwStartDelay = 0;
  943. // Create the prepared effect
  944. if ( FAILED( result = mDevice->CreateEffect( GUID_ConstantForce, &eff, &mForceFeedbackEffect, NULL ) ) )
  945. {
  946. #ifdef LOG_INPUT
  947. Input::log( "DInputDevice::rumbleJoystick - %s does not support force feedback.\n", mName );
  948. #endif
  949. Con::errorf( "DInputDevice::rumbleJoystick - %s does not support force feedback.\n", mName );
  950. return;
  951. }
  952. else
  953. {
  954. #ifdef LOG_INPUT
  955. Input::log( "DInputDevice::rumbleJoystick - %s supports force feedback.\n", mName );
  956. #endif
  957. Con::printf( "DInputDevice::rumbleJoystick - %s supports force feedback.\n", mName );
  958. }
  959. }
  960. // Clamp the input floats to [0 - 1]
  961. x = max(0, min(1, x));
  962. y = max(0, min(1, y));
  963. if ( 1 == mNumForceFeedbackAxes )
  964. {
  965. cf.lMagnitude = (DWORD)( x * DI_FFNOMINALMAX );
  966. }
  967. else
  968. {
  969. rglDirection[0] = (DWORD)( x * DI_FFNOMINALMAX );
  970. rglDirection[1] = (DWORD)( y * DI_FFNOMINALMAX );
  971. cf.lMagnitude = (DWORD)sqrt( (double)(x * x * DI_FFNOMINALMAX * DI_FFNOMINALMAX + y * y * DI_FFNOMINALMAX * DI_FFNOMINALMAX) );
  972. }
  973. DIEFFECT eff;
  974. ZeroMemory( &eff, sizeof(eff) );
  975. eff.dwSize = sizeof(DIEFFECT);
  976. eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
  977. eff.dwDuration = INFINITE;
  978. eff.dwSamplePeriod = 0;
  979. eff.dwGain = DI_FFNOMINALMAX;
  980. eff.dwTriggerButton = DIEB_NOTRIGGER;
  981. eff.dwTriggerRepeatInterval = 0;
  982. eff.cAxes = mNumForceFeedbackAxes;
  983. eff.rglDirection = rglDirection;
  984. eff.lpEnvelope = 0;
  985. eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
  986. eff.lpvTypeSpecificParams = &cf;
  987. eff.dwStartDelay = 0;
  988. if ( FAILED( result = mForceFeedbackEffect->SetParameters( &eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START ) ) )
  989. {
  990. const char* errorString = NULL;
  991. switch ( result )
  992. {
  993. case DIERR_INPUTLOST:
  994. errorString = "DIERR_INPUTLOST";
  995. break;
  996. case DIERR_INVALIDPARAM:
  997. errorString = "DIERR_INVALIDPARAM";
  998. break;
  999. case DIERR_NOTACQUIRED:
  1000. errorString = "DIERR_NOTACQUIRED";
  1001. break;
  1002. default:
  1003. errorString = "Unknown Error";
  1004. }
  1005. #ifdef LOG_INPUT
  1006. Input::log( "DInputDevice::rumbleJoystick - %s - Failed to start rumble effect\n", errorString );
  1007. #endif
  1008. Con::errorf( "DInputDevice::rumbleJoystick - %s - Failed to start rumble effect\n", errorString );
  1009. }
  1010. }
  1011. //------------------------------------------------------------------------------
  1012. //
  1013. // This function translates the DirectInput scan code to the associated
  1014. // internal key code (as defined in event.h).
  1015. //
  1016. //------------------------------------------------------------------------------
  1017. InputObjectInstances DIK_to_Key( U8 dikCode )
  1018. {
  1019. switch ( dikCode )
  1020. {
  1021. case DIK_ESCAPE: return KEY_ESCAPE;
  1022. case DIK_1: return KEY_1;
  1023. case DIK_2: return KEY_2;
  1024. case DIK_3: return KEY_3;
  1025. case DIK_4: return KEY_4;
  1026. case DIK_5: return KEY_5;
  1027. case DIK_6: return KEY_6;
  1028. case DIK_7: return KEY_7;
  1029. case DIK_8: return KEY_8;
  1030. case DIK_9: return KEY_9;
  1031. case DIK_0: return KEY_0;
  1032. case DIK_MINUS: return KEY_MINUS;
  1033. case DIK_EQUALS: return KEY_EQUALS;
  1034. case DIK_BACK: return KEY_BACKSPACE;
  1035. case DIK_TAB: return KEY_TAB;
  1036. case DIK_Q: return KEY_Q;
  1037. case DIK_W: return KEY_W;
  1038. case DIK_E: return KEY_E;
  1039. case DIK_R: return KEY_R;
  1040. case DIK_T: return KEY_T;
  1041. case DIK_Y: return KEY_Y;
  1042. case DIK_U: return KEY_U;
  1043. case DIK_I: return KEY_I;
  1044. case DIK_O: return KEY_O;
  1045. case DIK_P: return KEY_P;
  1046. case DIK_LBRACKET: return KEY_LBRACKET;
  1047. case DIK_RBRACKET: return KEY_RBRACKET;
  1048. case DIK_RETURN: return KEY_RETURN;
  1049. case DIK_LCONTROL: return KEY_LCONTROL;
  1050. case DIK_A: return KEY_A;
  1051. case DIK_S: return KEY_S;
  1052. case DIK_D: return KEY_D;
  1053. case DIK_F: return KEY_F;
  1054. case DIK_G: return KEY_G;
  1055. case DIK_H: return KEY_H;
  1056. case DIK_J: return KEY_J;
  1057. case DIK_K: return KEY_K;
  1058. case DIK_L: return KEY_L;
  1059. case DIK_SEMICOLON: return KEY_SEMICOLON;
  1060. case DIK_APOSTROPHE: return KEY_APOSTROPHE;
  1061. case DIK_GRAVE: return KEY_TILDE;
  1062. case DIK_LSHIFT: return KEY_LSHIFT;
  1063. case DIK_BACKSLASH: return KEY_BACKSLASH;
  1064. case DIK_Z: return KEY_Z;
  1065. case DIK_X: return KEY_X;
  1066. case DIK_C: return KEY_C;
  1067. case DIK_V: return KEY_V;
  1068. case DIK_B: return KEY_B;
  1069. case DIK_N: return KEY_N;
  1070. case DIK_M: return KEY_M;
  1071. case DIK_COMMA: return KEY_COMMA;
  1072. case DIK_PERIOD: return KEY_PERIOD;
  1073. case DIK_SLASH: return KEY_SLASH;
  1074. case DIK_RSHIFT: return KEY_RSHIFT;
  1075. case DIK_MULTIPLY: return KEY_MULTIPLY;
  1076. case DIK_LALT: return KEY_LALT;
  1077. case DIK_SPACE: return KEY_SPACE;
  1078. case DIK_CAPSLOCK: return KEY_CAPSLOCK;
  1079. case DIK_F1: return KEY_F1;
  1080. case DIK_F2: return KEY_F2;
  1081. case DIK_F3: return KEY_F3;
  1082. case DIK_F4: return KEY_F4;
  1083. case DIK_F5: return KEY_F5;
  1084. case DIK_F6: return KEY_F6;
  1085. case DIK_F7: return KEY_F7;
  1086. case DIK_F8: return KEY_F8;
  1087. case DIK_F9: return KEY_F9;
  1088. case DIK_F10: return KEY_F10;
  1089. case DIK_NUMLOCK: return KEY_NUMLOCK;
  1090. case DIK_SCROLL: return KEY_SCROLLLOCK;
  1091. case DIK_NUMPAD7: return KEY_NUMPAD7;
  1092. case DIK_NUMPAD8: return KEY_NUMPAD8;
  1093. case DIK_NUMPAD9: return KEY_NUMPAD9;
  1094. case DIK_SUBTRACT: return KEY_SUBTRACT;
  1095. case DIK_NUMPAD4: return KEY_NUMPAD4;
  1096. case DIK_NUMPAD5: return KEY_NUMPAD5;
  1097. case DIK_NUMPAD6: return KEY_NUMPAD6;
  1098. case DIK_ADD: return KEY_ADD;
  1099. case DIK_NUMPAD1: return KEY_NUMPAD1;
  1100. case DIK_NUMPAD2: return KEY_NUMPAD2;
  1101. case DIK_NUMPAD3: return KEY_NUMPAD3;
  1102. case DIK_NUMPAD0: return KEY_NUMPAD0;
  1103. case DIK_DECIMAL: return KEY_DECIMAL;
  1104. case DIK_F11: return KEY_F11;
  1105. case DIK_F12: return KEY_F12;
  1106. case DIK_F13: return KEY_F13;
  1107. case DIK_F14: return KEY_F14;
  1108. case DIK_F15: return KEY_F15;
  1109. case DIK_KANA: return KEY_NULL;
  1110. case DIK_CONVERT: return KEY_NULL;
  1111. case DIK_NOCONVERT: return KEY_NULL;
  1112. case DIK_YEN: return KEY_NULL;
  1113. case DIK_NUMPADEQUALS: return KEY_NULL;
  1114. case DIK_CIRCUMFLEX: return KEY_NULL;
  1115. case DIK_AT: return KEY_NULL;
  1116. case DIK_COLON: return KEY_NULL;
  1117. case DIK_UNDERLINE: return KEY_NULL;
  1118. case DIK_KANJI: return KEY_NULL;
  1119. case DIK_STOP: return KEY_NULL;
  1120. case DIK_AX: return KEY_NULL;
  1121. case DIK_UNLABELED: return KEY_NULL;
  1122. case DIK_NUMPADENTER: return KEY_NUMPADENTER;
  1123. case DIK_RCONTROL: return KEY_RCONTROL;
  1124. case DIK_NUMPADCOMMA: return KEY_SEPARATOR;
  1125. case DIK_DIVIDE: return KEY_DIVIDE;
  1126. case DIK_SYSRQ: return KEY_PRINT;
  1127. case DIK_RALT: return KEY_RALT;
  1128. case DIK_PAUSE: return KEY_PAUSE;
  1129. case DIK_HOME: return KEY_HOME;
  1130. case DIK_UP: return KEY_UP;
  1131. case DIK_PGUP: return KEY_PAGE_UP;
  1132. case DIK_LEFT: return KEY_LEFT;
  1133. case DIK_RIGHT: return KEY_RIGHT;
  1134. case DIK_END: return KEY_END;
  1135. case DIK_DOWN: return KEY_DOWN;
  1136. case DIK_PGDN: return KEY_PAGE_DOWN;
  1137. case DIK_INSERT: return KEY_INSERT;
  1138. case DIK_DELETE: return KEY_DELETE;
  1139. case DIK_LWIN: return KEY_WIN_LWINDOW;
  1140. case DIK_RWIN: return KEY_WIN_RWINDOW;
  1141. case DIK_APPS: return KEY_WIN_APPS;
  1142. case DIK_OEM_102: return KEY_OEM_102;
  1143. }
  1144. return KEY_NULL;
  1145. }
  1146. //------------------------------------------------------------------------------
  1147. //
  1148. // This function translates an internal key code to the associated
  1149. // DirectInput scan code
  1150. //
  1151. //------------------------------------------------------------------------------
  1152. U8 Key_to_DIK( U16 keyCode )
  1153. {
  1154. switch ( keyCode )
  1155. {
  1156. case KEY_BACKSPACE: return DIK_BACK;
  1157. case KEY_TAB: return DIK_TAB;
  1158. case KEY_RETURN: return DIK_RETURN;
  1159. //KEY_CONTROL:
  1160. //KEY_ALT:
  1161. //KEY_SHIFT:
  1162. case KEY_PAUSE: return DIK_PAUSE;
  1163. case KEY_CAPSLOCK: return DIK_CAPSLOCK;
  1164. case KEY_ESCAPE: return DIK_ESCAPE;
  1165. case KEY_SPACE: return DIK_SPACE;
  1166. case KEY_PAGE_DOWN: return DIK_PGDN;
  1167. case KEY_PAGE_UP: return DIK_PGUP;
  1168. case KEY_END: return DIK_END;
  1169. case KEY_HOME: return DIK_HOME;
  1170. case KEY_LEFT: return DIK_LEFT;
  1171. case KEY_UP: return DIK_UP;
  1172. case KEY_RIGHT: return DIK_RIGHT;
  1173. case KEY_DOWN: return DIK_DOWN;
  1174. case KEY_PRINT: return DIK_SYSRQ;
  1175. case KEY_INSERT: return DIK_INSERT;
  1176. case KEY_DELETE: return DIK_DELETE;
  1177. case KEY_HELP: return 0;
  1178. case KEY_0: return DIK_0;
  1179. case KEY_1: return DIK_1;
  1180. case KEY_2: return DIK_2;
  1181. case KEY_3: return DIK_3;
  1182. case KEY_4: return DIK_4;
  1183. case KEY_5: return DIK_5;
  1184. case KEY_6: return DIK_6;
  1185. case KEY_7: return DIK_7;
  1186. case KEY_8: return DIK_8;
  1187. case KEY_9: return DIK_9;
  1188. case KEY_A: return DIK_A;
  1189. case KEY_B: return DIK_B;
  1190. case KEY_C: return DIK_C;
  1191. case KEY_D: return DIK_D;
  1192. case KEY_E: return DIK_E;
  1193. case KEY_F: return DIK_F;
  1194. case KEY_G: return DIK_G;
  1195. case KEY_H: return DIK_H;
  1196. case KEY_I: return DIK_I;
  1197. case KEY_J: return DIK_J;
  1198. case KEY_K: return DIK_K;
  1199. case KEY_L: return DIK_L;
  1200. case KEY_M: return DIK_M;
  1201. case KEY_N: return DIK_N;
  1202. case KEY_O: return DIK_O;
  1203. case KEY_P: return DIK_P;
  1204. case KEY_Q: return DIK_Q;
  1205. case KEY_R: return DIK_R;
  1206. case KEY_S: return DIK_S;
  1207. case KEY_T: return DIK_T;
  1208. case KEY_U: return DIK_U;
  1209. case KEY_V: return DIK_V;
  1210. case KEY_W: return DIK_W;
  1211. case KEY_X: return DIK_X;
  1212. case KEY_Y: return DIK_Y;
  1213. case KEY_Z: return DIK_Z;
  1214. case KEY_TILDE: return DIK_GRAVE;
  1215. case KEY_MINUS: return DIK_MINUS;
  1216. case KEY_EQUALS: return DIK_EQUALS;
  1217. case KEY_LBRACKET: return DIK_LBRACKET;
  1218. case KEY_RBRACKET: return DIK_RBRACKET;
  1219. case KEY_BACKSLASH: return DIK_BACKSLASH;
  1220. case KEY_SEMICOLON: return DIK_SEMICOLON;
  1221. case KEY_APOSTROPHE: return DIK_APOSTROPHE;
  1222. case KEY_COMMA: return DIK_COMMA;
  1223. case KEY_PERIOD: return DIK_PERIOD;
  1224. case KEY_SLASH: return DIK_SLASH;
  1225. case KEY_NUMPAD0: return DIK_NUMPAD0;
  1226. case KEY_NUMPAD1: return DIK_NUMPAD1;
  1227. case KEY_NUMPAD2: return DIK_NUMPAD2;
  1228. case KEY_NUMPAD3: return DIK_NUMPAD3;
  1229. case KEY_NUMPAD4: return DIK_NUMPAD4;
  1230. case KEY_NUMPAD5: return DIK_NUMPAD5;
  1231. case KEY_NUMPAD6: return DIK_NUMPAD6;
  1232. case KEY_NUMPAD7: return DIK_NUMPAD7;
  1233. case KEY_NUMPAD8: return DIK_NUMPAD8;
  1234. case KEY_NUMPAD9: return DIK_NUMPAD9;
  1235. case KEY_MULTIPLY: return DIK_MULTIPLY;
  1236. case KEY_ADD: return DIK_ADD;
  1237. case KEY_SEPARATOR: return DIK_NUMPADCOMMA;
  1238. case KEY_SUBTRACT: return DIK_SUBTRACT;
  1239. case KEY_DECIMAL: return DIK_DECIMAL;
  1240. case KEY_DIVIDE: return DIK_DIVIDE;
  1241. case KEY_NUMPADENTER: return DIK_NUMPADENTER;
  1242. case KEY_F1: return DIK_F1;
  1243. case KEY_F2: return DIK_F2;
  1244. case KEY_F3: return DIK_F3;
  1245. case KEY_F4: return DIK_F4;
  1246. case KEY_F5: return DIK_F5;
  1247. case KEY_F6: return DIK_F6;
  1248. case KEY_F7: return DIK_F7;
  1249. case KEY_F8: return DIK_F8;
  1250. case KEY_F9: return DIK_F9;
  1251. case KEY_F10: return DIK_F10;
  1252. case KEY_F11: return DIK_F11;
  1253. case KEY_F12: return DIK_F12;
  1254. case KEY_F13: return DIK_F13;
  1255. case KEY_F14: return DIK_F14;
  1256. case KEY_F15: return DIK_F15;
  1257. case KEY_F16:
  1258. case KEY_F17:
  1259. case KEY_F18:
  1260. case KEY_F19:
  1261. case KEY_F20:
  1262. case KEY_F21:
  1263. case KEY_F22:
  1264. case KEY_F23:
  1265. case KEY_F24: return 0;
  1266. case KEY_NUMLOCK: return DIK_NUMLOCK;
  1267. case KEY_SCROLLLOCK: return DIK_SCROLL;
  1268. case KEY_LCONTROL: return DIK_LCONTROL;
  1269. case KEY_RCONTROL: return DIK_RCONTROL;
  1270. case KEY_LALT: return DIK_LALT;
  1271. case KEY_RALT: return DIK_RALT;
  1272. case KEY_LSHIFT: return DIK_LSHIFT;
  1273. case KEY_RSHIFT: return DIK_RSHIFT;
  1274. case KEY_WIN_LWINDOW: return DIK_LWIN;
  1275. case KEY_WIN_RWINDOW: return DIK_RWIN;
  1276. case KEY_WIN_APPS: return DIK_APPS;
  1277. case KEY_OEM_102: return DIK_OEM_102;
  1278. };
  1279. return 0;
  1280. }
  1281. #ifdef LOG_INPUT
  1282. //------------------------------------------------------------------------------
  1283. const char* getKeyName( U16 key )
  1284. {
  1285. switch ( key )
  1286. {
  1287. case KEY_BACKSPACE: return "Backspace";
  1288. case KEY_TAB: return "Tab";
  1289. case KEY_RETURN: return "Return";
  1290. case KEY_PAUSE: return "Pause";
  1291. case KEY_CAPSLOCK: return "CapsLock";
  1292. case KEY_ESCAPE: return "Esc";
  1293. case KEY_SPACE: return "SpaceBar";
  1294. case KEY_PAGE_DOWN: return "PageDown";
  1295. case KEY_PAGE_UP: return "PageUp";
  1296. case KEY_END: return "End";
  1297. case KEY_HOME: return "Home";
  1298. case KEY_LEFT: return "Left";
  1299. case KEY_UP: return "Up";
  1300. case KEY_RIGHT: return "Right";
  1301. case KEY_DOWN: return "Down";
  1302. case KEY_PRINT: return "PrintScreen";
  1303. case KEY_INSERT: return "Insert";
  1304. case KEY_DELETE: return "Delete";
  1305. case KEY_HELP: return "Help";
  1306. case KEY_NUMPAD0: return "Numpad 0";
  1307. case KEY_NUMPAD1: return "Numpad 1";
  1308. case KEY_NUMPAD2: return "Numpad 2";
  1309. case KEY_NUMPAD3: return "Numpad 3";
  1310. case KEY_NUMPAD4: return "Numpad 4";
  1311. case KEY_NUMPAD5: return "Numpad 5";
  1312. case KEY_NUMPAD6: return "Numpad 6";
  1313. case KEY_NUMPAD7: return "Numpad 7";
  1314. case KEY_NUMPAD8: return "Numpad 8";
  1315. case KEY_NUMPAD9: return "Numpad 9";
  1316. case KEY_MULTIPLY: return "Multiply";
  1317. case KEY_ADD: return "Add";
  1318. case KEY_SEPARATOR: return "Separator";
  1319. case KEY_SUBTRACT: return "Subtract";
  1320. case KEY_DECIMAL: return "Decimal";
  1321. case KEY_DIVIDE: return "Divide";
  1322. case KEY_NUMPADENTER: return "Numpad Enter";
  1323. case KEY_F1: return "F1";
  1324. case KEY_F2: return "F2";
  1325. case KEY_F3: return "F3";
  1326. case KEY_F4: return "F4";
  1327. case KEY_F5: return "F5";
  1328. case KEY_F6: return "F6";
  1329. case KEY_F7: return "F7";
  1330. case KEY_F8: return "F8";
  1331. case KEY_F9: return "F9";
  1332. case KEY_F10: return "F10";
  1333. case KEY_F11: return "F11";
  1334. case KEY_F12: return "F12";
  1335. case KEY_F13: return "F13";
  1336. case KEY_F14: return "F14";
  1337. case KEY_F15: return "F15";
  1338. case KEY_F16: return "F16";
  1339. case KEY_F17: return "F17";
  1340. case KEY_F18: return "F18";
  1341. case KEY_F19: return "F19";
  1342. case KEY_F20: return "F20";
  1343. case KEY_F21: return "F21";
  1344. case KEY_F22: return "F22";
  1345. case KEY_F23: return "F23";
  1346. case KEY_F24: return "F24";
  1347. case KEY_NUMLOCK: return "NumLock";
  1348. case KEY_SCROLLLOCK: return "ScrollLock";
  1349. case KEY_LCONTROL: return "LCtrl";
  1350. case KEY_RCONTROL: return "RCtrl";
  1351. case KEY_LALT: return "LAlt";
  1352. case KEY_RALT: return "RAlt";
  1353. case KEY_LSHIFT: return "LShift";
  1354. case KEY_RSHIFT: return "RShift";
  1355. case KEY_WIN_LWINDOW: return "LWin";
  1356. case KEY_WIN_RWINDOW: return "RWin";
  1357. case KEY_WIN_APPS: return "Apps";
  1358. }
  1359. static char returnString[5];
  1360. dSprintf( returnString, sizeof( returnString ), "%c", Input::getAscii( key, STATE_UPPER ) );
  1361. return returnString;
  1362. }
  1363. #endif // LOG_INPUT
  1364. //------------------------------------------------------------------------------
  1365. const char* DInputDevice::getJoystickAxesString()
  1366. {
  1367. if ( mDeviceType != JoystickDeviceType )
  1368. return( "" );
  1369. U32 axisCount = mDeviceCaps.dwAxes;
  1370. char buf[64];
  1371. dSprintf( buf, sizeof( buf ), "%d", axisCount );
  1372. for ( U32 i = 0; i < mObjCount; i++ )
  1373. {
  1374. switch ( mObjInfo[i].mInst )
  1375. {
  1376. case SI_XAXIS:
  1377. dStrcat( buf, "\tX", 64 );
  1378. break;
  1379. case SI_YAXIS:
  1380. dStrcat( buf, "\tY", 64 );
  1381. break;
  1382. case SI_ZAXIS:
  1383. dStrcat( buf, "\tZ", 64 );
  1384. break;
  1385. case SI_RXAXIS:
  1386. dStrcat( buf, "\tR", 64 );
  1387. break;
  1388. case SI_RYAXIS:
  1389. dStrcat( buf, "\tU", 64 );
  1390. break;
  1391. case SI_RZAXIS:
  1392. dStrcat( buf, "\tV", 64 );
  1393. break;
  1394. case SI_SLIDER:
  1395. dStrcat( buf, "\tS", 64 );
  1396. break;
  1397. }
  1398. }
  1399. dsize_t returnLen = dStrlen(buf) + 1;
  1400. char* returnString = Con::getReturnBuffer(returnLen);
  1401. dStrcpy( returnString, buf, returnLen );
  1402. return( returnString );
  1403. }
  1404. //------------------------------------------------------------------------------
  1405. bool DInputDevice::joystickDetected()
  1406. {
  1407. return( smDeviceCount[ JoystickDeviceType ] > 0 );
  1408. }