Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Oct 7, 2010, 8:21:33 PM (14 years ago)
Author:
rgrieder
Message:

Updated OIS source files to its current SVN trunk (r26).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/branches/ois_update/src/external/ois/win32/Win32JoyStick.cpp

    r5781 r7506  
    2121    3. This notice may not be removed or altered from any source distribution.
    2222*/
    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"
    2626#include "OISEvents.h"
    2727#include "OISException.h"
    2828
    2929#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
    3045
    3146//DX Only defines macros for the JOYSTICK not JOYSTICK2, so fix it
     
    4055#define DIJOFS_SLIDER3(n) (FIELD_OFFSET(DIJOYSTATE2, rglFSlider)+(n) * sizeof(LONG))
    4156
     57#define XINPUT_TRANSLATED_BUTTON_COUNT 12
     58#define XINPUT_TRANSLATED_AXIS_COUNT 6
     59
    4260using namespace OIS;
    4361
    4462//--------------------------------------------------------------------------------------------------//
    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;
     63Win32JoyStick::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{
    5671}
    5772
     
    5974Win32JoyStick::~Win32JoyStick()
    6075{
    61         delete ff_device;
     76        delete mFfDevice;
    6277
    6378        if(mJoyStick)
     
    6984
    7085        //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);
    7687}
    7788
     
    7990void Win32JoyStick::_initialize()
    8091{
    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    }
    120133}
    121134
     
    123136void Win32JoyStick::_enumerate()
    124137{
    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    }
    145166}
    146167
     
    191212        if((lpddoi->dwFlags & DIDOI_FFACTUATOR) != 0 )
    192213        {
    193                 if( _this->ff_device )
     214                if( _this->mFfDevice )
    194215                {
    195                         _this->ff_device->_addFFAxis();
     216                        _this->mFfDevice->_addFFAxis();
    196217                }
    197218        }
     
    200221        //as DInput has no API to query the device for these capabilities
    201222        //(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);
    206227        }
    207228
     
    215236
    216237        //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);
    221242
    222243        return DIENUM_CONTINUE;
     
    226247void Win32JoyStick::capture()
    227248{
     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
    228259        DIDEVICEOBJECTDATA diBuff[JOYSTICK_DX_BUFFERSIZE];
    229260        DWORD entries = JOYSTICK_DX_BUFFERSIZE;
     
    241272
    242273                // Poll the device to read the current state
    243             mJoyStick->Poll();
     274                mJoyStick->Poll();
    244275                hr = mJoyStick->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
    245276                //Perhaps the user just tabbed away
     
    353384
    354385//--------------------------------------------------------------------------------------------------//
     386void 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//--------------------------------------------------------------------------------------------------//
    355498bool Win32JoyStick::_doButtonClick( int button, DIDEVICEOBJECTDATA& di )
    356499{
     
    410553Interface* Win32JoyStick::queryInterface(Interface::IType type)
    411554{
    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;
    417557        else
    418558                return 0;
    419559}
     560
     561//--------------------------------------------------------------------------------------------------//
     562void 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
     664LCleanup:
     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.