00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
00099 _enumerate();
00100
00101 mState.clear();
00102
00103 capture();
00104 }
00105
00106
00107 void Win32JoyStick::_enumerate()
00108 {
00109
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
00121 _AxisNumber = 0;
00122
00123
00124 mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL);
00125
00126
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
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
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
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
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
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
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
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
00204 mJoyStick->Poll();
00205 hr = mJoyStick->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
00206
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
00216 for(unsigned int i = 0; i < entries; ++i)
00217 {
00218
00219 if( diBuff[i].uAppData != 0xFFFFFFFF && diBuff[i].uAppData > 0 )
00220 {
00221 int axis = 0x7FFFFFFF & diBuff[i].uAppData;
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
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
00240
00241 switch(diBuff[i].dwOfs)
00242 {
00243
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
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
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 }
00303 }
00304 }
00305
00306
00307 if( mBuffered && listener && entries > 0 )
00308 {
00309 JoyStickEvent temp(this, mState);
00310
00311
00312 for( int i = 0; i < 24; ++i )
00313 if( axisMoved[i] )
00314 if( listener->axisMoved( temp, i ) == false )
00315 return;
00316
00317
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;
00331 if( mBuffered && listener )
00332 return listener->buttonPressed( JoyStickEvent( this, mState ), button );
00333 }
00334 else
00335 {
00336 mState.buttons &= ~(1 << button);
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
00348
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
00395
00396
00397 if( ff_device && type == Interface::ForceFeedback )
00398 return ff_device;
00399 else
00400 return 0;
00401 }