winDInputDevice.cpp 53 KB

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