E:/Download/ois-1.0RC1/src/win32/Win32JoyStick.cpp

Go to the documentation of this file.
00001 /*
00002 The zlib/libpng License
00003 
00004 Copyright (c) 2006 Phillip Castaneda (pjcast -- www.wreckedgames.com)
00005 
00006 This software is provided 'as-is', without any express or implied warranty. In no event will
00007 the authors be held liable for any damages arising from the use of this software.
00008 
00009 Permission is granted to anyone to use this software for any purpose, including commercial
00010 applications, and to alter it and redistribute it freely, subject to the following
00011 restrictions:
00012 
00013     1. The origin of this software must not be misrepresented; you must not claim that
00014                 you wrote the original software. If you use this software in a product,
00015                 an acknowledgment in the product documentation would be appreciated but is
00016                 not required.
00017 
00018     2. Altered source versions must be plainly marked as such, and must not be
00019                 misrepresented as being the original software.
00020 
00021     3. This notice may not be removed or altered from any source distribution.
00022 */
00023 #include "Win32/Win32JoyStick.h"
00024 #include "Win32/Win32InputManager.h"
00025 #include "Win32/Win32ForceFeedback.h"
00026 
00027 #include "OISEvents.h"
00028 #include "OISException.h"
00029 
00030 #include <cassert>
00031 
00032 using namespace OIS;
00033 
00034 //--------------------------------------------------------------------------------------------------//
00035 Win32JoyStick::Win32JoyStick( InputManager* creator, IDirectInput8* pDI,
00036                                                          bool buffered, DWORD coopSettings,
00037                                                          const JoyStickInfo &info )
00038 {
00039         mCreator = creator;
00040         mBuffered = buffered;
00041         mDirectInput = pDI;
00042         coopSetting = coopSettings;
00043         mJoyStick = 0;
00044         mType = OISJoyStick;
00045 
00046         deviceGuid = info.deviceID;
00047         mVendor = info.vendor;
00048         mDevID = info.devId;
00049 
00050         listener = 0;
00051         ff_device = 0;
00052 }
00053 
00054 //--------------------------------------------------------------------------------------------------//
00055 Win32JoyStick::~Win32JoyStick()
00056 {
00057         delete ff_device;
00058 
00059         if(mJoyStick)
00060         {
00061                 mJoyStick->Unacquire();
00062                 mJoyStick->Release();
00063                 mJoyStick = 0;
00064         }
00065 }
00066 
00067 //--------------------------------------------------------------------------------------------------//
00068 void Win32JoyStick::_initialize()
00069 {
00070         //Clear old state
00071         mState.mAxes.clear();
00072 
00073         delete ff_device;
00074         ff_device = 0;
00075 
00076         DIPROPDWORD dipdw;
00077 
00078         dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
00079         dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
00080         dipdw.diph.dwObj        = 0;
00081         dipdw.diph.dwHow        = DIPH_DEVICE;
00082         dipdw.dwData            = JOYSTICK_DX_BUFFERSIZE;
00083 
00084         if(FAILED(mDirectInput->CreateDevice(deviceGuid, &mJoyStick, NULL)))
00085                 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> Could not initialize joy device!");
00086 
00087         if(FAILED(mJoyStick->SetDataFormat(&c_dfDIJoystick2)))
00088                 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> data format error!");
00089 
00090         HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle();
00091 
00092         if(FAILED(mJoyStick->SetCooperativeLevel( hwin, coopSetting)))
00093                 OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> failed to set cooperation level!");
00094 
00095         if( FAILED(mJoyStick->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)) )
00096                 OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set buffer size property" );
00097 
00098         //Enumerate all axes/buttons/sliders/etc before aquiring
00099         _enumerate();
00100 
00101         mState.clear();
00102 
00103         capture();
00104 }
00105 
00106 //--------------------------------------------------------------------------------------------------//
00107 void Win32JoyStick::_enumerate()
00108 {
00109         //We can check force feedback here too
00110         DIDEVCAPS  DIJoyCaps;
00111         DIJoyCaps.dwSize = sizeof(DIDEVCAPS);
00112         mJoyStick->GetCapabilities(&DIJoyCaps);
00113 
00114         numAxes = (short)DIJoyCaps.dwAxes;
00115         numButtons = (short)DIJoyCaps.dwButtons;
00116         numHats = (short)DIJoyCaps.dwPOVs;
00117 
00118         mState.mAxes.resize(numAxes);
00119 
00120         //Reset the axis mapping enumeration value
00121         _AxisNumber = 0;
00122 
00123         //Enumerate Force Feedback (if any)
00124         mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL);
00125 
00126         //Enumerate and set axis constraints (and check FF Axes)
00127         mJoyStick->EnumObjects(DIEnumDeviceObjectsCallback, this, DIDFT_AXIS);
00128 }
00129 
00130 //--------------------------------------------------------------------------------------------------//
00131 BOOL CALLBACK Win32JoyStick::DIEnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef)
00132 {
00133         Win32JoyStick* _this = (Win32JoyStick*)pvRef;
00134 
00135         //Setup mappings
00136         DIPROPPOINTER diptr;
00137         diptr.diph.dwSize       = sizeof(DIPROPPOINTER);
00138         diptr.diph.dwHeaderSize = sizeof(DIPROPHEADER);
00139         diptr.diph.dwHow        = DIPH_BYID;
00140         diptr.diph.dwObj        = lpddoi->dwType;
00141         //Add the high bit in so that an axis value of zero does not mean a null userdata
00142         diptr.uData             = 0x80000000 | _this->_AxisNumber++;
00143 
00144         if (FAILED(_this->mJoyStick->SetProperty(DIPROP_APPDATA, &diptr.diph)))
00145                 OIS_EXCEPT( E_General, "Win32JoyStick::_DIEnumDeviceObjectsCallback >> Failed to set mapping ptr property" );
00146 
00147         //Set range
00148         DIPROPRANGE diprg;
00149         diprg.diph.dwSize       = sizeof(DIPROPRANGE);
00150         diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
00151         diprg.diph.dwHow        = DIPH_BYID;
00152         diprg.diph.dwObj        = lpddoi->dwType;
00153         diprg.lMin              = MIN_AXIS;
00154         diprg.lMax              = MAX_AXIS;
00155 
00156         if (FAILED(_this->mJoyStick->SetProperty(DIPROP_RANGE, &diprg.diph)))
00157                 OIS_EXCEPT( E_General, "Win32JoyStick::_DIEnumDeviceObjectsCallback >> Failed to set min/max range property" );
00158 
00159         //Check if FF Axes
00160         if((lpddoi->dwFlags & DIDOI_FFACTUATOR) != 0 )
00161         {
00162                 assert( _this->ff_device && "Force Feedback axis found, but this device did not report any effects?");
00163                 if( _this->ff_device )
00164                 {
00165                         //todo - increment force feedback axis count
00166                 }
00167         }
00168 
00169         return DIENUM_CONTINUE;
00170 }
00171 
00172 //--------------------------------------------------------------------------------------------------//
00173 BOOL CALLBACK Win32JoyStick::DIEnumEffectsCallback(LPCDIEFFECTINFO pdei, LPVOID pvRef)
00174 {
00175         Win32JoyStick* _this = (Win32JoyStick*)pvRef;
00176 
00177         //Create the FF class after we know there is at least one effect type
00178         if( _this->ff_device == 0 )
00179                 _this->ff_device = new Win32ForceFeedback(_this->mJoyStick);
00180 
00181         _this->ff_device->_addEffectSupport( pdei );
00182 
00183         return DIENUM_CONTINUE;
00184 }
00185 
00186 //--------------------------------------------------------------------------------------------------//
00187 void Win32JoyStick::capture()
00188 {
00189         DIDEVICEOBJECTDATA diBuff[JOYSTICK_DX_BUFFERSIZE];
00190         DWORD entries = JOYSTICK_DX_BUFFERSIZE;
00191 
00192         // Poll the device to read the current state
00193         HRESULT hr = mJoyStick->Poll();
00194         if( hr == DI_OK )
00195                 hr = mJoyStick->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
00196 
00197         if( hr != DI_OK )
00198         {
00199                 hr = mJoyStick->Acquire();
00200                 while( hr == DIERR_INPUTLOST )
00201                         hr = mJoyStick->Acquire();
00202 
00203                 // Poll the device to read the current state
00204             mJoyStick->Poll();
00205                 hr = mJoyStick->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
00206                 //Perhaps the user just tabbed away
00207                 if( FAILED(hr) )
00208                         return;
00209         }
00210 
00211         bool axisMoved[24] = {false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,
00212                                                   false,false,false,false,false,false,false,false};
00213         bool sliderMoved[4] = {false,false,false,false};
00214 
00215         //Loop through all the events
00216         for(unsigned int i = 0; i < entries; ++i)
00217         {
00218                 //First check to see if event entry is a Axis we enumerated earlier
00219                 if( diBuff[i].uAppData != 0xFFFFFFFF && diBuff[i].uAppData > 0 )
00220                 {
00221                         int axis = 0x7FFFFFFF & diBuff[i].uAppData; //Mask out the high bit
00222                         assert( axis >= 0 && axis < mState.mAxes.size() && "Axis out of range!");
00223                         mState.mAxes[axis].abs = diBuff[i].dwData;
00224                         axisMoved[axis] = true;
00225                 }
00226                 else
00227                 {
00228                         //DX Only defines macros for the JOYSTICK not JOYSTICK2, so we redeclare them to match what we are using
00229                         #undef DIJOFS_BUTTON
00230                         #undef DIJOFS_POV
00231                         #define DIJOFS_BUTTON(n) (FIELD_OFFSET(DIJOYSTATE2, rgbButtons) + (n))
00232                         #define DIJOFS_POV(n) (FIELD_OFFSET(DIJOYSTATE2, rgdwPOV)+(n)*sizeof(DWORD))
00233 
00234                         #define DIJOFS_SLIDER0(n) (FIELD_OFFSET(DIJOYSTATE2, rglSlider)+(n) * sizeof(LONG))
00235                         #define DIJOFS_SLIDER1(n) (FIELD_OFFSET(DIJOYSTATE2, rglVSlider)+(n) * sizeof(LONG))
00236                         #define DIJOFS_SLIDER2(n) (FIELD_OFFSET(DIJOYSTATE2, rglASlider)+(n) * sizeof(LONG))
00237                         #define DIJOFS_SLIDER3(n) (FIELD_OFFSET(DIJOYSTATE2, rglFSlider)+(n) * sizeof(LONG))
00238 
00239                         //This may seem outof order, but is in order of the way these variables
00240                         //are declared in the JoyStick State 2 structure.
00241                         switch(diBuff[i].dwOfs)
00242                         {
00243                         //------ slider -//
00244                         case DIJOFS_SLIDER0(0):
00245                                 sliderMoved[0] = true;
00246                                 mState.mSliders[0].abX = diBuff[i].dwData;
00247                                 break;
00248                         case DIJOFS_SLIDER0(1):
00249                                 sliderMoved[0] = true;
00250                                 mState.mSliders[0].abY = diBuff[i].dwData;
00251                                 break;
00252                         //----- Max 4 POVs Next ---------------//
00253                         case DIJOFS_POV(0):
00254                                 if(!_changePOV(0,diBuff[i]))
00255                                         return;
00256                                 break;
00257                         case DIJOFS_POV(1):
00258                                 if(!_changePOV(1,diBuff[i]))
00259                                         return;
00260                                 break;
00261                         case DIJOFS_POV(2):
00262                                 if(!_changePOV(2,diBuff[i]))
00263                                         return;
00264                                 break;
00265                         case DIJOFS_POV(3):
00266                                 if(!_changePOV(3,diBuff[i]))
00267                                         return;
00268                                 break;
00269                         case DIJOFS_SLIDER1(0):
00270                                 sliderMoved[1] = true;
00271                                 mState.mSliders[1].abX = diBuff[i].dwData;
00272                                 break;
00273                         case DIJOFS_SLIDER1(1):
00274                                 sliderMoved[1] = true;
00275                                 mState.mSliders[1].abY = diBuff[i].dwData;
00276                                 break;
00277                         case DIJOFS_SLIDER2(0):
00278                                 sliderMoved[2] = true;
00279                                 mState.mSliders[2].abX = diBuff[i].dwData;
00280                                 break;
00281                         case DIJOFS_SLIDER2(1):
00282                                 sliderMoved[2] = true;
00283                                 mState.mSliders[2].abY = diBuff[i].dwData;
00284                                 break;
00285                         case DIJOFS_SLIDER3(0):
00286                                 sliderMoved[3] = true;
00287                                 mState.mSliders[3].abX = diBuff[i].dwData;
00288                                 break;
00289                         case DIJOFS_SLIDER3(1):
00290                                 sliderMoved[3] = true;
00291                                 mState.mSliders[3].abY = diBuff[i].dwData;
00292                                 break;
00293                         //-----------------------------------------//
00294                         default:
00295                                 //Handle Button Events Easily using the DX Offset Macros
00296                                 if( diBuff[i].dwOfs >= DIJOFS_BUTTON(0) && diBuff[i].dwOfs <= DIJOFS_BUTTON(30) )
00297                                 {
00298                                         if(!_doButtonClick((diBuff[i].dwOfs - DIJOFS_BUTTON(0)), diBuff[i]))
00299                                                 return;
00300                                 }
00301                                 break;
00302                         } //end case
00303                 } //End else
00304         } //end for
00305 
00306         //Check to see if any of the axes values have changed.. if so send events
00307         if( mBuffered && listener && entries > 0 )
00308         {
00309                 JoyStickEvent temp(this, mState);
00310 
00311                 //Update axes
00312                 for( int i = 0; i < 24; ++i )
00313                         if( axisMoved[i] )
00314                                 if( listener->axisMoved( temp, i ) == false )
00315                                         return;
00316 
00317                 //Now update sliders
00318                 for( int i = 0; i < 4; ++i )
00319                         if( sliderMoved[i] )
00320                                 if( listener->sliderMoved( temp, i ) == false )
00321                                         return;
00322         }
00323 }
00324 
00325 //--------------------------------------------------------------------------------------------------//
00326 bool Win32JoyStick::_doButtonClick( int button, DIDEVICEOBJECTDATA& di )
00327 {
00328         if( di.dwData & 0x80 )
00329         {
00330                 mState.buttons |= 1 << button; //turn the bit flag on
00331                 if( mBuffered && listener )
00332                         return listener->buttonPressed( JoyStickEvent( this, mState ), button );
00333         }
00334         else
00335         {
00336                 mState.buttons &= ~(1 << button); //turn the bit flag off
00337                 if( mBuffered && listener )
00338                         return listener->buttonReleased( JoyStickEvent( this, mState ), button );
00339         }
00340 
00341         return true;
00342 }
00343 
00344 //--------------------------------------------------------------------------------------------------//
00345 bool Win32JoyStick::_changePOV( int pov, DIDEVICEOBJECTDATA& di )
00346 {
00347         //Some drivers report a value of 65,535, instead of —1,
00348         //for the center position
00349         if(LOWORD(di.dwData) == 0xFFFF)
00350         {
00351                 mState.mPOV[pov].direction = Pov::Centered;
00352         }
00353         else
00354         {
00355                 switch(di.dwData)
00356                 {
00357                         case 0: mState.mPOV[pov].direction = Pov::North; break;
00358                         case 4500: mState.mPOV[pov].direction = Pov::NorthEast; break;
00359                         case 9000: mState.mPOV[pov].direction = Pov::East; break;
00360                         case 13500: mState.mPOV[pov].direction = Pov::SouthEast; break;
00361                         case 18000: mState.mPOV[pov].direction = Pov::South; break;
00362                         case 22500: mState.mPOV[pov].direction = Pov::SouthWest; break;
00363                         case 27000: mState.mPOV[pov].direction = Pov::West; break;
00364                         case 31500: mState.mPOV[pov].direction = Pov::NorthWest; break;
00365                 }
00366         }
00367 
00368         if( mBuffered && listener )
00369                 return listener->povMoved( JoyStickEvent( this, mState ), pov );
00370 
00371         return true;
00372 }
00373 
00374 //--------------------------------------------------------------------------------------------------//
00375 void Win32JoyStick::setBuffered(bool buffered)
00376 {
00377         mBuffered = buffered;
00378 }
00379 
00380 //--------------------------------------------------------------------------------------------------//
00381 JoyStickInfo Win32JoyStick::_getJoyInfo()
00382 {
00383         JoyStickInfo js;
00384         js.deviceID = deviceGuid;
00385         js.devId = mDevID;
00386         js.vendor = mVendor;
00387 
00388         return js;
00389 }
00390 
00391 //--------------------------------------------------------------------------------------------------//
00392 Interface* Win32JoyStick::queryInterface(Interface::IType type)
00393 {
00394         //Thought about using covariant return type here.. however,
00395         //some devices may allow LED light changing, or other interface stuff
00396 
00397         if( ff_device && type == Interface::ForceFeedback )
00398                 return ff_device;
00399         else
00400                 return 0;
00401 }

Generated on Sat Dec 1 20:13:52 2007 for OIS by  doxygen 1.5.4