directinput.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** Confidential - Westwood Studios ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Commando *
  23. * *
  24. * $Archive:: /Commando/Code/Combat/directinput.cpp $*
  25. * *
  26. * $Author:: Patrick $*
  27. * *
  28. * $Modtime:: 1/15/02 5:32p $*
  29. * *
  30. * $Revision:: 25 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "directinput.h"
  36. #include "win.h"
  37. #include "debug.h"
  38. #include "timemgr.h"
  39. #define DIRECTINPUT_VERSION 0x0800
  40. #include <dinput.h>
  41. /*
  42. **
  43. */
  44. LPDIRECTINPUT DIObject = NULL;
  45. LPDIRECTINPUTDEVICE DIKeyboardDevice = NULL;
  46. LPDIRECTINPUTDEVICE DIMouseDevice = NULL;
  47. LPDIRECTINPUTDEVICE2 DIJoystickDevice = NULL;
  48. DIJOYSTATE DIJoystickState;
  49. int PASCAL InitJoystick(LPCDIDEVICEINSTANCE pdinst, LPVOID pvRef);
  50. char DirectInput::DIKeyboardButtons[NUM_KEYBOARD_BUTTONS];
  51. char DirectInput::DIMouseButtons[NUM_MOUSE_BUTTONS];
  52. long DirectInput::DIMouseAxis[NUM_MOUSE_AXIS];
  53. char DirectInput::DIJoystickButtons[NUM_MOUSE_BUTTONS];
  54. float DirectInput::ButtonLastHitTime[NUM_KEYBOARD_BUTTONS];
  55. Vector3 DirectInput::CursorPos (0, 0, 0);
  56. bool DirectInput::EatMouseHeld = false;
  57. bool DirectInput::Captured = false;
  58. void * DirectInput::DirectInputLibrary = NULL;
  59. int DirectInput::LastKeyPressed = 0;
  60. // Temp State Table (only for joystick currently)
  61. char Button_State_Table[4] = { 0,
  62. DirectInput::DI_BUTTON_HIT | DirectInput::DI_BUTTON_HELD,
  63. DirectInput::DI_BUTTON_RELEASED,
  64. DirectInput::DI_BUTTON_HELD };
  65. // Buffered input
  66. #define DI_KEYBOARD_BUFFER_SIZE 20
  67. #define DI_MOUSE_BUFFER_SIZE 20
  68. int PASCAL DirectInputInitJoystick(LPCDIDEVICEINSTANCE pdinst, LPVOID pvRef);
  69. #define MINIMUM_DIRECTINPUT_VERSION 0x300
  70. // Button bits
  71. #define BUTTON_BIT_DOUBLE 8
  72. #define BUTTON_DOUBLE_THRESHHOLD 0.25f
  73. typedef HRESULT (WINAPI *DirectInput8CreateType) (HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID* ppvOut, LPUNKNOWN punkOuter);
  74. DirectInput8CreateType DirectInput8CreatePtr = NULL;
  75. /*
  76. **
  77. */
  78. void DirectInput::Init( void )
  79. {
  80. WWDEBUG_SAY(("DirectInput: Init\n"));
  81. HRESULT hr;
  82. WWASSERT(DirectInputLibrary == NULL);
  83. DirectInputLibrary = LoadLibrary("DINPUT8.DLL");
  84. if (DirectInputLibrary != NULL) {
  85. DirectInput8CreatePtr = (DirectInput8CreateType) GetProcAddress((HINSTANCE)DirectInputLibrary, "DirectInput8Create");
  86. if (DirectInput8CreatePtr) {
  87. // Create the DirectInput Object
  88. hr = DirectInput8CreatePtr( ProgramInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&DIObject, NULL);
  89. if FAILED(hr)
  90. {
  91. Debug_Say(( "DirectInput %x not available, trying version %x\n", DIRECTINPUT_VERSION/0x100, MINIMUM_DIRECTINPUT_VERSION/0x100 ));
  92. hr = DirectInput8CreatePtr( ProgramInstance, MINIMUM_DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&DIObject, NULL);
  93. if FAILED(hr)
  94. {
  95. Debug_Say(( "DirectInput %x not available\n", MINIMUM_DIRECTINPUT_VERSION ));
  96. FreeLibrary((HINSTANCE)DirectInputLibrary);
  97. DirectInputLibrary = NULL;
  98. return;
  99. }
  100. }
  101. }
  102. }
  103. // Debug_Say(( "DirectInput object Created\n" ));
  104. // Create the Keyboard Object
  105. hr = DIObject->CreateDevice( GUID_SysKeyboard , &DIKeyboardDevice, NULL);
  106. WWASSERT( !FAILED(hr) );
  107. if ( DIKeyboardDevice != NULL ) {
  108. // Set the keyboard's data format
  109. hr = DIKeyboardDevice->SetDataFormat(&c_dfDIKeyboard);
  110. WWASSERT( !FAILED(hr) );
  111. // Set the keyboard's cooperative level
  112. // First we try for "exclusive" access (mainly so debugging works well) if that fails
  113. // then we'll take non-exclusive access.
  114. #if 0
  115. hr = DIKeyboardDevice->SetCooperativeLevel( MainWindow,DISCL_FOREGROUND | DISCL_EXCLUSIVE);
  116. if (FAILED(hr)) {
  117. DIKeyboardDevice->SetCooperativeLevel( MainWindow, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
  118. }
  119. #else
  120. DIKeyboardDevice->SetCooperativeLevel( MainWindow, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
  121. #endif
  122. // Set Keyboard Buffer Size
  123. DIPROPDWORD dipdw;
  124. dipdw.diph.dwSize = sizeof(dipdw);
  125. dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
  126. dipdw.diph.dwObj = 0;
  127. dipdw.diph.dwHow = DIPH_DEVICE;
  128. dipdw.dwData = DI_KEYBOARD_BUFFER_SIZE;
  129. hr = DIKeyboardDevice->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph);
  130. WWASSERT( !FAILED(hr) );
  131. // Aquire the keyboard
  132. hr = DIKeyboardDevice->Acquire();
  133. if ( FAILED(hr) ) {
  134. Debug_Say(( "DirectInput Keyboard Failed to Aquire\n" ));
  135. if (hr == DIERR_INVALIDPARAM) WWDEBUG_SAY(("DIERR_INVALIDPARAM\n"));
  136. if (hr == DIERR_NOTINITIALIZED) WWDEBUG_SAY(("DIERR_NOTINITIALIZED\n"));
  137. if (hr == DIERR_OTHERAPPHASPRIO) WWDEBUG_SAY(("DIERR_OTHERAPPHASPRIO\n"));
  138. }
  139. // Debug_Say(( "DirectInput Keyboard Ready\n" ));
  140. }
  141. // Create the Mouse Object
  142. hr = DIObject->CreateDevice( GUID_SysMouse, &DIMouseDevice, NULL );
  143. WWASSERT( !FAILED(hr) );
  144. if ( DIMouseDevice != NULL ) {
  145. // Set the mouse's data format
  146. hr = DIMouseDevice->SetDataFormat(&c_dfDIMouse);
  147. WWASSERT( !FAILED(hr) );
  148. /**/
  149. // Set the mouse's cooperative level
  150. hr = DIMouseDevice->SetCooperativeLevel( MainWindow,
  151. DISCL_EXCLUSIVE | DISCL_FOREGROUND);
  152. WWASSERT( !FAILED(hr) );
  153. /**/
  154. // Set Mouse Buffer Size
  155. DIPROPDWORD dipdw;
  156. dipdw.diph.dwSize = sizeof(dipdw);
  157. dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
  158. dipdw.diph.dwObj = 0;
  159. dipdw.diph.dwHow = DIPH_DEVICE;
  160. dipdw.dwData = DI_MOUSE_BUFFER_SIZE;
  161. hr = DIMouseDevice->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph);
  162. WWASSERT( !FAILED(hr) );
  163. // Aquire the mouse
  164. hr = DIMouseDevice->Acquire();
  165. if ( FAILED(hr) ) {
  166. Debug_Say(( "DirectInput Mouse Failed to Aquire\n" ));
  167. if (hr == DIERR_INVALIDPARAM) WWDEBUG_SAY(("DIERR_INVALIDPARAM\n"));
  168. if (hr == DIERR_NOTINITIALIZED) WWDEBUG_SAY(("DIERR_NOTINITIALIZED\n"));
  169. if (hr == DIERR_OTHERAPPHASPRIO) WWDEBUG_SAY(("DIERR_OTHERAPPHASPRIO\n"));
  170. }
  171. // Debug_Say(( "DirectInput Mouse Ready\n" ));
  172. }
  173. // Enumerate the Joysticks
  174. DIObject->EnumDevices(DI8DEVCLASS_GAMECTRL, InitJoystick, DIObject, DIEDFL_ATTACHEDONLY );
  175. if ( DIJoystickDevice != NULL ) {
  176. // Set the joystick's data format
  177. hr = DIJoystickDevice->SetDataFormat( &c_dfDIJoystick );
  178. WWASSERT( !FAILED(hr) );
  179. // Set the joystick's cooperative level
  180. hr = DIJoystickDevice->SetCooperativeLevel( MainWindow, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
  181. WWASSERT( !FAILED(hr) );
  182. DIPROPRANGE diprg;
  183. diprg.diph.dwSize = sizeof(diprg);
  184. diprg.diph.dwHeaderSize = sizeof(diprg.diph);
  185. // Set X Range
  186. diprg.diph.dwObj = DIJOFS_X;
  187. diprg.diph.dwHow = DIPH_BYOFFSET;
  188. diprg.lMin = -1000;
  189. diprg.lMax = +1000;
  190. hr = DIJoystickDevice->SetProperty(DIPROP_RANGE, &diprg.diph);
  191. WWASSERT( !FAILED(hr) );
  192. // Set Y Range
  193. diprg.diph.dwObj = DIJOFS_Y;
  194. hr = DIJoystickDevice->SetProperty(DIPROP_RANGE, &diprg.diph);
  195. WWASSERT( !FAILED(hr) );
  196. DIPROPDWORD dipdw;
  197. dipdw.diph.dwSize = sizeof(dipdw);
  198. dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
  199. // set X axis dead zone to 20% (to avoid accidental turning)
  200. dipdw.diph.dwObj = DIJOFS_X;
  201. dipdw.diph.dwHow = DIPH_BYOFFSET;
  202. dipdw.dwData = 200;
  203. hr = DIJoystickDevice->SetProperty(DIPROP_DEADZONE, &dipdw.diph);
  204. WWASSERT( !FAILED(hr) );
  205. // set Y axis dead zone to 20% (to avoid accidental turning)
  206. dipdw.diph.dwObj = DIJOFS_Y;
  207. hr = DIJoystickDevice->SetProperty(DIPROP_DEADZONE, &dipdw.diph);
  208. WWASSERT( !FAILED(hr) );
  209. // Aquire the mouse
  210. hr = DIJoystickDevice->Acquire();
  211. if ( FAILED(hr) ) {
  212. Debug_Say(( "DirectInput Joystick Failed to Aquire\n" ));
  213. }
  214. }
  215. Captured = true;
  216. Flush();
  217. //
  218. // Reset the double-click array entries
  219. //
  220. for ( int index = 0; index < NUM_KEYBOARD_BUTTONS; index++ ) {
  221. ButtonLastHitTime[index] = 1000;
  222. }
  223. return ;
  224. }
  225. /*
  226. **
  227. */
  228. void DirectInput::Shutdown( void )
  229. {
  230. WWDEBUG_SAY(("DirectInput: Shutdown\n"));
  231. if ( DIKeyboardDevice ) {
  232. DIKeyboardDevice->Unacquire();
  233. DIKeyboardDevice->Release();
  234. DIKeyboardDevice = NULL;
  235. }
  236. if ( DIMouseDevice ) {
  237. DIMouseDevice->Unacquire();
  238. DIMouseDevice->Release();
  239. DIMouseDevice = NULL;
  240. }
  241. if ( DIJoystickDevice ) {
  242. DIJoystickDevice->Unacquire();
  243. DIJoystickDevice->Release();
  244. DIJoystickDevice = NULL;
  245. }
  246. if ( DIObject ) {
  247. DIObject->Release();
  248. DIObject = NULL;
  249. if (DirectInputLibrary) {
  250. FreeLibrary((HINSTANCE)DirectInputLibrary);
  251. }
  252. }
  253. }
  254. /*
  255. **
  256. */
  257. void DirectInput::Flush( void )
  258. {
  259. memset( DIKeyboardButtons, 0, sizeof(DIKeyboardButtons) );
  260. memset( DIMouseButtons, 0, sizeof(DIMouseButtons) );
  261. memset( DIMouseAxis, 0, sizeof(DIMouseAxis) );
  262. memset( DIJoystickButtons, 0, sizeof(DIJoystickButtons) );
  263. }
  264. /*
  265. ** Acquire access to input devices
  266. */
  267. void DirectInput::Acquire(void)
  268. {
  269. // WWDEBUG_SAY(("DirectInput: Acquire\n"));
  270. if (Captured == false) {
  271. Flush();
  272. if (DIKeyboardDevice) {
  273. DIKeyboardDevice->Acquire();
  274. }
  275. POINT cursorPos;
  276. GetCursorPos(&cursorPos);
  277. ScreenToClient(MainWindow, &cursorPos);
  278. CursorPos.X = (float)cursorPos.x;
  279. CursorPos.Y = (float)cursorPos.y;
  280. if (DIMouseDevice) {
  281. DIMouseDevice->Acquire();
  282. }
  283. Captured = true;
  284. }
  285. }
  286. /*
  287. ** Release accesss to input devices.
  288. */
  289. void DirectInput::Unacquire(void)
  290. {
  291. // WWDEBUG_SAY(("DirectInput: Unacquire\n"));
  292. if (Captured) {
  293. if (DIMouseDevice) {
  294. DIMouseDevice->Unacquire();
  295. }
  296. if (DIKeyboardDevice) {
  297. DIKeyboardDevice->Unacquire();
  298. }
  299. POINT cursorPos;
  300. cursorPos.x = (LONG)CursorPos.X;
  301. cursorPos.y = (LONG)CursorPos.Y;
  302. ClientToScreen(MainWindow, &cursorPos);
  303. SetCursorPos(cursorPos.x, cursorPos.y);
  304. Captured = false;
  305. }
  306. }
  307. /*
  308. **
  309. */
  310. int PASCAL InitJoystick(LPCDIDEVICEINSTANCE pdinst, LPVOID pvRef)
  311. {
  312. LPDIRECTINPUT pdi = (LPDIRECTINPUT)pvRef;
  313. if ( DIJoystickDevice == NULL ) {
  314. LPDIRECTINPUTDEVICE temp;
  315. HRESULT hr;
  316. hr = pdi->CreateDevice(pdinst->guidInstance, &temp, NULL);
  317. if ( !FAILED(hr)) {
  318. hr = temp->QueryInterface(IID_IDirectInputDevice2,
  319. (LPVOID *)&DIJoystickDevice);
  320. IDirectInputDevice_Release(temp);
  321. }
  322. if ( FAILED(hr) ) {
  323. Debug_Say(( "Failed to Create Joystick\n" ));
  324. } else {
  325. return DIENUM_STOP; // we got one
  326. }
  327. }
  328. return DIENUM_CONTINUE;
  329. }
  330. /*
  331. **
  332. */
  333. void DirectInput::ReadKeyboard( void )
  334. {
  335. if ( DIKeyboardDevice == NULL ) return;
  336. for (int i = 0; i < sizeof( DIKeyboardButtons ); i++ ) {
  337. DIKeyboardButtons[i] &= DI_BUTTON_HELD; // make off all but the STATE
  338. }
  339. DWORD buffer_size = 1;
  340. DIDEVICEOBJECTDATA input_buffer;
  341. bool done = false;
  342. while( !done ) {
  343. // Jani: Try to acquire first (Acquire doesn't increase ref count).
  344. HRESULT hr = DIKeyboardDevice->Acquire();
  345. if ( FAILED( hr) ) {
  346. return;
  347. }
  348. hr = DIKeyboardDevice->GetDeviceData(
  349. sizeof(DIDEVICEOBJECTDATA), &input_buffer, &buffer_size, 0 );
  350. if FAILED(hr) {
  351. if ( (hr == DIERR_INPUTLOST) || (hr == DIERR_NOTACQUIRED) ) {
  352. if (hr == DIERR_INPUTLOST) {
  353. Debug_Say(( "DirectInput keyboard lost\n" ));
  354. }
  355. // Try to re-aquire
  356. hr = DIKeyboardDevice->Acquire();
  357. if ( FAILED( hr) ) {
  358. // Debug_Say(( "DirectInput keyboard not re-aquired\n" ));
  359. return;
  360. }
  361. Debug_Say(( "DirectInput keyboard re-aquired\n" ));
  362. continue;
  363. } else {
  364. Debug_Say(( "DirectInput GetDeviceState FAILED %x\n", hr ));
  365. return;
  366. }
  367. }
  368. if ( buffer_size == 0 ) {
  369. done = true;
  370. } else {
  371. WWASSERT( !(input_buffer.dwOfs & 0x0FF00) );
  372. if ( input_buffer.dwData & 0x80 ) {
  373. DIKeyboardButtons[ input_buffer.dwOfs ] |= DI_BUTTON_HIT;
  374. DIKeyboardButtons[ input_buffer.dwOfs ] |= DI_BUTTON_HELD;
  375. LastKeyPressed = input_buffer.dwOfs;
  376. } else {
  377. DIKeyboardButtons[ input_buffer.dwOfs ] |= DI_BUTTON_RELEASED;
  378. DIKeyboardButtons[ input_buffer.dwOfs ] &= ~DI_BUTTON_HELD;
  379. }
  380. }
  381. }
  382. // Set Dupe Keys
  383. DIKeyboardButtons[ DIK_CONTROL ] = DIKeyboardButtons[ DIK_LCONTROL ] | DIKeyboardButtons[ DIK_RCONTROL ] ;
  384. DIKeyboardButtons[ DIK_SHIFT ] = DIKeyboardButtons[ DIK_LSHIFT ] | DIKeyboardButtons[ DIK_RSHIFT ] ;
  385. DIKeyboardButtons[ DIK_ALT ] = DIKeyboardButtons[ DIK_LALT ] | DIKeyboardButtons[ DIK_RALT ];
  386. DIKeyboardButtons[ DIK_WIN ] = DIKeyboardButtons[ DIK_LWIN ] | DIKeyboardButtons[ DIK_RWIN ];
  387. #if 0
  388. retry_keyboard:
  389. HRESULT hr = DIKeyboardDevice->GetDeviceState(sizeof(DIKeyboardState),(LPVOID)&DIKeyboardState);
  390. if FAILED(hr) {
  391. if ( (hr == DIERR_INPUTLOST) || (hr == DIERR_NOTACQUIRED) ) {
  392. if (hr == DIERR_INPUTLOST) {
  393. Debug_Say(( "DirectInput keyboard lost\n" ));
  394. }
  395. // Try to re-aquire
  396. hr = DIKeyboardDevice->Acquire();
  397. if ( FAILED( hr) ) {
  398. // Debug_Say(( "DirectInput keyboard not re-aquired\n" ));
  399. return;
  400. }
  401. Debug_Say(( "DirectInput keyboard re-aquired\n" ));
  402. goto retry_keyboard;
  403. } else {
  404. Debug_Say(( "DirectInput GetDeviceState FAILED %x\n", hr ));
  405. return;
  406. }
  407. }
  408. // Set Dupe Keys
  409. DIKeyboardState[ DIK_CONTROL ] = DIKeyboardState[ DIK_LCONTROL ] | DIKeyboardState[ DIK_RCONTROL ] ;
  410. DIKeyboardState[ DIK_SHIFT ] = DIKeyboardState[ DIK_LSHIFT ] | DIKeyboardState[ DIK_RSHIFT ] ;
  411. DIKeyboardState[ DIK_ALT ] = DIKeyboardState[ DIK_LALT ] | DIKeyboardState[ DIK_RALT ];
  412. DIKeyboardState[ DIK_WIN ] = DIKeyboardState[ DIK_LWIN ] | DIKeyboardState[ DIK_RWIN ];
  413. #endif
  414. }
  415. /*
  416. **
  417. */
  418. void DirectInput::ReadMouse( void )
  419. {
  420. if ( DIMouseDevice == NULL ) return;
  421. for (int i = 0; i < sizeof( DIMouseButtons ); i++ ) {
  422. DIMouseButtons[i] &= DI_BUTTON_HELD; // make off all but the STATE
  423. }
  424. for (i = 0; i < (sizeof( DIMouseAxis )/sizeof( DIMouseAxis[0] ) ); i++ ) {
  425. DIMouseAxis[i] = 0;
  426. }
  427. DWORD buffer_size = 1;
  428. DIDEVICEOBJECTDATA input_buffer;
  429. bool done = false;
  430. while( !done ) {
  431. // Try to aquire first
  432. HRESULT hr = DIMouseDevice->Acquire();
  433. if ( FAILED( hr) ) {
  434. return;
  435. }
  436. hr = DIMouseDevice->GetDeviceData(
  437. sizeof(DIDEVICEOBJECTDATA), &input_buffer, &buffer_size, 0 );
  438. if FAILED(hr) {
  439. if ( (hr == DIERR_INPUTLOST) || (hr == DIERR_NOTACQUIRED) ) {
  440. if (hr == DIERR_INPUTLOST) {
  441. Debug_Say(( "DirectInput mouse lost\n" ));
  442. }
  443. // Try to re-aquire
  444. hr = DIMouseDevice->Acquire();
  445. if ( FAILED( hr) ) {
  446. // Debug_Say(( "DirectInput mouse not re-aquired\n" ));
  447. return;
  448. }
  449. Debug_Say(( "DirectInput mouse re-aquired\n" ));
  450. continue;
  451. } else {
  452. Debug_Say(( "DirectInput mouse GetDeviceState FAILED %x\n", hr ));
  453. return;
  454. }
  455. }
  456. if ( buffer_size == 0 ) {
  457. done = true;
  458. } else {
  459. int index = 0;
  460. switch( input_buffer.dwOfs ) {
  461. case DIMOFS_Z: index++;
  462. case DIMOFS_Y: index++;
  463. case DIMOFS_X:
  464. DIMouseAxis[index] += input_buffer.dwData;
  465. CursorPos[index] += ((int)input_buffer.dwData) * 2;
  466. break;
  467. case DIMOFS_BUTTON2: index++;
  468. case DIMOFS_BUTTON1: index++;
  469. case DIMOFS_BUTTON0:
  470. if ( input_buffer.dwData & 0x80 ) {
  471. DIMouseButtons[ index ] |= DI_BUTTON_HIT;
  472. DIMouseButtons[ index ] |= DI_BUTTON_HELD;
  473. } else {
  474. DIMouseButtons[ index ] |= DI_BUTTON_RELEASED;
  475. DIMouseButtons[ index ] &= ~DI_BUTTON_HELD;
  476. EatMouseHeld = false;
  477. }
  478. break;
  479. }
  480. }
  481. }
  482. //
  483. // "Eat" the left mouse button as necessary
  484. //
  485. if ( EatMouseHeld ) {
  486. DIMouseButtons[ BUTTON_MOUSE_LEFT & 0xFF ] &= ~DI_BUTTON_HELD;
  487. DIMouseButtons[ BUTTON_MOUSE_LEFT & 0xFF ] &= ~DI_BUTTON_HIT;
  488. DIMouseButtons[ BUTTON_MOUSE_LEFT & 0xFF ] |= DI_BUTTON_RELEASED;
  489. }
  490. #if 0
  491. retry_mouse:
  492. HRESULT hr = DIMouseDevice->GetDeviceState( sizeof(DIMouseState), (LPVOID)&DIMouseState );
  493. if FAILED(hr) {
  494. if ( (hr == DIERR_INPUTLOST) || (hr == DIERR_NOTACQUIRED) ) {
  495. if (hr == DIERR_INPUTLOST) {
  496. Debug_Say(( "DirectInput mouse lost\n" ));
  497. }
  498. // Try to re-aquire
  499. hr = DIMouseDevice->Acquire();
  500. if ( FAILED( hr) ) {
  501. // Debug_Say(( "DirectInput mouse not re-aquired\n" ));
  502. return;
  503. }
  504. Debug_Say(( "DirectInput mouse re-aquired\n" ));
  505. goto retry_mouse;
  506. } else {
  507. Debug_Say(( "DirectInput GetDeviceState FAILED %x\n", hr ));
  508. return;
  509. }
  510. }
  511. DIMouseButtons[ 0 ] = Button_State_Table[ ((DIMouseButtons[ 0 ]&1) << 1) + ((DIMouseState.rgbButtons[ 0 ] & 0x80 )?1:0) ];
  512. DIMouseButtons[ 1 ] = Button_State_Table[ ((DIMouseButtons[ 1 ]&1) << 1) + ((DIMouseState.rgbButtons[ 1 ] & 0x80 )?1:0) ];
  513. DIMouseButtons[ 2 ] = Button_State_Table[ ((DIMouseButtons[ 2 ]&1) << 1) + ((DIMouseState.rgbButtons[ 2 ] & 0x80 )?1:0) ];
  514. #endif
  515. }
  516. /*
  517. **
  518. */
  519. void DirectInput::ReadJoystick( void )
  520. {
  521. if ( DIJoystickDevice == NULL ) return;
  522. // poll the joystick to read the current state
  523. retry_joystick:
  524. HRESULT hr = DIJoystickDevice->Poll();
  525. if (FAILED(hr)) {
  526. if ( (hr == DIERR_INPUTLOST) || (hr == DIERR_NOTACQUIRED) ) {
  527. if (hr == DIERR_INPUTLOST) {
  528. Debug_Say(( "DirectInput Joystick lost\n" ));
  529. }
  530. // Try to re-aquire
  531. hr = DIJoystickDevice->Acquire();
  532. if ( FAILED( hr) ) {
  533. // Debug_Say(( "DirectInput joystick not re-aquired\n" ));
  534. return;
  535. }
  536. Debug_Say(( "DirectInput Joystick re-aquired\n" ));
  537. goto retry_joystick;
  538. }
  539. }
  540. hr = DIJoystickDevice->GetDeviceState( sizeof(DIJoystickState), (LPVOID)&DIJoystickState );
  541. if FAILED(hr) {
  542. Debug_Say(( "DirectInput GetDeviceState FAILED %x\n", hr ));
  543. return;
  544. }
  545. DIJoystickButtons[ 0 ] = Button_State_Table[ ((DIJoystickButtons[ 0 ]&1) << 1) + ((DIJoystickState.rgbButtons[ 0 ] & 0x80 )?1:0) ];
  546. DIJoystickButtons[ 1 ] = Button_State_Table[ ((DIJoystickButtons[ 1 ]&1) << 1) + ((DIJoystickState.rgbButtons[ 1 ] & 0x80 )?1:0) ];
  547. }
  548. /*
  549. **
  550. */
  551. void DirectInput::Read( void )
  552. {
  553. if (Captured) {
  554. ReadKeyboard();
  555. ReadMouse();
  556. ReadJoystick();
  557. Update_Double_Clicks();
  558. }
  559. return ;
  560. }
  561. /*
  562. **
  563. */
  564. void DirectInput::Eat_Mouse_Held_States (void)
  565. {
  566. if ( (DIMouseButtons[BUTTON_MOUSE_LEFT & 0xFF] & DI_BUTTON_HELD) ||
  567. (DIMouseButtons[BUTTON_MOUSE_LEFT & 0xFF] & DI_BUTTON_HIT))
  568. {
  569. EatMouseHeld = true;
  570. }
  571. return ;
  572. }
  573. /*
  574. **
  575. */
  576. long DirectInput::Get_Joystick_Axis_State( JoystickAxis axis )
  577. {
  578. return ((long*)&DIJoystickState.lX)[axis];
  579. }
  580. /*
  581. **
  582. */
  583. void DirectInput::Update_Double_Clicks (void)
  584. {
  585. float time_delta = TimeManager::Get_Frame_Real_Seconds();
  586. for ( int index = 0; index < NUM_KEYBOARD_BUTTONS; index++ ) {
  587. //
  588. // Bump time since last
  589. //
  590. ButtonLastHitTime[index] += time_delta;
  591. //
  592. // If the button is hit, check for double and reset time
  593. //
  594. if ( DIKeyboardButtons[index] & DI_BUTTON_HIT ) {
  595. if ( ButtonLastHitTime[index] <= BUTTON_DOUBLE_THRESHHOLD ) {
  596. DIKeyboardButtons[index] |= BUTTON_BIT_DOUBLE;
  597. }
  598. ButtonLastHitTime[index] = 0;
  599. }
  600. }
  601. return ;
  602. }