"L. Spiro Engine"
|
00001 00016 #ifndef __LSE_MOUSE_H__ 00017 #define __LSE_MOUSE_H__ 00018 00019 #include "../LSEEngine.h" 00020 #include "Vector/LSMVector2.h" 00021 00022 00023 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00024 // MACROS 00025 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00026 // Number of buttons on a mouse. Change it to support as many as you want (but you will 00027 // also have to make a way to send clicks to the extra slots). 00028 #define __LSE_MOUSE_BUTTONS__ 3 00029 // Number of history items in the mouse-smoothening array. 00030 #define __LSE_MOUSE_SMOOTH_HISTORY__ 50 00031 00032 namespace lse { 00033 00039 class CMouse { 00040 public : 00041 // == Various constructors. 00042 LSE_INLINE LSE_CALL CMouse(); 00043 00044 00045 // == Functions. 00051 const CVector2 & LSE_CALL GetPos() const; 00052 00058 const CVector2 & LSE_CALL GetLastPos() const; 00059 00065 CVector2 LSE_CALL GetDelta() const; 00066 00072 LSREAL LSE_CALL GetXDelta() const; 00073 00079 LSREAL LSE_CALL GetYDelta() const; 00080 00086 const CVector2 & LSE_CALL GetInterpPos() const; 00087 00093 const CVector2 & LSE_CALL GetInterpLastPos() const; 00094 00100 CVector2 LSE_CALL GetInterpDelta() const; 00101 00107 LSREAL LSE_CALL GetInterpXDelta() const; 00108 00114 LSREAL LSE_CALL GetInterpYDelta() const; 00115 00116 00124 LSVOID LSE_CALL SetPos( LSREAL _fX, LSREAL _fY ); 00125 00133 LSVOID LSE_CALL AddPos( LSREAL _fX, LSREAL _fY ); 00134 00141 LSVOID LSE_CALL ApplyChanges( LSUINT64 _ui64TimeStamp ); 00142 00150 LSVOID LSE_CALL SetStartPos( LSREAL _fX, LSREAL _fY ); 00151 00160 LSVOID LSE_CALL Snap( LSREAL _fX, LSREAL _fY, LSREAL _fRight, LSREAL _fBottom ); 00161 00167 LSVOID LSE_CALL Click( LSUINT32 _ui32Index ); 00168 00174 LSVOID LSE_CALL UnClick( LSUINT32 _ui32Index ); 00175 00182 LSBOOL LSE_CALL IsMouseButtonDown( LSUINT32 _ui32Index ) const; 00183 00190 LSBOOL LSE_CALL MouseButtonJustPressed( LSUINT32 _ui32Index ) const; 00191 00198 LSBOOL LSE_CALL MouseButtonJustReleased( LSUINT32 _ui32Index ) const; 00199 00204 LSVOID LSE_CALL ResetClicks(); 00205 00211 const LSINT16 * LSE_CALL GetIndexMap() const; 00212 00213 00214 protected : 00215 // == Types. 00221 struct LSE_MOUSE_MOVE_POS { 00225 CVector2 vPos; 00226 00230 LSUINT64 ui64Time; 00231 }; 00232 00233 00234 // == Members. 00238 CVector2 m_vPos; 00239 00243 CVector2 m_vTempPos; 00244 00248 CVector2 m_vLastPos; 00249 00253 CVector2 m_vInterpPos; 00254 00258 CVector2 m_vLastInterpPos; 00259 00263 LSE_MOUSE_MOVE_POS m_mmpHistory[__LSE_MOUSE_SMOOTH_HISTORY__]; 00264 00268 LSUINT32 m_ui32HistorySize : 30; 00269 00273 LSUINT32 m_ui32UpdateMoveBuffer : 2; 00274 00291 LSUINT32 m_ui32InterpTime; 00292 00296 LSUINT64 m_ui64TimeNow; 00297 00308 LSINT32 m_i32ClickCountBuffer[__LSE_MOUSE_BUTTONS__]; 00309 LSINT32 m_i32ClickCount[__LSE_MOUSE_BUTTONS__]; 00310 00317 LSINT32 m_i32UnClickCount[__LSE_MOUSE_BUTTONS__]; 00318 00319 // States of each button at the last update. 00320 LSINT32 m_i32LastClickState[__LSE_MOUSE_BUTTONS__]; 00321 00322 // Input mapping. The source index is the index into this array. 00323 // the destination index is the value at that index. Defaults 00324 // to a one-to-one mapping where the source and destination 00325 // values are the same. 00326 LSINT16 m_i16IndexMap[__LSE_MOUSE_BUTTONS__]; 00327 00328 00329 // == Functions. 00335 LSUINT64 LSE_CALL GetMostRecentHistoryTime() const; 00336 00345 LSUINT32 LSE_CALL FindTimeStampByTime( LSUINT64 _ui64Time ) const; 00346 00353 CVector2 LSE_CALL GetInterpolatedPos() const; 00354 }; 00355 00356 00357 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00358 // DEFINITIONS 00359 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00360 // == Various constructors. 00361 LSE_INLINE LSE_CALL CMouse::CMouse() : 00362 m_ui32HistorySize( 0 ), 00363 m_ui32UpdateMoveBuffer( 0 ), 00364 m_ui32InterpTime( 8000 ), 00365 m_ui64TimeNow( 0ULL ) { 00366 for ( LSUINT32 I = 0; I < LSE_ELEMENTS( m_i32ClickCount ); ++I ) { 00367 m_i32ClickCountBuffer[I] = m_i32ClickCount[I] = m_i32UnClickCount[I] = m_i32LastClickState[I] = 0; 00368 m_i16IndexMap[I] = static_cast<LSINT16>(I); 00369 } 00370 } 00371 00372 // == Functions. 00378 LSE_INLINE const CVector2 & LSE_CALL CMouse::GetPos() const { 00379 return m_vPos; 00380 } 00381 00387 LSE_INLINE const CVector2 & LSE_CALL CMouse::GetLastPos() const { 00388 return m_vLastPos; 00389 } 00390 00396 LSE_INLINE CVector2 LSE_CALL CMouse::GetDelta() const { 00397 return CVector2( m_vPos.x - m_vLastPos.x, m_vPos.y - m_vLastPos.y ); 00398 } 00399 00405 LSE_INLINE LSREAL LSE_CALL CMouse::GetXDelta() const { 00406 return m_vPos.x - m_vLastPos.x; 00407 } 00408 00414 LSE_INLINE LSREAL LSE_CALL CMouse::GetYDelta() const { 00415 return m_vPos.y - m_vLastPos.y; 00416 } 00417 00423 LSE_INLINE const CVector2 & LSE_CALL CMouse::GetInterpPos() const { 00424 return m_vInterpPos; 00425 } 00426 00432 LSE_INLINE const CVector2 & LSE_CALL CMouse::GetInterpLastPos() const { 00433 return m_vLastInterpPos; 00434 } 00435 00441 LSE_INLINE CVector2 LSE_CALL CMouse::GetInterpDelta() const { 00442 return m_vInterpPos - m_vLastInterpPos; 00443 } 00444 00450 LSE_INLINE LSREAL LSE_CALL CMouse::GetInterpXDelta() const { 00451 return m_vInterpPos.x - m_vLastInterpPos.x; 00452 } 00453 00459 LSE_INLINE LSREAL LSE_CALL CMouse::GetInterpYDelta() const { 00460 return m_vInterpPos.y - m_vLastInterpPos.y; 00461 } 00462 00469 LSE_INLINE LSBOOL LSE_CALL CMouse::IsMouseButtonDown( LSUINT32 _ui32Index ) const { 00470 assert( _ui32Index < __LSE_MOUSE_BUTTONS__ ); 00471 return m_i32ClickCount[_ui32Index] != 0; 00472 } 00473 00480 LSE_INLINE LSBOOL LSE_CALL CMouse::MouseButtonJustPressed( LSUINT32 _ui32Index ) const { 00481 assert( _ui32Index < __LSE_MOUSE_BUTTONS__ ); 00482 return m_i32ClickCount[_ui32Index] > m_i32LastClickState[_ui32Index]; 00483 } 00484 00491 LSE_INLINE LSBOOL LSE_CALL CMouse::MouseButtonJustReleased( LSUINT32 _ui32Index ) const { 00492 assert( _ui32Index < __LSE_MOUSE_BUTTONS__ ); 00493 return m_i32ClickCount[_ui32Index] < m_i32LastClickState[_ui32Index]; 00494 } 00495 00500 LSE_INLINE LSVOID LSE_CALL CMouse::ResetClicks() { 00501 // Actually we set the unclick count to a number absurdly high so that the mouse buttons 00502 // are guaranteed to be unclicked fully on the next update. 00503 // We cannot set it too high, however, as we would risk overflow if another unclick 00504 // event occurred before the next update. 00505 // This is why we clip both the click and unclick values to 0x0FFFFFFF. 00506 for ( LSUINT32 I = 0; I < LSE_ELEMENTS( m_i32ClickCount ); ++I ) { 00507 m_i32UnClickCount[I] = 0x0FFFFFFF; 00508 } 00509 } 00510 00516 LSE_INLINE const LSINT16 * LSE_CALL CMouse::GetIndexMap() const { return m_i16IndexMap; } 00517 00523 LSE_INLINE LSUINT64 LSE_CALL CMouse::GetMostRecentHistoryTime() const { 00524 if ( m_ui32HistorySize == 0 ) { 00525 // No history. 00526 return 0ULL; 00527 } 00528 return m_mmpHistory[m_ui32HistorySize-1].ui64Time; 00529 } 00530 00539 LSE_INLINE LSUINT32 LSE_CALL CMouse::FindTimeStampByTime( LSUINT64 _ui64Time ) const { 00540 for ( LSUINT32 I = 0; I < m_ui32HistorySize; ++I ) { 00541 if ( m_mmpHistory[I].ui64Time >= _ui64Time ) { 00542 return I; 00543 } 00544 } 00545 return __LSE_MOUSE_SMOOTH_HISTORY__; 00546 } 00547 00554 LSE_INLINE CVector2 LSE_CALL CMouse::GetInterpolatedPos() const { 00555 if ( m_ui32HistorySize == 0 ) { 00556 // No history. 00557 return m_vPos; 00558 } 00559 00560 LSUINT32 ui32Index = FindTimeStampByTime( m_ui64TimeNow - m_ui32InterpTime ); 00561 // If none found, we are at the end of the history. 00562 if ( ui32Index == __LSE_MOUSE_SMOOTH_HISTORY__ ) { 00563 return m_vPos; 00564 } 00565 if ( ui32Index == 0 ) { 00566 // No history item prior to this for interpolating between. 00567 return m_mmpHistory[ui32Index].vPos; 00568 } 00569 00570 // Now we have positions on both sides of our delayed timestamp, so 00571 // we can interpolate between them. 00572 LSUINT32 ui32DistanceBetweenPos = static_cast<LSUINT32>(m_mmpHistory[ui32Index].ui64Time - m_mmpHistory[ui32Index-1].ui64Time); 00573 LSUINT32 ui32DistanceBetweenCurTime = static_cast<LSUINT32>((m_ui64TimeNow - m_ui32InterpTime) - m_mmpHistory[ui32Index-1].ui64Time); 00574 LSREAL fFrac = static_cast<LSREAL>(ui32DistanceBetweenCurTime >> 2UL) / static_cast<LSREAL>(ui32DistanceBetweenPos >> 2UL); 00575 00576 CVector2 vInterp = m_mmpHistory[ui32Index].vPos - m_mmpHistory[ui32Index-1].vPos; 00577 return m_mmpHistory[ui32Index-1].vPos + (vInterp * fFrac); 00578 } 00579 00580 } // namespace lse 00581 00582 #endif // __LSE_MOUSE_H__