CmInput.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #include "CmInput.h"
  2. #include "CmTime.h"
  3. #include "CmMath.h"
  4. #include "CmRect.h"
  5. #include "CmDebug.h"
  6. #include <boost/bind.hpp>
  7. namespace CamelotFramework
  8. {
  9. const int Input::HISTORY_BUFFER_SIZE = 10; // Size of buffer used for input smoothing
  10. const float Input::WEIGHT_MODIFIER = 0.5f;
  11. Input::Input()
  12. :mSmoothHorizontalAxis(0.0f), mSmoothVerticalAxis(0.0f), mCurrentBufferIdx(0), mMouseLastRel(0, 0),
  13. mUsingClipRect(false), mClipRect(0, 0, 0, 0), mInputHandler(nullptr)
  14. {
  15. mHorizontalHistoryBuffer = CM_NEW_ARRAY(float, HISTORY_BUFFER_SIZE, GenAlloc);
  16. mVerticalHistoryBuffer = CM_NEW_ARRAY(float, HISTORY_BUFFER_SIZE, GenAlloc);
  17. mTimesHistoryBuffer = CM_NEW_ARRAY(float, HISTORY_BUFFER_SIZE, GenAlloc);
  18. for(int i = 0; i < HISTORY_BUFFER_SIZE; i++)
  19. {
  20. mHorizontalHistoryBuffer[i] = 0.0f;
  21. mVerticalHistoryBuffer[i] = 0.0f;
  22. mTimesHistoryBuffer[i] = 0.0f;
  23. }
  24. for(int i = 0; i < MB_Count; i++)
  25. mMouseButtonState[i] = false;
  26. for(int i = 0; i < KC_Count; i++)
  27. mKeyState[i] = false;
  28. }
  29. Input::~Input()
  30. {
  31. CM_DELETE_ARRAY(mHorizontalHistoryBuffer, float, HISTORY_BUFFER_SIZE, GenAlloc);
  32. CM_DELETE_ARRAY(mVerticalHistoryBuffer, float, HISTORY_BUFFER_SIZE, GenAlloc);
  33. CM_DELETE_ARRAY(mTimesHistoryBuffer, float, HISTORY_BUFFER_SIZE, GenAlloc);
  34. }
  35. void Input::initClipRect(Rect& clipRect)
  36. {
  37. mClipRect = clipRect;
  38. mUsingClipRect = (clipRect.width > 0 && clipRect.height > 0);
  39. }
  40. void Input::registerInputHandler(InputHandlerPtr inputHandler)
  41. {
  42. if(mInputHandler != inputHandler)
  43. {
  44. mInputHandler = inputHandler;
  45. if(mInputHandler != nullptr)
  46. {
  47. mInputHandler->onKeyDown.connect(boost::bind(&Input::keyDown, this, _1));
  48. mInputHandler->onKeyUp.connect(boost::bind(&Input::keyUp, this, _1));
  49. mInputHandler->onMouseMoved.connect(boost::bind(&Input::mouseMoved, this, _1));
  50. mInputHandler->onMouseDown.connect(boost::bind(&Input::mouseDown, this, _1, _2));
  51. mInputHandler->onMouseUp.connect(boost::bind(&Input::mouseUp, this, _1, _2));
  52. }
  53. }
  54. }
  55. void Input::update()
  56. {
  57. if(mInputHandler == nullptr)
  58. {
  59. LOGERR("Input handler not initialized!");
  60. return;
  61. }
  62. mInputHandler->update();
  63. updateSmoothInput();
  64. }
  65. void Input::keyDown(KeyCode keyCode)
  66. {
  67. mKeyState[keyCode] = true;
  68. }
  69. void Input::keyUp(KeyCode keyCode)
  70. {
  71. mKeyState[keyCode] = false;
  72. }
  73. void Input::mouseMoved(const MouseEvent& event)
  74. {
  75. if(mUsingClipRect)
  76. {
  77. if(!mClipRect.contains(event.coords))
  78. return;
  79. }
  80. mMouseLastRel = Int2(-event.relCoords.x, -event.relCoords.y);
  81. }
  82. void Input::mouseDown(const MouseEvent& event, MouseButton buttonID)
  83. {
  84. if(mUsingClipRect)
  85. {
  86. if(!mClipRect.contains(event.coords))
  87. return;
  88. }
  89. mMouseButtonState[buttonID] = true;
  90. }
  91. void Input::mouseUp(const MouseEvent& event, MouseButton buttonID)
  92. {
  93. if(mUsingClipRect)
  94. {
  95. if(!mClipRect.contains(event.coords))
  96. return;
  97. }
  98. mMouseButtonState[buttonID] = false;
  99. }
  100. float Input::getHorizontalAxis() const
  101. {
  102. return mSmoothHorizontalAxis;
  103. }
  104. float Input::getVerticalAxis() const
  105. {
  106. return mSmoothVerticalAxis;
  107. }
  108. bool Input::isButtonDown(MouseButton button) const
  109. {
  110. return mMouseButtonState[button];
  111. }
  112. bool Input::isKeyDown(KeyCode keyCode) const
  113. {
  114. return mKeyState[keyCode];
  115. }
  116. void Input::updateSmoothInput()
  117. {
  118. float currentTime = gTime().getTime();
  119. mHorizontalHistoryBuffer[mCurrentBufferIdx] = (float)mMouseLastRel.x;
  120. mVerticalHistoryBuffer[mCurrentBufferIdx] = (float)mMouseLastRel.y;
  121. mTimesHistoryBuffer[mCurrentBufferIdx] = currentTime;
  122. int i = 0;
  123. int idx = mCurrentBufferIdx;
  124. float currentWeight = 1.0f;
  125. float horizontalTotal = 0.0f;
  126. float verticalTotal = 0.0f;
  127. while(i < HISTORY_BUFFER_SIZE)
  128. {
  129. float timeWeight = 1.0f - (currentTime - mTimesHistoryBuffer[idx]) * 10.0f;
  130. if(timeWeight < 0.0f)
  131. timeWeight = 0.0f;
  132. horizontalTotal += mHorizontalHistoryBuffer[idx] * currentWeight * timeWeight;
  133. verticalTotal += mVerticalHistoryBuffer[idx] * currentWeight * timeWeight;
  134. currentWeight *= WEIGHT_MODIFIER;
  135. idx = (idx + 1) % HISTORY_BUFFER_SIZE;
  136. i++;
  137. }
  138. mCurrentBufferIdx = (mCurrentBufferIdx + 1) % HISTORY_BUFFER_SIZE;
  139. mSmoothHorizontalAxis = Math::Clamp(horizontalTotal / HISTORY_BUFFER_SIZE, -1.0f, 1.0f);
  140. mSmoothVerticalAxis = Math::Clamp(verticalTotal / HISTORY_BUFFER_SIZE, -1.0f, 1.0f);
  141. mMouseLastRel = Int2(0, 0);
  142. }
  143. Input& gInput()
  144. {
  145. return Input::instance();
  146. }
  147. }