- Timestamp:
- Mar 14, 2011, 3:53:38 AM (14 years ago)
- Location:
- code/branches/kicklib
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/kicklib
-
code/branches/kicklib/src/external/ois/win32/Win32JoyStick.cpp
r5781 r8071 21 21 3. This notice may not be removed or altered from any source distribution. 22 22 */ 23 #include " Win32/Win32JoyStick.h"24 #include " Win32/Win32InputManager.h"25 #include " Win32/Win32ForceFeedback.h"23 #include "win32/Win32JoyStick.h" 24 #include "win32/Win32InputManager.h" 25 #include "win32/Win32ForceFeedback.h" 26 26 #include "OISEvents.h" 27 27 #include "OISException.h" 28 28 29 29 #include <cassert> 30 #include <wbemidl.h> 31 #include <oleauto.h> 32 //#include <wmsstd.h> 33 #ifndef SAFE_RELEASE 34 #define SAFE_RELEASE(x) \ 35 if(x != NULL) \ 36 { \ 37 x->Release(); \ 38 x = NULL; \ 39 } 40 #endif 41 42 #ifdef OIS_WIN32_XINPUT_SUPPORT 43 # pragma comment(lib, "xinput.lib") 44 #endif 30 45 31 46 //DX Only defines macros for the JOYSTICK not JOYSTICK2, so fix it … … 40 55 #define DIJOFS_SLIDER3(n) (FIELD_OFFSET(DIJOYSTATE2, rglFSlider)+(n) * sizeof(LONG)) 41 56 57 #define XINPUT_TRANSLATED_BUTTON_COUNT 12 58 #define XINPUT_TRANSLATED_AXIS_COUNT 6 59 42 60 using namespace OIS; 43 61 44 62 //--------------------------------------------------------------------------------------------------// 45 Win32JoyStick::Win32JoyStick( InputManager* creator, IDirectInput8* pDI, 46 bool buffered, DWORD coopSettings, const JoyStickInfo &info ) 47 : JoyStick(info.vendor, buffered, info.devId, creator) 48 { 49 mDirectInput = pDI; 50 coopSetting = coopSettings; 51 mJoyStick = 0; 52 53 deviceGuid = info.deviceID; 54 55 ff_device = 0; 63 Win32JoyStick::Win32JoyStick( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings, const JoyStickInfo &info ) : 64 JoyStick(info.vendor, buffered, info.devId, creator), 65 mDirectInput(pDI), 66 coopSetting(coopSettings), 67 mJoyStick(0), 68 mJoyInfo(info), 69 mFfDevice(0) 70 { 56 71 } 57 72 … … 59 74 Win32JoyStick::~Win32JoyStick() 60 75 { 61 delete ff_device;76 delete mFfDevice; 62 77 63 78 if(mJoyStick) … … 69 84 70 85 //Return joystick to pool 71 JoyStickInfo js; 72 js.deviceID = deviceGuid; 73 js.devId = mDevID; 74 js.vendor = mVendor; 75 static_cast<Win32InputManager*>(mCreator)->_returnJoyStick(js); 86 static_cast<Win32InputManager*>(mCreator)->_returnJoyStick(mJoyInfo); 76 87 } 77 88 … … 79 90 void Win32JoyStick::_initialize() 80 91 { 81 //Clear old state 82 mState.mAxes.clear(); 83 84 if (ff_device) 85 { 86 delete ff_device; 87 ff_device = 0; 88 } 89 90 // Create direct input joystick device. 91 if(FAILED(mDirectInput->CreateDevice(deviceGuid, &mJoyStick, NULL))) 92 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> Could not initialize joy device!"); 93 94 // Set DIJoystick2 data format. 95 if(FAILED(mJoyStick->SetDataFormat(&c_dfDIJoystick2))) 96 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> data format error!"); 97 98 // Set cooperative level as specified when creating input manager. 99 HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle(); 100 if(FAILED(mJoyStick->SetCooperativeLevel( hwin, coopSetting))) 101 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> failed to set cooperation level!"); 102 103 // Set buffer size. 104 DIPROPDWORD dipdw; 105 dipdw.diph.dwSize = sizeof(DIPROPDWORD); 106 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); 107 dipdw.diph.dwObj = 0; 108 dipdw.diph.dwHow = DIPH_DEVICE; 109 dipdw.dwData = JOYSTICK_DX_BUFFERSIZE; 110 111 if( FAILED(mJoyStick->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)) ) 112 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize >> Failed to set buffer size property" ); 113 114 // Enumerate all axes/buttons/sliders/force feedback/etc before aquiring 115 _enumerate(); 116 117 mState.clear(); 118 119 capture(); 92 if (mJoyInfo.isXInput) 93 { 94 _enumerate(); 95 } 96 else 97 { 98 //Clear old state 99 mState.mAxes.clear(); 100 101 delete mFfDevice; 102 mFfDevice = 0; 103 104 DIPROPDWORD dipdw; 105 106 dipdw.diph.dwSize = sizeof(DIPROPDWORD); 107 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); 108 dipdw.diph.dwObj = 0; 109 dipdw.diph.dwHow = DIPH_DEVICE; 110 dipdw.dwData = JOYSTICK_DX_BUFFERSIZE; 111 112 if(FAILED(mDirectInput->CreateDevice(mJoyInfo.deviceID, &mJoyStick, NULL))) 113 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> Could not initialize joy device!"); 114 115 if(FAILED(mJoyStick->SetDataFormat(&c_dfDIJoystick2))) 116 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> data format error!"); 117 118 HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle(); 119 120 if(FAILED(mJoyStick->SetCooperativeLevel( hwin, coopSetting))) 121 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> failed to set cooperation level!"); 122 123 if( FAILED(mJoyStick->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)) ) 124 OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set buffer size property" ); 125 126 //Enumerate all axes/buttons/sliders/etc before aquiring 127 _enumerate(); 128 129 mState.clear(); 130 131 capture(); 132 } 120 133 } 121 134 … … 123 136 void Win32JoyStick::_enumerate() 124 137 { 125 // Get joystick capabilities. 126 mDIJoyCaps.dwSize = sizeof(DIDEVCAPS); 127 if( FAILED(mJoyStick->GetCapabilities(&mDIJoyCaps)) ) 128 OIS_EXCEPT( E_General, "Win32JoyStick::_enumerate >> Failed to get capabilities" ); 129 130 // => Number of POVs 131 mPOVs = (short)mDIJoyCaps.dwPOVs; 132 133 // => Number of buttons and axes. 134 mState.mButtons.resize(mDIJoyCaps.dwButtons); 135 mState.mAxes.resize(mDIJoyCaps.dwAxes); 136 137 // Enumerate all Force Feedback effects (if any) 138 mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL); 139 140 //Reset the axis mapping enumeration value 141 _AxisNumber = 0; 142 143 // Enumerate and set axis constraints (and check FF Axes) 144 mJoyStick->EnumObjects(DIEnumDeviceObjectsCallback, this, DIDFT_AXIS); 138 if (mJoyInfo.isXInput) 139 { 140 mPOVs = 1; 141 142 mState.mButtons.resize(XINPUT_TRANSLATED_BUTTON_COUNT); 143 mState.mAxes.resize(XINPUT_TRANSLATED_AXIS_COUNT); 144 } 145 else 146 { 147 // Get joystick capabilities. 148 mDIJoyCaps.dwSize = sizeof(DIDEVCAPS); 149 if( FAILED(mJoyStick->GetCapabilities(&mDIJoyCaps)) ) 150 OIS_EXCEPT( E_General, "Win32JoyStick::_enumerate >> Failed to get capabilities" ); 151 152 mPOVs = (short)mDIJoyCaps.dwPOVs; 153 154 mState.mButtons.resize(mDIJoyCaps.dwButtons); 155 mState.mAxes.resize(mDIJoyCaps.dwAxes); 156 157 //Reset the axis mapping enumeration value 158 _AxisNumber = 0; 159 160 //Enumerate Force Feedback (if any) 161 mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL); 162 163 //Enumerate and set axis constraints (and check FF Axes) 164 mJoyStick->EnumObjects(DIEnumDeviceObjectsCallback, this, DIDFT_AXIS); 165 } 145 166 } 146 167 … … 191 212 if((lpddoi->dwFlags & DIDOI_FFACTUATOR) != 0 ) 192 213 { 193 if( _this-> ff_device )214 if( _this->mFfDevice ) 194 215 { 195 _this-> ff_device->_addFFAxis();216 _this->mFfDevice->_addFFAxis(); 196 217 } 197 218 } … … 200 221 //as DInput has no API to query the device for these capabilities 201 222 //(the only way to know is to try them ...) 202 if( _this-> ff_device )203 { 204 _this-> ff_device->_setGainSupport(true);205 _this-> ff_device->_setAutoCenterSupport(true);223 if( _this->mFfDevice ) 224 { 225 _this->mFfDevice->_setGainSupport(true); 226 _this->mFfDevice->_setAutoCenterSupport(true); 206 227 } 207 228 … … 215 236 216 237 //Create the FF instance only after we know there is at least one effect type 217 if( _this-> ff_device == 0 )218 _this->ff_device = new Win32ForceFeedback(_this->mJoyStick, &_this->mDIJoyCaps);219 220 _this-> ff_device->_addEffectSupport( pdei);238 if( _this->mFfDevice == 0 ) 239 _this->mFfDevice = new Win32ForceFeedback(_this->mJoyStick, &_this->mDIJoyCaps); 240 241 _this->mFfDevice->_addEffectSupport(pdei); 221 242 222 243 return DIENUM_CONTINUE; … … 226 247 void Win32JoyStick::capture() 227 248 { 249 #ifdef OIS_WIN32_XINPUT_SUPPORT 250 //handle xbox controller differently 251 if (mJoyInfo.isXInput) 252 { 253 captureXInput(); 254 return; 255 } 256 #endif 257 258 //handle directinput based devices 228 259 DIDEVICEOBJECTDATA diBuff[JOYSTICK_DX_BUFFERSIZE]; 229 260 DWORD entries = JOYSTICK_DX_BUFFERSIZE; … … 241 272 242 273 // Poll the device to read the current state 243 274 mJoyStick->Poll(); 244 275 hr = mJoyStick->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 ); 245 276 //Perhaps the user just tabbed away … … 353 384 354 385 //--------------------------------------------------------------------------------------------------// 386 void Win32JoyStick::captureXInput() 387 { 388 #ifdef OIS_WIN32_XINPUT_SUPPORT 389 XINPUT_STATE inputState; 390 if (XInputGetState((DWORD)mJoyInfo.xInputDev, &inputState) != ERROR_SUCCESS) 391 memset(&inputState, 0, sizeof(inputState)); 392 393 //Sticks and triggers 394 int value; 395 bool axisMoved[XINPUT_TRANSLATED_AXIS_COUNT] = {false,false,false,false,false,false}; 396 397 //LeftY 398 value = -(int)inputState.Gamepad.sThumbLY; 399 mState.mAxes[0].rel = value - mState.mAxes[0].abs; 400 mState.mAxes[0].abs = value; 401 if(mState.mAxes[0].rel != 0) 402 axisMoved[0] = true; 403 404 //LeftX 405 mState.mAxes[1].rel = inputState.Gamepad.sThumbLX - mState.mAxes[1].abs; 406 mState.mAxes[1].abs = inputState.Gamepad.sThumbLX; 407 408 if(mState.mAxes[1].rel != 0) 409 axisMoved[1] = true; 410 411 //RightY 412 value = -(int)inputState.Gamepad.sThumbRY; 413 mState.mAxes[2].rel = value - mState.mAxes[2].abs; 414 mState.mAxes[2].abs = value; 415 if(mState.mAxes[2].rel != 0) 416 axisMoved[2] = true; 417 418 //RightX 419 mState.mAxes[3].rel = inputState.Gamepad.sThumbRX - mState.mAxes[3].abs; 420 mState.mAxes[3].abs = inputState.Gamepad.sThumbRX; 421 if(mState.mAxes[3].rel != 0) 422 axisMoved[3] = true; 423 424 //Left trigger 425 value = inputState.Gamepad.bLeftTrigger * 129; 426 if(value > JoyStick::MAX_AXIS) 427 value = JoyStick::MAX_AXIS; 428 429 mState.mAxes[4].rel = value - mState.mAxes[4].abs; 430 mState.mAxes[4].abs = value; 431 if(mState.mAxes[4].rel != 0) 432 axisMoved[4] = true; 433 434 //Right trigger 435 value = (int)inputState.Gamepad.bRightTrigger * 129; 436 if(value > JoyStick::MAX_AXIS) 437 value = JoyStick::MAX_AXIS; 438 439 mState.mAxes[5].rel = value - mState.mAxes[5].abs; 440 mState.mAxes[5].abs = value; 441 if(mState.mAxes[5].rel != 0) 442 axisMoved[5] = true; 443 444 //POV 445 int previousPov = mState.mPOV[0].direction; 446 int& pov = mState.mPOV[0].direction; 447 pov = Pov::Centered; 448 if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) 449 pov |= Pov::North; 450 else if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) 451 pov |= Pov::South; 452 if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) 453 pov |= Pov::West; 454 else if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) 455 pov |= Pov::East; 456 457 //Buttons - The first 4 buttons don't need to be checked since they represent the dpad 458 bool previousButtons[XINPUT_TRANSLATED_BUTTON_COUNT]; 459 std::copy(mState.mButtons.begin(), mState.mButtons.end(), previousButtons); 460 for (size_t i = 0; i < XINPUT_TRANSLATED_BUTTON_COUNT; i++) 461 mState.mButtons[i] = (inputState.Gamepad.wButtons & (1 << (i + 4))) != 0; 462 463 //Send events 464 if (mBuffered && mListener) 465 { 466 JoyStickEvent joystickEvent(this, mState); 467 468 //Axes 469 for (int i = 0; i < XINPUT_TRANSLATED_AXIS_COUNT; i++) 470 { 471 if (axisMoved[i] && !mListener->axisMoved(joystickEvent, i)) 472 return; 473 } 474 475 //POV 476 if (previousPov != pov && !mListener->povMoved(joystickEvent, 0)) 477 return; 478 479 //Buttons 480 for (int i = 0; i < XINPUT_TRANSLATED_BUTTON_COUNT; i++) 481 { 482 if (!previousButtons[i] && mState.mButtons[i]) 483 { 484 if (!mListener->buttonPressed(joystickEvent, i)) 485 return; 486 } 487 else if (previousButtons[i] && !mState.mButtons[i]) 488 { 489 if (!mListener->buttonReleased(joystickEvent, i)) 490 return; 491 } 492 } 493 } 494 #endif 495 } 496 497 //--------------------------------------------------------------------------------------------------// 355 498 bool Win32JoyStick::_doButtonClick( int button, DIDEVICEOBJECTDATA& di ) 356 499 { … … 410 553 Interface* Win32JoyStick::queryInterface(Interface::IType type) 411 554 { 412 //Thought about using covariant return type here.. however, 413 //some devices may allow LED light changing, or other interface stuff 414 415 if( ff_device && type == Interface::ForceFeedback ) 416 return ff_device; 555 if( mFfDevice && type == Interface::ForceFeedback ) 556 return mFfDevice; 417 557 else 418 558 return 0; 419 559 } 560 561 //--------------------------------------------------------------------------------------------------// 562 void Win32JoyStick::CheckXInputDevices(JoyStickInfoList &joys) 563 { 564 IWbemLocator* pIWbemLocator = NULL; 565 IEnumWbemClassObject* pEnumDevices = NULL; 566 IWbemClassObject* pDevices[20] = {0}; 567 IWbemServices* pIWbemServices = NULL; 568 BSTR bstrNamespace = NULL; 569 BSTR bstrDeviceID = NULL; 570 BSTR bstrClassName = NULL; 571 DWORD uReturned = 0; 572 bool bIsXinputDevice= false; 573 DWORD iDevice = 0; 574 int xDevice = 0; 575 VARIANT var; 576 HRESULT hr; 577 578 if(joys.size() == 0) 579 return; 580 581 // CoInit if needed 582 hr = CoInitialize(NULL); 583 bool bCleanupCOM = SUCCEEDED(hr); 584 585 // Create WMI 586 hr = CoCreateInstance(__uuidof(WbemLocator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IWbemLocator), (LPVOID*)&pIWbemLocator); 587 if( FAILED(hr) || pIWbemLocator == NULL ) 588 goto LCleanup; 589 590 bstrNamespace = SysAllocString( L"\\\\.\\root\\cimv2" ); 591 if( bstrNamespace == NULL ) 592 goto LCleanup; 593 594 bstrClassName = SysAllocString( L"Win32_PNPEntity" ); 595 if( bstrClassName == NULL ) 596 goto LCleanup; 597 598 bstrDeviceID = SysAllocString( L"DeviceID" ); 599 if( bstrDeviceID == NULL ) 600 goto LCleanup; 601 602 // Connect to WMI 603 hr = pIWbemLocator->ConnectServer( bstrNamespace, NULL, NULL, 0L, 0L, NULL, NULL, &pIWbemServices ); 604 if( FAILED(hr) || pIWbemServices == NULL ) 605 goto LCleanup; 606 607 // Switch security level to IMPERSONATE. 608 CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE ); 609 610 hr = pIWbemServices->CreateInstanceEnum( bstrClassName, 0, NULL, &pEnumDevices ); 611 if( FAILED(hr) || pEnumDevices == NULL ) 612 goto LCleanup; 613 614 // Loop over all devices 615 for( ;; ) 616 { 617 // Get 20 at a time 618 hr = pEnumDevices->Next(5000, 20, pDevices, &uReturned); 619 if( FAILED(hr) ) 620 goto LCleanup; 621 622 if( uReturned == 0 ) 623 break; 624 625 for(iDevice = 0; iDevice < uReturned; iDevice++) 626 { 627 // For each device, get its device ID 628 hr = pDevices[iDevice]->Get(bstrDeviceID, 0L, &var, NULL, NULL); 629 if(SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != NULL) 630 { 631 // Check if the device ID contains "IG_". If it does, then it's an XInput device - This information can not be found from DirectInput 632 if(wcsstr(var.bstrVal, L"IG_")) 633 { 634 // If it does, then get the VID/PID from var.bstrVal 635 DWORD dwPid = 0, dwVid = 0; 636 WCHAR* strVid = wcsstr( var.bstrVal, L"VID_" ); 637 if(strVid && swscanf_s( strVid, L"VID_%4X", &dwVid ) != 1) 638 dwVid = 0; 639 640 WCHAR* strPid = wcsstr( var.bstrVal, L"PID_" ); 641 if(strPid && swscanf_s( strPid, L"PID_%4X", &dwPid ) != 1) 642 dwPid = 0; 643 644 // Compare the VID/PID to the DInput device 645 DWORD dwVidPid = MAKELONG(dwVid, dwPid); 646 for(JoyStickInfoList::iterator i = joys.begin(); i != joys.end(); ++i) 647 { 648 if(dwVidPid == i->productGuid.Data1) 649 { 650 i->isXInput = true; 651 i->xInputDev = xDevice; 652 } 653 } 654 655 if(joys.size() == 0) 656 goto LCleanup; 657 } 658 } 659 660 SAFE_RELEASE(pDevices[iDevice]); 661 } 662 } 663 664 LCleanup: 665 if(bstrNamespace) 666 SysFreeString(bstrNamespace); 667 668 if(bstrDeviceID) 669 SysFreeString(bstrDeviceID); 670 671 if(bstrClassName) 672 SysFreeString(bstrClassName); 673 674 for(iDevice=0; iDevice < 20; iDevice++) 675 SAFE_RELEASE(pDevices[iDevice]); 676 677 SAFE_RELEASE(pEnumDevices); 678 SAFE_RELEASE(pIWbemLocator); 679 SAFE_RELEASE(pIWbemServices); 680 681 if(bCleanupCOM) 682 CoUninitialize(); 683 }
Note: See TracChangeset
for help on using the changeset viewer.