# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

di_mouse_device.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000-2002 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "stdmisc.h"
00027 
00028 #include "misc/di_mouse_device.h"
00029 #include "nel/misc/game_device_events.h"
00030 
00031 
00032 #ifdef NL_OS_WINDOWS
00033 
00034 #include <memory>
00035 #include <algorithm>
00036 
00037 
00038 
00039 
00040 namespace NLMISC
00041 {
00042 
00043 
00044 
00045 
00046 //======================================================
00047 CDIMouse::CDIMouse() : _MessageMode(RawMode),
00048                                            _MouseSpeed(1.0f),
00049                                            _Mouse(NULL),
00050                                            _XAcc(0),
00051                                            _YAcc(0),
00052                                            _XMousePos(0),
00053                                            _YMousePos(0),
00054                                            _LastMouseButtonClicked(-1),
00055                                            _DoubleClickDelay(300),
00056                                            _XFactor(1.f),
00057                                            _YFactor(1.f),
00058                                            OldDIXPos(0),
00059                                            OldDIYPos(0),
00060                                            OldDIZPos(0),
00061                                            _XRaw(0),
00062                                            _YRaw(0),
00063                                            _FirstX(true),
00064                                            _FirstY(true)
00065 
00066 {
00067         std::fill(_MouseButtons, _MouseButtons + MaxNumMouseButtons, 0);
00068         std::fill(_MouseAxisMode, _MouseAxisMode + NumMouseAxis, Raw);
00069         _MouseFrame.setWH(0, 0, 640, 480);      
00070 }
00071 
00072 //======================================================
00073 CDIMouse::~CDIMouse()
00074 {
00075         if (_Mouse)
00076         {
00077                 _Mouse->Unacquire();
00078                 _Mouse->Release();
00079         }
00080 }
00081 
00082 //======================================================
00083 void        CDIMouse::setMouseMode(TAxis axis, TAxisMode axisMode)
00084 {       
00085         nlassert(axisMode < AxisModeLast);
00086         nlassert(axis < AxisLast);
00087         _MouseAxisMode[axis] = axisMode;
00088         clampMouseAxis();
00089 }
00090 
00091 //======================================================
00092 CDIMouse::TAxisMode     CDIMouse::getMouseMode(TAxis axis) const
00093 {       
00094         nlassert(axis < NumMouseAxis);  
00095         return _MouseAxisMode[axis];
00096 }
00097 
00098 //======================================================
00099 void            CDIMouse::setMouseSpeed(float speed)
00100 {
00101         nlassert(_MessageMode == NormalMode);
00102         nlassert(speed > 0);
00103         _MouseSpeed = speed;
00104 }
00105 
00106 //======================================================
00107 bool    CDIMouse::setBufferSize(uint size)
00108 {
00109         nlassert(size > 0);
00110         nlassert(_Mouse);
00111         _Mouse->Unacquire();    
00112         DIPROPDWORD dipdw;
00113     dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
00114     dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
00115     dipdw.diph.dwObj        = 0;
00116     dipdw.diph.dwHow        = DIPH_DEVICE;
00117     dipdw.dwData            = size;
00118         HRESULT                                 r = _Mouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph );
00119         if (r != DI_OK) return false;
00120         _MouseBufferSize = size;
00121         return true;
00122 }
00123 
00124 //======================================================
00125 uint                            CDIMouse::getBufferSize() const { return _MouseBufferSize; }
00126 
00127 //======================================================
00128 void    CDIMouse::setMousePos(float x, float y)
00129 {       
00130         nlassert(_MessageMode == NormalMode);
00131         _XMousePos = (sint32) (x * (1 << 16));
00132         _YMousePos = (sint32) (y * (1 << 16));
00133 }
00134 
00135 //======================================================
00136 CDIMouse *CDIMouse::createMouseDevice(IDirectInput8 *di8, HWND hwnd, CDIEventEmitter *diEventEmitter) throw(EDirectInput)
00137 {
00138         std::auto_ptr<CDIMouse> mouse(new CDIMouse);
00139         mouse->_DIEventEmitter = diEventEmitter;
00140         HRESULT result = di8->CreateDevice(GUID_SysMouse, &(mouse->_Mouse), NULL);
00141         if (result != DI_OK) throw EDirectInputNoMouse();
00142         result = mouse->_Mouse->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE);
00143         if (result != DI_OK) throw EDirectInputCooperativeLevelFailed();
00144         mouse->_Mouse->SetDataFormat(&c_dfDIMouse2);    
00145         mouse->setBufferSize(64);
00146 
00147 
00150         DIPROPDWORD prop;
00151         prop.diph.dwSize = sizeof(DIPROPDWORD);
00152         prop.diph.dwHeaderSize = sizeof(DIPROPHEADER);
00153         prop.diph.dwHow = DIPH_DEVICE;
00154         prop.diph.dwObj = 0;
00155         prop.dwData = DIPROPAXISMODE_ABS;
00156         HRESULT r = mouse->_Mouse->SetProperty(DIPROP_AXISMODE, &prop.diph);
00157         nlassert(r == DI_OK); // should always succeed...
00158         //
00159         mouse->_Mouse->Acquire();       
00160         mouse->_hWnd = hwnd;
00161         return mouse.release();
00162 }
00163 
00164 //======================================================
00165 float                           CDIMouse::getMouseSpeed() const 
00166 {       
00167         nlassert(_MessageMode == NormalMode);
00168         return _MouseSpeed; 
00169 }
00170 
00171 //======================================================
00172 const CRect &CDIMouse::getMouseFrame() const 
00173 { 
00174         nlassert(_MessageMode == NormalMode);
00175         return _MouseFrame; 
00176 }
00177 
00178 //======================================================
00179 uint                            CDIMouse::getDoubleClickDelay() const { return _DoubleClickDelay; }
00180 
00181 //======================================================
00182 inline void     CDIMouse::clampMouseAxis()
00183 {
00184         if (_MouseAxisMode[XAxis] == Clamped) clamp(_XMousePos, (sint32) _MouseFrame.X  << 16, (sint32) (_MouseFrame.X + _MouseFrame.Width - 1) << 16);
00185         if (_MouseAxisMode[YAxis] == Clamped) clamp(_YMousePos, (sint32) _MouseFrame.Y << 16, (sint32) (_MouseFrame.X + _MouseFrame.Height - 1) << 16); 
00186 }
00187 
00188 //======================================================
00189 void CDIMouse::poll(CInputDeviceServer *dev)
00190 {
00191         nlassert(_Mouse);
00192         nlassert(_MouseBufferSize > 0);
00193         static std::vector<DIDEVICEOBJECTDATA> datas;
00194         datas.resize(_MouseBufferSize);
00195         DWORD numElements = _MouseBufferSize;   
00196         HRESULT result = _Mouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &datas[0], &numElements, 0);
00197         if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
00198         {               
00199                 result = _Mouse->Acquire();
00200                 HRESULT result = _Mouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &datas[0], &numElements, 0);
00201                 if (result != DI_OK) return;
00202         }
00203         else if (result != DI_OK) return;
00204                  
00205         if (::IsWindowEnabled(_hWnd) && ::IsWindowVisible(_hWnd))
00206         {
00207                 for(uint k = 0; k < numElements; ++k)
00208                 {
00209                         CDIEvent *die = new CDIEvent;
00210                         die->Emitter = this;
00211                         die->Datas = datas[k];
00212                         dev->submitEvent(die);
00213                 }
00214         }
00215 }
00216 
00217 
00218 //======================================================================
00219 TMouseButton CDIMouse::buildMouseButtonFlags() const
00220 {
00221         return (TMouseButton) (
00222                                                    _DIEventEmitter->buildKeyboardButtonFlags()
00223                                                    | (_MouseButtons[0] ? leftButton   : 0)
00224                                                    | (_MouseButtons[1] ? rightButton  : 0)
00225                                                    | (_MouseButtons[2] ? middleButton : 0)
00226                                                   );
00227 }
00228 
00229 //======================================================
00230 TMouseButton CDIMouse::buildMouseSingleButtonFlags(uint button)
00231 {
00232         static const TMouseButton mb[] = { leftButton, rightButton, middleButton };
00233         nlassert(button < MaxNumMouseButtons);
00234         return (TMouseButton) (_DIEventEmitter->buildKeyboardButtonFlags() | mb[button]);                                                                                                 
00235 }
00236 
00237 //======================================================
00238 void CDIMouse::onButtonClicked(uint button, CEventServer *server, uint32 date)
00239 {
00240         // check for double click
00241         if (_LastMouseButtonClicked == (sint) button)
00242         {
00243                 if (date - _MouseButtonsLastClickDate < _DoubleClickDelay)
00244                 {
00245                         CEventMouseDblClk *emdc 
00246                         = new CEventMouseDblClk((float) (_XMousePos >> 16),
00247                                                                                     (float) (_YMousePos >> 16),
00248                                                                                     buildMouseSingleButtonFlags(button),
00249                                                                                     _DIEventEmitter);
00250                         server->postEvent(emdc);
00251                         _LastMouseButtonClicked = -1;
00252                 }
00253                 else
00254                 {
00255                         _MouseButtonsLastClickDate = date;
00256                 }
00257         }
00258         else
00259         {
00260                 _LastMouseButtonClicked = button;
00261                 _MouseButtonsLastClickDate = date;
00262         }
00263 }
00264 
00265 //======================================================
00266 void CDIMouse::processButton(uint button, bool pressed, CEventServer *server, uint32 date)
00267 {
00268         updateMove(server);
00269         if (pressed)
00270         {
00271                 CEventMouseDown *emd = 
00272                 new CEventMouseDown((float) (_XMousePos >> 16),
00273                                                                     (float) (_YMousePos >> 16),
00274                                                                     buildMouseSingleButtonFlags(button),
00275                                                                     _DIEventEmitter);
00276                 server->postEvent(emd);
00277         }
00278         else
00279         {
00280                 CEventMouseUp *emu = 
00281                 new CEventMouseUp((float) (_XMousePos >> 16),
00282                                                                   (float) (_YMousePos >> 16),
00283                                                                   buildMouseSingleButtonFlags(button),
00284                                                                   _DIEventEmitter);
00285                 server->postEvent(emu);
00286                 onButtonClicked(button, server, date);
00287         }
00288         _MouseButtons[button] = pressed;
00289 }
00290 
00291 //======================================================
00292 void CDIMouse::submit(IInputDeviceEvent *deviceEvent, CEventServer *server)
00293 {
00294         CDIEvent *die = safe_cast<CDIEvent *>(deviceEvent);
00295         bool    pressed;
00296         switch(die->Datas.dwOfs)
00297         {
00298                 case    DIMOFS_X:
00299                 {
00300                         if (!_FirstX)
00301                         {
00302                                 sint dep = (sint32) die->Datas.dwData - OldDIXPos;                              
00303                                 _XAcc += dep;                           
00304                         }
00305                         else
00306                         {
00307                                 _FirstX = false;
00308                         }
00309                         OldDIXPos = (sint32) die->Datas.dwData;
00310                 }
00311                 break;
00312                 case    DIMOFS_Y:
00313                 {
00314                         if (!_FirstY)
00315                         {
00316                                 sint dep = (sint32) die->Datas.dwData - OldDIYPos;                              
00317                                 _YAcc -= dep;                           
00318                         }
00319                         else
00320                         {       
00321                                 _FirstY = false;
00322                         }
00323                         OldDIYPos = (sint32) die->Datas.dwData;
00324                 }
00325                 break;
00326                 case    DIMOFS_Z:
00327                 {
00328                         updateMove(server);
00329                         sint dep = die->Datas.dwData - OldDIZPos;
00330                         OldDIZPos = (sint32) die->Datas.dwData;
00331                         CEventMouseWheel *emw = 
00332                         new CEventMouseWheel((float) (_XMousePos >> 16),
00333                                                                                  (float) (_XMousePos >> 16),                                                                             
00334                                                                                  buildMouseButtonFlags(),
00335                                                                                  dep > 0,
00336                                                                                  _DIEventEmitter);
00337                         server->postEvent(emw);
00338                 }
00339                 break;
00340                 case    DIMOFS_BUTTON0: /* left button */                       
00341                         pressed = (die->Datas.dwData & 0x80) != 0;
00342                         processButton(0, pressed, server, die->Datas.dwTimeStamp);
00343                 break;
00344                 case    DIMOFS_BUTTON1: /* right button */
00345                         pressed = (die->Datas.dwData & 0x80) != 0;
00346                         processButton(1, pressed, server, die->Datas.dwTimeStamp);
00347                 break;
00348                 case    DIMOFS_BUTTON2: /* middle button */
00349                         pressed = (die->Datas.dwData & 0x80) != 0;
00350                         processButton(2, pressed, server, die->Datas.dwTimeStamp);
00351                 break;
00352                 default:
00353                         return;
00354                 break;
00355         }
00356 }
00357 
00358 //======================================================
00359 void    CDIMouse::updateMove(CEventServer *server)
00360 {
00361         if (_XAcc != 0 || _YAcc != 0)
00362         {
00363                 if (_MessageMode == NormalMode)
00364                 {
00365                         _XMousePos += (sint32) (_MouseSpeed * _XAcc * (1 << 16)); 
00366                         _YMousePos += (sint32) (_MouseSpeed * _YAcc * (1 << 16));                       
00367                         clampMouseAxis();
00368                         CEventMouseMove *emm = new CEventMouseMove(_XFactor * (float) (_XMousePos >> 16), _YFactor *(float) (_YMousePos >> 16), buildMouseButtonFlags(), _DIEventEmitter);
00369                         server->postEvent(emm);
00370                 }
00371                 else
00372                 {                       
00373                         _XRaw += _XAcc;
00374                         _YRaw += _YAcc;
00375                         CGDMouseMove *emm = new CGDMouseMove(_DIEventEmitter, this, _XRaw, _YRaw);
00376                         server->postEvent(emm);                 
00377                 }
00378                 _XAcc = _YAcc = 0;
00379         }
00380 }
00381 
00382 //======================================================
00383 void CDIMouse::transitionOccured(CEventServer *server, const IInputDeviceEvent *)
00384 {
00385         updateMove(server);     
00386 }
00387 
00388 //======================================================
00389 void    CDIMouse::setButton(uint button, bool pushed)
00390 {
00391         nlassert(button < MaxNumMouseButtons);
00392         _MouseButtons[button] = pushed;
00393 }
00394 
00395 //======================================================
00396 bool    CDIMouse::getButton(uint button) const
00397 {
00398         nlassert(button < MaxNumMouseButtons);
00399         return _MouseButtons[button];
00400 }
00401 
00402 //======================================================
00403 void    CDIMouse::setDoubleClickDelay(uint ms)
00404 {
00405         nlassert(ms > 0);
00406         _DoubleClickDelay = ms;
00407 }
00408 
00409 //======================================================
00410 void    CDIMouse::setMouseFrame(const CRect &rect)
00411 {
00412         nlassert(_MessageMode == NormalMode);
00413         _MouseFrame = rect;
00414 }
00415 
00416 //======================================================
00417 void    CDIMouse::setMessagesMode(TMessageMode mode)
00418 { 
00419         nlassert(mode < AxisModeLast); 
00420         _MessageMode = mode;    
00421         if (mode == RawMode)
00422         {
00423                 _FirstX = _FirstY = false;
00424         }       
00425 }
00426 
00427 
00428 } // NLMISC
00429 
00430 #endif // NL_OS_WINDOWS
00431 
00432