| [1505] | 1 | /* | 
|---|
 | 2 | The zlib/libpng License | 
|---|
 | 3 |  | 
|---|
 | 4 | Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com) | 
|---|
 | 5 |  | 
|---|
 | 6 | This software is provided 'as-is', without any express or implied warranty. In no event will | 
|---|
 | 7 | the authors be held liable for any damages arising from the use of this software. | 
|---|
 | 8 |  | 
|---|
 | 9 | Permission is granted to anyone to use this software for any purpose, including commercial | 
|---|
 | 10 | applications, and to alter it and redistribute it freely, subject to the following | 
|---|
 | 11 | restrictions: | 
|---|
 | 12 |  | 
|---|
 | 13 |     1. The origin of this software must not be misrepresented; you must not claim that | 
|---|
 | 14 |                 you wrote the original software. If you use this software in a product, | 
|---|
 | 15 |                 an acknowledgment in the product documentation would be appreciated but is | 
|---|
 | 16 |                 not required. | 
|---|
 | 17 |  | 
|---|
 | 18 |     2. Altered source versions must be plainly marked as such, and must not be | 
|---|
 | 19 |                 misrepresented as being the original software. | 
|---|
 | 20 |  | 
|---|
 | 21 |     3. This notice may not be removed or altered from any source distribution. | 
|---|
 | 22 | */ | 
|---|
| [8351] | 23 | #include "win32/Win32JoyStick.h" | 
|---|
 | 24 | #include "win32/Win32InputManager.h" | 
|---|
 | 25 | #include "win32/Win32ForceFeedback.h" | 
|---|
| [1505] | 26 | #include "OISEvents.h" | 
|---|
 | 27 | #include "OISException.h" | 
|---|
 | 28 |  | 
|---|
| [8351] | 29 | // (Orxonox): Required for MinGW to compile properly | 
|---|
 | 30 | #ifdef __MINGW32__ | 
|---|
 | 31 | #  include <oaidl.h> | 
|---|
 | 32 | #  ifndef __MINGW_EXTENSION | 
|---|
 | 33 | #    define __MINGW_EXTENSION __extension__ | 
|---|
 | 34 | #  endif | 
|---|
 | 35 | #endif | 
|---|
 | 36 |  | 
|---|
| [1505] | 37 | #include <cassert> | 
|---|
| [8351] | 38 | #include <wbemidl.h> | 
|---|
 | 39 | #include <oleauto.h> | 
|---|
 | 40 | //#include <wmsstd.h> | 
|---|
 | 41 | #ifndef SAFE_RELEASE | 
|---|
 | 42 | #define SAFE_RELEASE(x) \ | 
|---|
 | 43 |    if(x != NULL)        \ | 
|---|
 | 44 |    {                    \ | 
|---|
 | 45 |       x->Release();     \ | 
|---|
 | 46 |       x = NULL;         \ | 
|---|
 | 47 |    } | 
|---|
 | 48 | #endif | 
|---|
| [1505] | 49 |  | 
|---|
| [8351] | 50 | // (Orxonox): MinGW doesn't have swscanf_s | 
|---|
 | 51 | #ifdef __MINGW32__ | 
|---|
 | 52 | #       define swscanf_s swscanf | 
|---|
 | 53 | #endif | 
|---|
 | 54 |  | 
|---|
 | 55 | #ifdef OIS_WIN32_XINPUT_SUPPORT | 
|---|
 | 56 | #       pragma comment(lib, "xinput.lib") | 
|---|
 | 57 | #endif | 
|---|
 | 58 |  | 
|---|
| [1505] | 59 | //DX Only defines macros for the JOYSTICK not JOYSTICK2, so fix it | 
|---|
 | 60 | #undef DIJOFS_BUTTON | 
|---|
 | 61 | #undef DIJOFS_POV | 
|---|
 | 62 |  | 
|---|
 | 63 | #define DIJOFS_BUTTON(n)  (FIELD_OFFSET(DIJOYSTATE2, rgbButtons) + (n)) | 
|---|
 | 64 | #define DIJOFS_POV(n)     (FIELD_OFFSET(DIJOYSTATE2, rgdwPOV)+(n)*sizeof(DWORD)) | 
|---|
 | 65 | #define DIJOFS_SLIDER0(n) (FIELD_OFFSET(DIJOYSTATE2, rglSlider)+(n) * sizeof(LONG)) | 
|---|
 | 66 | #define DIJOFS_SLIDER1(n) (FIELD_OFFSET(DIJOYSTATE2, rglVSlider)+(n) * sizeof(LONG)) | 
|---|
 | 67 | #define DIJOFS_SLIDER2(n) (FIELD_OFFSET(DIJOYSTATE2, rglASlider)+(n) * sizeof(LONG)) | 
|---|
 | 68 | #define DIJOFS_SLIDER3(n) (FIELD_OFFSET(DIJOYSTATE2, rglFSlider)+(n) * sizeof(LONG)) | 
|---|
 | 69 |  | 
|---|
| [8351] | 70 | #define XINPUT_TRANSLATED_BUTTON_COUNT 12 | 
|---|
 | 71 | #define XINPUT_TRANSLATED_AXIS_COUNT 6 | 
|---|
 | 72 |  | 
|---|
| [1505] | 73 | using namespace OIS; | 
|---|
 | 74 |  | 
|---|
 | 75 | //--------------------------------------------------------------------------------------------------// | 
|---|
| [8351] | 76 | Win32JoyStick::Win32JoyStick( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings, const JoyStickInfo &info ) : | 
|---|
 | 77 |         JoyStick(info.vendor, buffered, info.devId, creator), | 
|---|
 | 78 |         mDirectInput(pDI), | 
|---|
 | 79 |         coopSetting(coopSettings), | 
|---|
 | 80 |         mJoyStick(0), | 
|---|
 | 81 |         mJoyInfo(info), | 
|---|
 | 82 |         mFfDevice(0) | 
|---|
| [1505] | 83 | { | 
|---|
 | 84 | } | 
|---|
 | 85 |  | 
|---|
 | 86 | //--------------------------------------------------------------------------------------------------// | 
|---|
 | 87 | Win32JoyStick::~Win32JoyStick() | 
|---|
 | 88 | { | 
|---|
| [8351] | 89 |         delete mFfDevice; | 
|---|
| [1505] | 90 |  | 
|---|
 | 91 |         if(mJoyStick) | 
|---|
 | 92 |         { | 
|---|
 | 93 |                 mJoyStick->Unacquire(); | 
|---|
 | 94 |                 mJoyStick->Release(); | 
|---|
 | 95 |                 mJoyStick = 0; | 
|---|
 | 96 |         } | 
|---|
 | 97 |  | 
|---|
 | 98 |         //Return joystick to pool | 
|---|
| [8351] | 99 |         static_cast<Win32InputManager*>(mCreator)->_returnJoyStick(mJoyInfo); | 
|---|
| [1505] | 100 | } | 
|---|
 | 101 |  | 
|---|
 | 102 | //--------------------------------------------------------------------------------------------------// | 
|---|
 | 103 | void Win32JoyStick::_initialize() | 
|---|
 | 104 | { | 
|---|
| [8351] | 105 |     if (mJoyInfo.isXInput) | 
|---|
 | 106 |     { | 
|---|
 | 107 |         _enumerate(); | 
|---|
 | 108 |     } | 
|---|
 | 109 |     else | 
|---|
 | 110 |     { | 
|---|
 | 111 |             //Clear old state | 
|---|
 | 112 |             mState.mAxes.clear(); | 
|---|
| [1505] | 113 |  | 
|---|
| [8351] | 114 |             delete mFfDevice; | 
|---|
 | 115 |             mFfDevice = 0; | 
|---|
| [1505] | 116 |  | 
|---|
| [8351] | 117 |             DIPROPDWORD dipdw; | 
|---|
| [1505] | 118 |  | 
|---|
| [8351] | 119 |             dipdw.diph.dwSize       = sizeof(DIPROPDWORD); | 
|---|
 | 120 |             dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); | 
|---|
 | 121 |             dipdw.diph.dwObj        = 0; | 
|---|
 | 122 |             dipdw.diph.dwHow        = DIPH_DEVICE; | 
|---|
 | 123 |             dipdw.dwData            = JOYSTICK_DX_BUFFERSIZE; | 
|---|
| [1505] | 124 |  | 
|---|
| [8351] | 125 |             if(FAILED(mDirectInput->CreateDevice(mJoyInfo.deviceID, &mJoyStick, NULL))) | 
|---|
 | 126 |                     OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> Could not initialize joy device!"); | 
|---|
| [1505] | 127 |  | 
|---|
| [8351] | 128 |             if(FAILED(mJoyStick->SetDataFormat(&c_dfDIJoystick2))) | 
|---|
 | 129 |                     OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> data format error!"); | 
|---|
| [5695] | 130 |  | 
|---|
| [8351] | 131 |             HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle(); | 
|---|
| [1505] | 132 |  | 
|---|
| [8351] | 133 |             if(FAILED(mJoyStick->SetCooperativeLevel( hwin, coopSetting))) | 
|---|
 | 134 |                     OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> failed to set cooperation level!"); | 
|---|
| [1505] | 135 |  | 
|---|
| [8351] | 136 |             if( FAILED(mJoyStick->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)) ) | 
|---|
 | 137 |                     OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set buffer size property" ); | 
|---|
| [1505] | 138 |  | 
|---|
| [8351] | 139 |             //Enumerate all axes/buttons/sliders/etc before aquiring | 
|---|
 | 140 |             _enumerate(); | 
|---|
 | 141 |  | 
|---|
 | 142 |             mState.clear(); | 
|---|
 | 143 |  | 
|---|
 | 144 |             capture(); | 
|---|
 | 145 |     } | 
|---|
| [1505] | 146 | } | 
|---|
 | 147 |  | 
|---|
 | 148 | //--------------------------------------------------------------------------------------------------// | 
|---|
 | 149 | void Win32JoyStick::_enumerate() | 
|---|
 | 150 | { | 
|---|
| [8351] | 151 |     if (mJoyInfo.isXInput) | 
|---|
 | 152 |     { | 
|---|
 | 153 |         mPOVs = 1; | 
|---|
| [1505] | 154 |  | 
|---|
| [8351] | 155 |         mState.mButtons.resize(XINPUT_TRANSLATED_BUTTON_COUNT); | 
|---|
 | 156 |             mState.mAxes.resize(XINPUT_TRANSLATED_AXIS_COUNT); | 
|---|
 | 157 |     } | 
|---|
 | 158 |     else | 
|---|
 | 159 |     { | 
|---|
 | 160 |                 // Get joystick capabilities. | 
|---|
 | 161 |                 mDIJoyCaps.dwSize = sizeof(DIDEVCAPS); | 
|---|
 | 162 |                 if( FAILED(mJoyStick->GetCapabilities(&mDIJoyCaps)) ) | 
|---|
 | 163 |                         OIS_EXCEPT( E_General, "Win32JoyStick::_enumerate >> Failed to get capabilities" ); | 
|---|
| [1505] | 164 |  | 
|---|
| [8351] | 165 |             mPOVs = (short)mDIJoyCaps.dwPOVs; | 
|---|
| [1505] | 166 |  | 
|---|
| [8351] | 167 |             mState.mButtons.resize(mDIJoyCaps.dwButtons); | 
|---|
 | 168 |             mState.mAxes.resize(mDIJoyCaps.dwAxes); | 
|---|
| [5695] | 169 |  | 
|---|
| [8351] | 170 |             //Reset the axis mapping enumeration value | 
|---|
 | 171 |             _AxisNumber = 0; | 
|---|
| [1505] | 172 |  | 
|---|
| [8351] | 173 |             //Enumerate Force Feedback (if any) | 
|---|
 | 174 |             mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL); | 
|---|
 | 175 |  | 
|---|
 | 176 |             //Enumerate and set axis constraints (and check FF Axes) | 
|---|
 | 177 |             mJoyStick->EnumObjects(DIEnumDeviceObjectsCallback, this, DIDFT_AXIS); | 
|---|
 | 178 |     } | 
|---|
| [1505] | 179 | } | 
|---|
 | 180 |  | 
|---|
 | 181 | //--------------------------------------------------------------------------------------------------// | 
|---|
 | 182 | BOOL CALLBACK Win32JoyStick::DIEnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) | 
|---|
 | 183 | { | 
|---|
 | 184 |         Win32JoyStick* _this = (Win32JoyStick*)pvRef; | 
|---|
 | 185 |  | 
|---|
 | 186 |         //Setup mappings | 
|---|
 | 187 |         DIPROPPOINTER diptr; | 
|---|
 | 188 |         diptr.diph.dwSize       = sizeof(DIPROPPOINTER); | 
|---|
 | 189 |         diptr.diph.dwHeaderSize = sizeof(DIPROPHEADER); | 
|---|
 | 190 |         diptr.diph.dwHow        = DIPH_BYID; | 
|---|
 | 191 |         diptr.diph.dwObj        = lpddoi->dwType; | 
|---|
 | 192 |         //Add a magic number to recognise we set seomthing | 
|---|
 | 193 |         diptr.uData             = 0x13130000 | _this->_AxisNumber; | 
|---|
 | 194 |  | 
|---|
 | 195 |         //Check if axis is slider, if so, do not treat as regular axis | 
|---|
 | 196 |         if(GUID_Slider == lpddoi->guidType) | 
|---|
 | 197 |         { | 
|---|
 | 198 |                 ++_this->mSliders; | 
|---|
 | 199 |  | 
|---|
 | 200 |                 //Decrease Axes, since this slider shows up in a different place | 
|---|
 | 201 |                 _this->mState.mAxes.pop_back(); | 
|---|
 | 202 |         } | 
|---|
 | 203 |         else if (FAILED(_this->mJoyStick->SetProperty(DIPROP_APPDATA, &diptr.diph))) | 
|---|
 | 204 |         {       //If for some reason we could not set needed user data, just ignore this axis | 
|---|
 | 205 |                 return DIENUM_CONTINUE; | 
|---|
 | 206 |         } | 
|---|
 | 207 |  | 
|---|
 | 208 |         //Increase for next time through | 
|---|
 | 209 |         if(GUID_Slider != lpddoi->guidType) | 
|---|
 | 210 |                 _this->_AxisNumber += 1; | 
|---|
 | 211 |  | 
|---|
 | 212 |         //Set range | 
|---|
 | 213 |         DIPROPRANGE diprg; | 
|---|
 | 214 |         diprg.diph.dwSize       = sizeof(DIPROPRANGE); | 
|---|
 | 215 |         diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); | 
|---|
 | 216 |         diprg.diph.dwHow        = DIPH_BYID; | 
|---|
 | 217 |         diprg.diph.dwObj        = lpddoi->dwType; | 
|---|
 | 218 |         diprg.lMin              = MIN_AXIS; | 
|---|
 | 219 |         diprg.lMax              = MAX_AXIS; | 
|---|
 | 220 |  | 
|---|
 | 221 |         if (FAILED(_this->mJoyStick->SetProperty(DIPROP_RANGE, &diprg.diph))) | 
|---|
 | 222 |                 OIS_EXCEPT( E_General, "Win32JoyStick::_DIEnumDeviceObjectsCallback >> Failed to set min/max range property" ); | 
|---|
 | 223 |  | 
|---|
| [5695] | 224 |         //Check if FF Axes, and if so, increment counter | 
|---|
| [1505] | 225 |         if((lpddoi->dwFlags & DIDOI_FFACTUATOR) != 0 ) | 
|---|
 | 226 |         { | 
|---|
| [8351] | 227 |                 if( _this->mFfDevice ) | 
|---|
| [1505] | 228 |                 { | 
|---|
| [8351] | 229 |                         _this->mFfDevice->_addFFAxis(); | 
|---|
| [1505] | 230 |                 } | 
|---|
 | 231 |         } | 
|---|
 | 232 |  | 
|---|
| [5695] | 233 |         //Force the flags for gain and auto-center support to true, | 
|---|
 | 234 |         //as DInput has no API to query the device for these capabilities | 
|---|
 | 235 |         //(the only way to know is to try them ...) | 
|---|
| [8351] | 236 |         if( _this->mFfDevice ) | 
|---|
| [5695] | 237 |         { | 
|---|
| [8351] | 238 |             _this->mFfDevice->_setGainSupport(true); | 
|---|
 | 239 |             _this->mFfDevice->_setAutoCenterSupport(true); | 
|---|
| [5695] | 240 |         } | 
|---|
 | 241 |  | 
|---|
| [1505] | 242 |         return DIENUM_CONTINUE; | 
|---|
 | 243 | } | 
|---|
 | 244 |  | 
|---|
 | 245 | //--------------------------------------------------------------------------------------------------// | 
|---|
 | 246 | BOOL CALLBACK Win32JoyStick::DIEnumEffectsCallback(LPCDIEFFECTINFO pdei, LPVOID pvRef) | 
|---|
 | 247 | { | 
|---|
 | 248 |         Win32JoyStick* _this = (Win32JoyStick*)pvRef; | 
|---|
 | 249 |  | 
|---|
| [5695] | 250 |         //Create the FF instance only after we know there is at least one effect type | 
|---|
| [8351] | 251 |         if( _this->mFfDevice == 0 ) | 
|---|
 | 252 |                 _this->mFfDevice = new Win32ForceFeedback(_this->mJoyStick, &_this->mDIJoyCaps); | 
|---|
| [1505] | 253 |  | 
|---|
| [8351] | 254 |         _this->mFfDevice->_addEffectSupport(pdei); | 
|---|
| [1505] | 255 |  | 
|---|
 | 256 |         return DIENUM_CONTINUE; | 
|---|
 | 257 | } | 
|---|
 | 258 |  | 
|---|
 | 259 | //--------------------------------------------------------------------------------------------------// | 
|---|
 | 260 | void Win32JoyStick::capture() | 
|---|
 | 261 | { | 
|---|
| [8351] | 262 | #ifdef OIS_WIN32_XINPUT_SUPPORT | 
|---|
 | 263 |         //handle xbox controller differently | 
|---|
 | 264 |     if (mJoyInfo.isXInput) | 
|---|
 | 265 |         { | 
|---|
 | 266 |                 captureXInput(); | 
|---|
 | 267 |                 return; | 
|---|
 | 268 |         } | 
|---|
 | 269 | #endif | 
|---|
 | 270 |  | 
|---|
 | 271 |         //handle directinput based devices | 
|---|
| [1505] | 272 |         DIDEVICEOBJECTDATA diBuff[JOYSTICK_DX_BUFFERSIZE]; | 
|---|
 | 273 |         DWORD entries = JOYSTICK_DX_BUFFERSIZE; | 
|---|
 | 274 |  | 
|---|
 | 275 |         // Poll the device to read the current state | 
|---|
 | 276 |         HRESULT hr = mJoyStick->Poll(); | 
|---|
 | 277 |         if( hr == DI_OK ) | 
|---|
 | 278 |                 hr = mJoyStick->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 ); | 
|---|
 | 279 |  | 
|---|
 | 280 |         if( hr != DI_OK ) | 
|---|
 | 281 |         { | 
|---|
 | 282 |                 hr = mJoyStick->Acquire(); | 
|---|
 | 283 |                 while( hr == DIERR_INPUTLOST ) | 
|---|
 | 284 |                         hr = mJoyStick->Acquire(); | 
|---|
 | 285 |  | 
|---|
 | 286 |                 // Poll the device to read the current state | 
|---|
| [8351] | 287 |                 mJoyStick->Poll(); | 
|---|
| [1505] | 288 |                 hr = mJoyStick->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 ); | 
|---|
 | 289 |                 //Perhaps the user just tabbed away | 
|---|
 | 290 |                 if( FAILED(hr) ) | 
|---|
 | 291 |                         return; | 
|---|
 | 292 |         } | 
|---|
 | 293 |  | 
|---|
 | 294 |         bool axisMoved[24] = {false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false, | 
|---|
 | 295 |                                                   false,false,false,false,false,false,false,false}; | 
|---|
 | 296 |         bool sliderMoved[4] = {false,false,false,false}; | 
|---|
 | 297 |  | 
|---|
 | 298 |         //Loop through all the events | 
|---|
 | 299 |         for(unsigned int i = 0; i < entries; ++i) | 
|---|
 | 300 |         { | 
|---|
 | 301 |                 //This may seem outof order, but is in order of the way these variables | 
|---|
 | 302 |                 //are declared in the JoyStick State 2 structure. | 
|---|
 | 303 |                 switch(diBuff[i].dwOfs) | 
|---|
 | 304 |                 { | 
|---|
 | 305 |                 //------ slider -// | 
|---|
 | 306 |                 case DIJOFS_SLIDER0(0): | 
|---|
 | 307 |                         sliderMoved[0] = true; | 
|---|
 | 308 |                         mState.mSliders[0].abX = diBuff[i].dwData; | 
|---|
 | 309 |                         break; | 
|---|
 | 310 |                 case DIJOFS_SLIDER0(1): | 
|---|
 | 311 |                         sliderMoved[0] = true; | 
|---|
 | 312 |                         mState.mSliders[0].abY = diBuff[i].dwData; | 
|---|
 | 313 |                         break; | 
|---|
 | 314 |                 //----- Max 4 POVs Next ---------------// | 
|---|
 | 315 |                 case DIJOFS_POV(0): | 
|---|
 | 316 |                         if(!_changePOV(0,diBuff[i])) | 
|---|
 | 317 |                                 return; | 
|---|
 | 318 |                         break; | 
|---|
 | 319 |                 case DIJOFS_POV(1): | 
|---|
 | 320 |                         if(!_changePOV(1,diBuff[i])) | 
|---|
 | 321 |                                 return; | 
|---|
 | 322 |                         break; | 
|---|
 | 323 |                 case DIJOFS_POV(2): | 
|---|
 | 324 |                         if(!_changePOV(2,diBuff[i])) | 
|---|
 | 325 |                                 return; | 
|---|
 | 326 |                         break; | 
|---|
 | 327 |                 case DIJOFS_POV(3): | 
|---|
 | 328 |                         if(!_changePOV(3,diBuff[i])) | 
|---|
 | 329 |                                 return; | 
|---|
 | 330 |                         break; | 
|---|
 | 331 |                 case DIJOFS_SLIDER1(0): | 
|---|
 | 332 |                         sliderMoved[1] = true; | 
|---|
 | 333 |                         mState.mSliders[1].abX = diBuff[i].dwData; | 
|---|
 | 334 |                         break; | 
|---|
 | 335 |                 case DIJOFS_SLIDER1(1): | 
|---|
 | 336 |                         sliderMoved[1] = true; | 
|---|
 | 337 |                         mState.mSliders[1].abY = diBuff[i].dwData; | 
|---|
 | 338 |                         break; | 
|---|
 | 339 |                 case DIJOFS_SLIDER2(0): | 
|---|
 | 340 |                         sliderMoved[2] = true; | 
|---|
 | 341 |                         mState.mSliders[2].abX = diBuff[i].dwData; | 
|---|
 | 342 |                         break; | 
|---|
 | 343 |                 case DIJOFS_SLIDER2(1): | 
|---|
 | 344 |                         sliderMoved[2] = true; | 
|---|
 | 345 |                         mState.mSliders[2].abY = diBuff[i].dwData; | 
|---|
 | 346 |                         break; | 
|---|
 | 347 |                 case DIJOFS_SLIDER3(0): | 
|---|
 | 348 |                         sliderMoved[3] = true; | 
|---|
 | 349 |                         mState.mSliders[3].abX = diBuff[i].dwData; | 
|---|
 | 350 |                         break; | 
|---|
 | 351 |                 case DIJOFS_SLIDER3(1): | 
|---|
 | 352 |                         sliderMoved[3] = true; | 
|---|
 | 353 |                         mState.mSliders[3].abY = diBuff[i].dwData; | 
|---|
 | 354 |                         break; | 
|---|
 | 355 |                 //-----------------------------------------// | 
|---|
 | 356 |                 default: | 
|---|
 | 357 |                         //Handle Button Events Easily using the DX Offset Macros | 
|---|
 | 358 |                         if( diBuff[i].dwOfs >= DIJOFS_BUTTON(0) && diBuff[i].dwOfs < DIJOFS_BUTTON(128) ) | 
|---|
 | 359 |                         { | 
|---|
 | 360 |                                 if(!_doButtonClick((diBuff[i].dwOfs - DIJOFS_BUTTON(0)), diBuff[i])) | 
|---|
 | 361 |                                         return; | 
|---|
 | 362 |                         } | 
|---|
 | 363 |                         else if((short)(diBuff[i].uAppData >> 16) == 0x1313) | 
|---|
 | 364 |                         {       //If it was nothing else, might be axis enumerated earlier (determined by magic number) | 
|---|
 | 365 |                                 int axis = (int)(0x0000FFFF & diBuff[i].uAppData); //Mask out the high bit | 
|---|
 | 366 |                                 assert( axis >= 0 && axis < (int)mState.mAxes.size() && "Axis out of range!"); | 
|---|
 | 367 |  | 
|---|
 | 368 |                                 if(axis >= 0 && axis < (int)mState.mAxes.size()) | 
|---|
 | 369 |                                 { | 
|---|
 | 370 |                                         mState.mAxes[axis].abs = diBuff[i].dwData; | 
|---|
 | 371 |                                         axisMoved[axis] = true; | 
|---|
 | 372 |                                 } | 
|---|
 | 373 |                         } | 
|---|
 | 374 |  | 
|---|
 | 375 |                         break; | 
|---|
 | 376 |                 } //end case | 
|---|
 | 377 |         } //end for | 
|---|
 | 378 |  | 
|---|
 | 379 |         //Check to see if any of the axes values have changed.. if so send events | 
|---|
 | 380 |         if( mBuffered && mListener && entries > 0 ) | 
|---|
 | 381 |         { | 
|---|
 | 382 |                 JoyStickEvent temp(this, mState); | 
|---|
 | 383 |  | 
|---|
 | 384 |                 //Update axes | 
|---|
 | 385 |                 for( int i = 0; i < 24; ++i ) | 
|---|
 | 386 |                         if( axisMoved[i] ) | 
|---|
 | 387 |                                 if( mListener->axisMoved( temp, i ) == false ) | 
|---|
 | 388 |                                         return; | 
|---|
 | 389 |  | 
|---|
 | 390 |                 //Now update sliders | 
|---|
 | 391 |                 for( int i = 0; i < 4; ++i ) | 
|---|
 | 392 |                         if( sliderMoved[i] ) | 
|---|
 | 393 |                                 if( mListener->sliderMoved( temp, i ) == false ) | 
|---|
 | 394 |                                         return; | 
|---|
 | 395 |         } | 
|---|
 | 396 | } | 
|---|
 | 397 |  | 
|---|
 | 398 | //--------------------------------------------------------------------------------------------------// | 
|---|
| [8351] | 399 | void Win32JoyStick::captureXInput() | 
|---|
 | 400 | { | 
|---|
 | 401 | #ifdef OIS_WIN32_XINPUT_SUPPORT | 
|---|
 | 402 |     XINPUT_STATE inputState; | 
|---|
 | 403 |         if (XInputGetState((DWORD)mJoyInfo.xInputDev, &inputState) != ERROR_SUCCESS) | 
|---|
 | 404 |         memset(&inputState, 0, sizeof(inputState)); | 
|---|
 | 405 |  | 
|---|
 | 406 |     //Sticks and triggers | 
|---|
 | 407 |         int value; | 
|---|
 | 408 |     bool axisMoved[XINPUT_TRANSLATED_AXIS_COUNT] = {false,false,false,false,false,false}; | 
|---|
 | 409 |  | 
|---|
 | 410 |         //LeftY | 
|---|
 | 411 |         value = -(int)inputState.Gamepad.sThumbLY; | 
|---|
 | 412 |         mState.mAxes[0].rel = value - mState.mAxes[0].abs; | 
|---|
 | 413 |         mState.mAxes[0].abs = value; | 
|---|
 | 414 |         if(mState.mAxes[0].rel != 0) | 
|---|
 | 415 |         axisMoved[0] = true; | 
|---|
 | 416 |  | 
|---|
 | 417 |         //LeftX | 
|---|
 | 418 |     mState.mAxes[1].rel = inputState.Gamepad.sThumbLX - mState.mAxes[1].abs; | 
|---|
 | 419 |     mState.mAxes[1].abs = inputState.Gamepad.sThumbLX; | 
|---|
 | 420 |  | 
|---|
 | 421 |         if(mState.mAxes[1].rel != 0) | 
|---|
 | 422 |         axisMoved[1] = true; | 
|---|
 | 423 |  | 
|---|
 | 424 |         //RightY | 
|---|
 | 425 |         value = -(int)inputState.Gamepad.sThumbRY;            | 
|---|
 | 426 |     mState.mAxes[2].rel = value - mState.mAxes[2].abs; | 
|---|
 | 427 |     mState.mAxes[2].abs = value; | 
|---|
 | 428 |         if(mState.mAxes[2].rel != 0) | 
|---|
 | 429 |         axisMoved[2] = true; | 
|---|
 | 430 |  | 
|---|
 | 431 |         //RightX | 
|---|
 | 432 |     mState.mAxes[3].rel = inputState.Gamepad.sThumbRX - mState.mAxes[3].abs; | 
|---|
 | 433 |     mState.mAxes[3].abs = inputState.Gamepad.sThumbRX; | 
|---|
 | 434 |         if(mState.mAxes[3].rel != 0) | 
|---|
 | 435 |                 axisMoved[3] = true; | 
|---|
 | 436 |  | 
|---|
 | 437 |         //Left trigger | 
|---|
 | 438 |     value = inputState.Gamepad.bLeftTrigger * 129; | 
|---|
 | 439 |         if(value > JoyStick::MAX_AXIS) | 
|---|
 | 440 |                 value = JoyStick::MAX_AXIS; | 
|---|
 | 441 |  | 
|---|
 | 442 |     mState.mAxes[4].rel = value - mState.mAxes[4].abs; | 
|---|
 | 443 |     mState.mAxes[4].abs = value; | 
|---|
 | 444 |         if(mState.mAxes[4].rel != 0) | 
|---|
 | 445 |                 axisMoved[4] = true; | 
|---|
 | 446 |  | 
|---|
 | 447 |         //Right trigger | 
|---|
 | 448 |     value = (int)inputState.Gamepad.bRightTrigger * 129; | 
|---|
 | 449 |         if(value > JoyStick::MAX_AXIS) | 
|---|
 | 450 |                 value = JoyStick::MAX_AXIS; | 
|---|
 | 451 |  | 
|---|
 | 452 |         mState.mAxes[5].rel = value - mState.mAxes[5].abs; | 
|---|
 | 453 |     mState.mAxes[5].abs = value; | 
|---|
 | 454 |         if(mState.mAxes[5].rel != 0) | 
|---|
 | 455 |                 axisMoved[5] = true; | 
|---|
 | 456 |      | 
|---|
 | 457 |     //POV | 
|---|
 | 458 |     int previousPov = mState.mPOV[0].direction;         | 
|---|
 | 459 |     int& pov = mState.mPOV[0].direction; | 
|---|
 | 460 |     pov = Pov::Centered;         | 
|---|
 | 461 |     if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) | 
|---|
 | 462 |         pov |= Pov::North; | 
|---|
 | 463 |     else if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) | 
|---|
 | 464 |         pov |= Pov::South; | 
|---|
 | 465 |     if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) | 
|---|
 | 466 |         pov |= Pov::West; | 
|---|
 | 467 |     else if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) | 
|---|
 | 468 |         pov |= Pov::East; | 
|---|
 | 469 |      | 
|---|
 | 470 |     //Buttons - The first 4 buttons don't need to be checked since they represent the dpad | 
|---|
 | 471 |     bool previousButtons[XINPUT_TRANSLATED_BUTTON_COUNT]; | 
|---|
 | 472 |     std::copy(mState.mButtons.begin(), mState.mButtons.end(), previousButtons); | 
|---|
 | 473 |     for (size_t i = 0; i < XINPUT_TRANSLATED_BUTTON_COUNT; i++) | 
|---|
 | 474 |         mState.mButtons[i] = (inputState.Gamepad.wButtons & (1 << (i + 4))) != 0; | 
|---|
 | 475 |  | 
|---|
 | 476 |     //Send events | 
|---|
 | 477 |     if (mBuffered && mListener) | 
|---|
 | 478 |     { | 
|---|
 | 479 |             JoyStickEvent joystickEvent(this, mState); | 
|---|
 | 480 |  | 
|---|
 | 481 |             //Axes | 
|---|
 | 482 |             for (int i = 0; i < XINPUT_TRANSLATED_AXIS_COUNT; i++) | 
|---|
 | 483 |         { | 
|---|
 | 484 |                     if (axisMoved[i] && !mListener->axisMoved(joystickEvent, i)) | 
|---|
 | 485 |                             return; | 
|---|
 | 486 |         } | 
|---|
 | 487 |  | 
|---|
 | 488 |         //POV | 
|---|
 | 489 |         if (previousPov != pov && !mListener->povMoved(joystickEvent, 0)) | 
|---|
 | 490 |             return; | 
|---|
 | 491 |  | 
|---|
 | 492 |         //Buttons | 
|---|
 | 493 |         for (int i = 0; i < XINPUT_TRANSLATED_BUTTON_COUNT; i++) | 
|---|
 | 494 |         { | 
|---|
 | 495 |             if (!previousButtons[i] && mState.mButtons[i]) | 
|---|
 | 496 |             { | 
|---|
 | 497 |                 if (!mListener->buttonPressed(joystickEvent, i)) | 
|---|
 | 498 |                     return; | 
|---|
 | 499 |             } | 
|---|
 | 500 |             else if (previousButtons[i] && !mState.mButtons[i]) | 
|---|
 | 501 |             { | 
|---|
 | 502 |                 if (!mListener->buttonReleased(joystickEvent, i)) | 
|---|
 | 503 |                     return; | 
|---|
 | 504 |             } | 
|---|
 | 505 |         } | 
|---|
 | 506 |     } | 
|---|
 | 507 | #endif | 
|---|
 | 508 | } | 
|---|
 | 509 |  | 
|---|
 | 510 | //--------------------------------------------------------------------------------------------------// | 
|---|
| [1505] | 511 | bool Win32JoyStick::_doButtonClick( int button, DIDEVICEOBJECTDATA& di ) | 
|---|
 | 512 | { | 
|---|
 | 513 |         if( di.dwData & 0x80 ) | 
|---|
 | 514 |         { | 
|---|
 | 515 |                 mState.mButtons[button] = true; | 
|---|
 | 516 |                 if( mBuffered && mListener ) | 
|---|
 | 517 |                         return mListener->buttonPressed( JoyStickEvent( this, mState ), button ); | 
|---|
 | 518 |         } | 
|---|
 | 519 |         else | 
|---|
 | 520 |         { | 
|---|
 | 521 |                 mState.mButtons[button] = false; | 
|---|
 | 522 |                 if( mBuffered && mListener ) | 
|---|
 | 523 |                         return mListener->buttonReleased( JoyStickEvent( this, mState ), button ); | 
|---|
 | 524 |         } | 
|---|
 | 525 |  | 
|---|
 | 526 |         return true; | 
|---|
 | 527 | } | 
|---|
 | 528 |  | 
|---|
 | 529 | //--------------------------------------------------------------------------------------------------// | 
|---|
 | 530 | bool Win32JoyStick::_changePOV( int pov, DIDEVICEOBJECTDATA& di ) | 
|---|
 | 531 | { | 
|---|
 | 532 |         //Some drivers report a value of 65,535, instead of 1, | 
|---|
 | 533 |         //for the center position | 
|---|
 | 534 |         if(LOWORD(di.dwData) == 0xFFFF) | 
|---|
 | 535 |         { | 
|---|
 | 536 |                 mState.mPOV[pov].direction = Pov::Centered; | 
|---|
 | 537 |         } | 
|---|
 | 538 |         else | 
|---|
 | 539 |         { | 
|---|
 | 540 |                 switch(di.dwData) | 
|---|
 | 541 |                 { | 
|---|
 | 542 |                         case 0: mState.mPOV[pov].direction = Pov::North; break; | 
|---|
 | 543 |                         case 4500: mState.mPOV[pov].direction = Pov::NorthEast; break; | 
|---|
 | 544 |                         case 9000: mState.mPOV[pov].direction = Pov::East; break; | 
|---|
 | 545 |                         case 13500: mState.mPOV[pov].direction = Pov::SouthEast; break; | 
|---|
 | 546 |                         case 18000: mState.mPOV[pov].direction = Pov::South; break; | 
|---|
 | 547 |                         case 22500: mState.mPOV[pov].direction = Pov::SouthWest; break; | 
|---|
 | 548 |                         case 27000: mState.mPOV[pov].direction = Pov::West; break; | 
|---|
 | 549 |                         case 31500: mState.mPOV[pov].direction = Pov::NorthWest; break; | 
|---|
 | 550 |                 } | 
|---|
 | 551 |         } | 
|---|
 | 552 |  | 
|---|
 | 553 |         if( mBuffered && mListener ) | 
|---|
 | 554 |                 return mListener->povMoved( JoyStickEvent( this, mState ), pov ); | 
|---|
 | 555 |  | 
|---|
 | 556 |         return true; | 
|---|
 | 557 | } | 
|---|
 | 558 |  | 
|---|
 | 559 | //--------------------------------------------------------------------------------------------------// | 
|---|
 | 560 | void Win32JoyStick::setBuffered(bool buffered) | 
|---|
 | 561 | { | 
|---|
 | 562 |         mBuffered = buffered; | 
|---|
 | 563 | } | 
|---|
 | 564 |  | 
|---|
 | 565 | //--------------------------------------------------------------------------------------------------// | 
|---|
 | 566 | Interface* Win32JoyStick::queryInterface(Interface::IType type) | 
|---|
 | 567 | { | 
|---|
| [8351] | 568 |         if( mFfDevice && type == Interface::ForceFeedback ) | 
|---|
 | 569 |                 return mFfDevice; | 
|---|
| [1505] | 570 |         else | 
|---|
 | 571 |                 return 0; | 
|---|
 | 572 | } | 
|---|
| [8351] | 573 |  | 
|---|
 | 574 | //--------------------------------------------------------------------------------------------------// | 
|---|
 | 575 | void Win32JoyStick::CheckXInputDevices(JoyStickInfoList &joys) | 
|---|
 | 576 | { | 
|---|
 | 577 |     IWbemLocator*           pIWbemLocator  = NULL; | 
|---|
 | 578 |     IEnumWbemClassObject*   pEnumDevices   = NULL; | 
|---|
 | 579 |     IWbemClassObject*       pDevices[20]   = {0}; | 
|---|
 | 580 |     IWbemServices*          pIWbemServices = NULL; | 
|---|
 | 581 |     BSTR                    bstrNamespace  = NULL; | 
|---|
 | 582 |     BSTR                    bstrDeviceID   = NULL; | 
|---|
 | 583 |     BSTR                    bstrClassName  = NULL; | 
|---|
 | 584 |     DWORD                   uReturned      = 0; | 
|---|
 | 585 |     bool                    bIsXinputDevice= false; | 
|---|
 | 586 |         DWORD                   iDevice        = 0; | 
|---|
 | 587 |         int                     xDevice        = 0; | 
|---|
 | 588 |     VARIANT                 var; | 
|---|
 | 589 |     HRESULT                 hr; | 
|---|
 | 590 |  | 
|---|
 | 591 |         if(joys.size() == 0) | 
|---|
 | 592 |                 return; | 
|---|
 | 593 |  | 
|---|
 | 594 |     // CoInit if needed | 
|---|
 | 595 |     hr = CoInitialize(NULL); | 
|---|
 | 596 |     bool bCleanupCOM = SUCCEEDED(hr); | 
|---|
 | 597 |  | 
|---|
 | 598 |     // Create WMI | 
|---|
 | 599 |     // (Orxonox): Fix for MinGW | 
|---|
 | 600 | #ifdef __MINGW32__ | 
|---|
 | 601 |     hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pIWbemLocator); | 
|---|
 | 602 | #else | 
|---|
 | 603 |     hr = CoCreateInstance(__uuidof(WbemLocator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IWbemLocator), (LPVOID*)&pIWbemLocator); | 
|---|
 | 604 | #endif | 
|---|
 | 605 |     if( FAILED(hr) || pIWbemLocator == NULL ) | 
|---|
 | 606 |         goto LCleanup; | 
|---|
 | 607 |  | 
|---|
 | 608 |     bstrNamespace = SysAllocString( L"\\\\.\\root\\cimv2" ); | 
|---|
 | 609 |         if( bstrNamespace == NULL ) | 
|---|
 | 610 |                 goto LCleanup; | 
|---|
 | 611 |  | 
|---|
 | 612 |     bstrClassName = SysAllocString( L"Win32_PNPEntity" ); | 
|---|
 | 613 |         if( bstrClassName == NULL ) | 
|---|
 | 614 |                 goto LCleanup; | 
|---|
 | 615 |  | 
|---|
 | 616 |     bstrDeviceID  = SysAllocString( L"DeviceID" ); | 
|---|
 | 617 |         if( bstrDeviceID == NULL ) | 
|---|
 | 618 |                 goto LCleanup; | 
|---|
 | 619 |      | 
|---|
 | 620 |     // Connect to WMI  | 
|---|
 | 621 |     hr = pIWbemLocator->ConnectServer( bstrNamespace, NULL, NULL, 0L, 0L, NULL, NULL, &pIWbemServices ); | 
|---|
 | 622 |     if( FAILED(hr) || pIWbemServices == NULL ) | 
|---|
 | 623 |         goto LCleanup; | 
|---|
 | 624 |  | 
|---|
 | 625 |     // Switch security level to IMPERSONATE.  | 
|---|
 | 626 |     CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );                     | 
|---|
 | 627 |  | 
|---|
 | 628 |     hr = pIWbemServices->CreateInstanceEnum( bstrClassName, 0, NULL, &pEnumDevices );  | 
|---|
 | 629 |     if( FAILED(hr) || pEnumDevices == NULL ) | 
|---|
 | 630 |         goto LCleanup; | 
|---|
 | 631 |  | 
|---|
 | 632 |     // Loop over all devices | 
|---|
 | 633 |     for( ;; ) | 
|---|
 | 634 |     { | 
|---|
 | 635 |         // Get 20 at a time | 
|---|
 | 636 |         hr = pEnumDevices->Next(5000, 20, pDevices, &uReturned); | 
|---|
 | 637 |         if( FAILED(hr) ) | 
|---|
 | 638 |             goto LCleanup; | 
|---|
 | 639 |  | 
|---|
 | 640 |         if( uReturned == 0 ) | 
|---|
 | 641 |             break; | 
|---|
 | 642 |  | 
|---|
 | 643 |         for(iDevice = 0; iDevice < uReturned; iDevice++) | 
|---|
 | 644 |         { | 
|---|
 | 645 |             // For each device, get its device ID | 
|---|
 | 646 |             hr = pDevices[iDevice]->Get(bstrDeviceID, 0L, &var, NULL, NULL); | 
|---|
 | 647 |             if(SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != NULL) | 
|---|
 | 648 |             { | 
|---|
 | 649 |                 // Check if the device ID contains "IG_".  If it does, then it's an XInput device - This information can not be found from DirectInput  | 
|---|
 | 650 |                 if(wcsstr(var.bstrVal, L"IG_")) | 
|---|
 | 651 |                 { | 
|---|
 | 652 |                     // If it does, then get the VID/PID from var.bstrVal | 
|---|
 | 653 |                     DWORD dwPid = 0, dwVid = 0; | 
|---|
 | 654 |                     WCHAR* strVid = wcsstr( var.bstrVal, L"VID_" ); | 
|---|
 | 655 |                     if(strVid && swscanf_s( strVid, L"VID_%4X", &dwVid ) != 1) | 
|---|
 | 656 |                                                 dwVid = 0; | 
|---|
 | 657 |  | 
|---|
 | 658 |                     WCHAR* strPid = wcsstr( var.bstrVal, L"PID_" ); | 
|---|
 | 659 |                     if(strPid && swscanf_s( strPid, L"PID_%4X", &dwPid ) != 1) | 
|---|
 | 660 |                         dwPid = 0; | 
|---|
 | 661 |  | 
|---|
 | 662 |                     // Compare the VID/PID to the DInput device | 
|---|
 | 663 |                     DWORD dwVidPid = MAKELONG(dwVid, dwPid); | 
|---|
 | 664 |                                         for(JoyStickInfoList::iterator i = joys.begin(); i != joys.end(); ++i) | 
|---|
 | 665 |                                         { | 
|---|
 | 666 |                                                 if(dwVidPid == i->productGuid.Data1) | 
|---|
 | 667 |                                                 { | 
|---|
 | 668 |                                                         i->isXInput = true; | 
|---|
 | 669 |                                                         i->xInputDev = xDevice; | 
|---|
 | 670 |                                                 } | 
|---|
 | 671 |                                         } | 
|---|
 | 672 |  | 
|---|
 | 673 |                                         if(joys.size() == 0) | 
|---|
 | 674 |                                                 goto LCleanup; | 
|---|
 | 675 |                 } | 
|---|
 | 676 |             } | 
|---|
 | 677 |  | 
|---|
 | 678 |             SAFE_RELEASE(pDevices[iDevice]); | 
|---|
 | 679 |         } | 
|---|
 | 680 |     } | 
|---|
 | 681 |  | 
|---|
 | 682 | LCleanup: | 
|---|
 | 683 |     if(bstrNamespace) | 
|---|
 | 684 |         SysFreeString(bstrNamespace); | 
|---|
 | 685 |  | 
|---|
 | 686 |     if(bstrDeviceID) | 
|---|
 | 687 |         SysFreeString(bstrDeviceID); | 
|---|
 | 688 |  | 
|---|
 | 689 |     if(bstrClassName) | 
|---|
 | 690 |         SysFreeString(bstrClassName); | 
|---|
 | 691 |  | 
|---|
 | 692 |     for(iDevice=0; iDevice < 20; iDevice++) | 
|---|
 | 693 |         SAFE_RELEASE(pDevices[iDevice]); | 
|---|
 | 694 |  | 
|---|
 | 695 |     SAFE_RELEASE(pEnumDevices); | 
|---|
 | 696 |     SAFE_RELEASE(pIWbemLocator); | 
|---|
 | 697 |     SAFE_RELEASE(pIWbemServices); | 
|---|
 | 698 |  | 
|---|
 | 699 |     if(bCleanupCOM) | 
|---|
 | 700 |         CoUninitialize(); | 
|---|
 | 701 | } | 
|---|