00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "stdmisc.h"
00028
00029 #include "nel/misc/di_event_emitter.h"
00030 #include "nel/misc/events.h"
00031 #include "nel/misc/win_event_emitter.h"
00032
00033 #include "misc/di_mouse_device.h"
00034 #include "misc/di_keyboard_device.h"
00035 #include "misc/di_game_device.h"
00036
00037 #include <memory>
00038 #include <algorithm>
00039
00040 #ifdef NL_OS_WINDOWS
00041
00042
00043
00044 namespace NLMISC
00045 {
00046
00047 #ifdef NL_DEBUG
00048 static const char DirectInputLibName[] = "dinput8.dll";
00049 #else
00050 static const char DirectInputLibName[] = "dinput8d.dll";
00051 #endif
00052
00053
00055
00057
00058 HMODULE CDIEventEmitter::_DirectInputLibHandle = 0;
00059 CDIEventEmitter::TPDirectInput8Create CDIEventEmitter::_PDirectInput8Create = NULL;
00060 uint CDIEventEmitter::_NumCreatedInterfaces = 0;
00061
00064
00066
00068
00069
00070
00071 CDIEventEmitter::CDIEventEmitter(HWND hwnd, CWinEventEmitter *we)
00072 :
00073 _hWnd(hwnd),
00074 _WE(we),
00075 _DInput8(NULL),
00076 _Keyboard(NULL),
00077 _Mouse(NULL),
00078 _ButtonsFlags(noButton)
00079 {
00080 }
00081
00082 CDIEventEmitter::~CDIEventEmitter()
00083 {
00084 releaseMouse();
00085 releaseKeyboard();
00086
00087 while (_DeviceServer.getNumDevices() != 0)
00088 {
00089 IInputDevice *dev = _DeviceServer.getDevice(0);
00090 _DeviceServer.removeDevice(dev);
00091 delete dev;
00092 }
00093 if (_DInput8) _DInput8->Release();
00094 -- _NumCreatedInterfaces;
00095 if (_NumCreatedInterfaces == 0) unloadLib();
00096 }
00097
00098
00099 CDIEventEmitter *CDIEventEmitter::create(HINSTANCE hinst, HWND hwnd, CWinEventEmitter *we) throw(EDirectInput)
00100 {
00101 if (!loadLib()) throw EDirectInputLibNotFound();
00102 std::auto_ptr<CDIEventEmitter> dxee(new CDIEventEmitter(hwnd, we));
00103 HRESULT result = _PDirectInput8Create(hinst,
00104 DIRECTINPUT_VERSION,
00105 IID_IDirectInput8A,
00106 (void **) &dxee->_DInput8,
00107 NULL);
00108 if (result != DI_OK) throw EDirectInputInitFailed();
00109
00110
00111 ++_NumCreatedInterfaces;
00112 return dxee.release();
00113 }
00114
00115
00116
00117 bool CDIEventEmitter::loadLib()
00118 {
00119 if (_DirectInputLibHandle != 0) return true;
00120 HMODULE handle = ::LoadLibrary(DirectInputLibName);
00121 if (handle == 0) return false;
00122
00123 TPDirectInput8Create cf = (TPDirectInput8Create) ::GetProcAddress(handle, "DirectInput8Create");
00124 if (!cf)
00125 {
00126 ::FreeLibrary(handle);
00127 return false;
00128 }
00129
00130 _DirectInputLibHandle = handle;
00131 _PDirectInput8Create = cf;
00132 return true;
00133 }
00134
00135
00136
00137 void CDIEventEmitter::unloadLib()
00138 {
00139 nlassert(_DirectInputLibHandle != 0);
00140 ::FreeLibrary(_DirectInputLibHandle);
00141 _DirectInputLibHandle = 0;
00142 _PDirectInput8Create = NULL;
00143 }
00144
00145
00146 void CDIEventEmitter::poll(CEventServer *server)
00147 {
00148 if (_WE) _ButtonsFlags = _WE->buildFlags();
00149 if (!server)
00150 server=&_InternalServer;
00151 _DeviceServer.poll(server);
00152 }
00153
00154
00155
00156 TMouseButton CDIEventEmitter::buildButtonsFlags() const
00157 {
00158 uint mouseFlags;
00159 uint keybFlags;
00160
00161 if (_Mouse)
00162 {
00163 mouseFlags = (_Mouse->getButton(0) ? leftButton : 0)
00164 | (_Mouse->getButton(1) ? rightButton : 0)
00165 | (_Mouse->getButton(2) ? middleButton : 0);
00166 }
00167 else
00168 {
00169 mouseFlags = _ButtonsFlags & (leftButton | rightButton | middleButton);
00170 }
00171
00172 if (_Keyboard)
00173 {
00174 keybFlags = (_Keyboard->ShiftPressed ? shiftButton : 0)
00175 | (_Keyboard->AltPressed ? altButton : 0)
00176 | (_Keyboard->CtrlPressed ? ctrlButton : 0);
00177 }
00178 else
00179 {
00180 keybFlags = _ButtonsFlags & (shiftButton | altButton | ctrlButton);
00181 }
00182 return (TMouseButton) (keybFlags | mouseFlags);
00183 }
00184
00185
00186 IMouseDevice *CDIEventEmitter::getMouseDevice() throw(EInputDevice)
00187 {
00188 if (_Mouse) return _Mouse;
00189 try
00190 {
00191
00192 std::auto_ptr<CDIMouse> mouse(CDIMouse::createMouseDevice(_DInput8, _hWnd, this));
00193
00194 _DeviceServer.registerDevice(mouse.get());
00195 _Mouse = mouse.get();
00196 if (_WE) _WE->enableMouseEvents(false);
00197 return mouse.release();
00198 }
00199 catch (...)
00200 {
00201 if (_WE) _WE->enableMouseEvents(true);
00202 throw;
00203 }
00204 }
00205
00206
00207 void CDIEventEmitter::releaseMouse()
00208 {
00209 if (!_Mouse) return;
00210
00211 if (_WE)
00212 {
00213 _WE->resetButtonFlagState();
00214 _WE->enableMouseEvents(true);
00215 }
00216
00217 _DeviceServer.removeDevice(_Mouse);
00218 delete _Mouse;
00219 _Mouse = NULL;
00220 }
00221
00222
00223 IKeyboardDevice *CDIEventEmitter::getKeyboardDevice() throw(EInputDevice)
00224 {
00225 if (_Keyboard) return _Keyboard;
00226
00227 std::auto_ptr<CDIKeyboard> keyboard(CDIKeyboard::createKeyboardDevice(_DInput8, _hWnd, this, _WE));
00228
00229 _DeviceServer.registerDevice(keyboard.get());
00230 _Keyboard = keyboard.get();
00231 return keyboard.release();
00232 }
00233
00234
00235 void CDIEventEmitter::releaseKeyboard()
00236 {
00237 if (!_Keyboard) return;
00238
00239 if (_WE) _WE->resetButtonFlagState();
00240
00241 _DeviceServer.removeDevice(_Keyboard);
00242 delete _Keyboard;
00243 _Keyboard = NULL;
00244 }
00245
00246
00247
00248 void CDIEventEmitter::submitEvents(CEventServer &server)
00249 {
00250 _InternalServer.setServer(&server);
00251 _InternalServer.pump();
00252 }
00253
00254
00256
00257 (
00258 LPCDIDEVICEINSTANCE lpddi,
00259 LPVOID pvRef
00260 )
00261 {
00262 CGameDeviceDesc desc;
00263 desc.InstanceName = lpddi->tszInstanceName;
00264 desc.ProductName = lpddi->tszProductName;
00265 switch (lpddi->wUsage & 0xff)
00266 {
00267 case DI8DEVTYPE_JOYSTICK: desc.DevType = CGameDeviceDesc::Joystick; break;
00268 case DI8DEVTYPE_GAMEPAD: desc.DevType = CGameDeviceDesc::GamePad; break;
00269 default: desc.DevType = CGameDeviceDesc::DontKnow; break;
00270 }
00271 TDeviceDescVect *dv = (TDeviceDescVect *) pvRef;
00272 dv->push_back(desc);
00273 return DIENUM_CONTINUE;
00274 }
00275
00276
00277
00279
00280 (
00281 LPCDIDEVICEINSTANCE lpddi,
00282 LPVOID pvRef
00283 )
00284 {
00285 std::vector<GUID> *gv = (std::vector<GUID> *) pvRef;
00286 gv->push_back(lpddi->guidInstance);
00287 return DIENUM_CONTINUE;
00288 }
00289
00290
00291
00292 void CDIEventEmitter::enumerateGameDevice(TDeviceDescVect &descs) throw(EInputDevice)
00293 {
00294 uint k;
00295 nlassert(_DInput8);
00296 descs.clear();
00297
00298 _DInput8->EnumDevices(DI8DEVCLASS_GAMECTRL, &DIEnumDevicesDescCallback, (LPVOID) &descs, DIEDFL_ALLDEVICES);
00299 for (k = 0; k < descs.size(); ++k) descs[k].Connected = false;
00300
00301 static TDeviceDescVect connecteds;
00302 _DInput8->EnumDevices(DI8DEVCLASS_GAMECTRL, &DIEnumDevicesDescCallback, (LPVOID) &connecteds, DIEDFL_ATTACHEDONLY);
00303
00304 for (k = 0; k < connecteds.size(); ++k)
00305 {
00306 TDeviceDescVect::iterator it = std::find(descs.begin(), descs.end(), connecteds[k]);
00307 it->Connected = true;
00308 }
00309 }
00310
00311
00312 IGameDevice *CDIEventEmitter::createGameDevice(const std::string &instanceName) throw(EInputDevice)
00313 {
00314 static TDeviceDescVect deviceDescs;
00315 static std::vector<GUID> deviceGUID;
00316
00317 nlassert(_DInput8);
00318 enumerateGameDevice(deviceDescs);
00319
00320 deviceGUID.clear();
00321 HRESULT r = _DInput8->EnumDevices(DI8DEVCLASS_GAMECTRL, &DIEnumDevicesGUIDCallback, (LPVOID) &deviceGUID, DIEDFL_ALLDEVICES);
00322 nlassert(r == DI_OK);
00323 nlassert(deviceDescs.size() == deviceGUID.size());
00324
00325
00326 for (uint k = 0; k < deviceDescs.size(); ++k)
00327 {
00328 if (deviceDescs[k].InstanceName == instanceName)
00329 {
00330 std::auto_ptr<CDIGameDevice> gd(CDIGameDevice::createGameDevice(_DInput8, _hWnd, this, deviceDescs[k], deviceGUID[k]));
00331
00332 _DeviceServer.registerDevice(gd.get());
00333 return gd.release();
00334 }
00335 }
00336 return NULL;
00337 }
00338
00339
00340 void CDIEventEmitter::releaseGameDevice(IGameDevice *gd)
00341 {
00342 nlassert(gd);
00343 CDIGameDevice *digd = safe_cast<CDIGameDevice *>(gd);
00344 _DeviceServer.removeDevice(digd);
00345 delete gd;
00346 }
00347
00348
00349 }
00350
00351 #endif // NL_OS_WINDOWS