CmInput.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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. onKeyDown(keyCode);
  69. }
  70. void Input::keyUp(KeyCode keyCode)
  71. {
  72. mKeyState[keyCode] = false;
  73. onKeyUp(keyCode);
  74. }
  75. void Input::mouseMoved(const MouseEvent& event)
  76. {
  77. if(mUsingClipRect)
  78. {
  79. if(!mClipRect.contains(event.coords))
  80. return;
  81. }
  82. onMouseMoved(event);
  83. mMouseLastRel = Int2(-event.relCoords.x, -event.relCoords.y);
  84. }
  85. void Input::mouseDown(const MouseEvent& event, MouseButton buttonID)
  86. {
  87. if(mUsingClipRect)
  88. {
  89. if(!mClipRect.contains(event.coords))
  90. return;
  91. }
  92. mMouseButtonState[buttonID] = true;
  93. onMouseDown(event, buttonID);
  94. }
  95. void Input::mouseUp(const MouseEvent& event, MouseButton buttonID)
  96. {
  97. if(mUsingClipRect)
  98. {
  99. if(!mClipRect.contains(event.coords))
  100. return;
  101. }
  102. mMouseButtonState[buttonID] = false;
  103. onMouseUp(event, buttonID);
  104. }
  105. float Input::getHorizontalAxis() const
  106. {
  107. return mSmoothHorizontalAxis;
  108. }
  109. float Input::getVerticalAxis() const
  110. {
  111. return mSmoothVerticalAxis;
  112. }
  113. bool Input::isButtonDown(MouseButton button) const
  114. {
  115. return mMouseButtonState[button];
  116. }
  117. bool Input::isKeyDown(KeyCode keyCode) const
  118. {
  119. return mKeyState[keyCode];
  120. }
  121. void Input::updateSmoothInput()
  122. {
  123. float currentTime = gTime().getTime();
  124. mHorizontalHistoryBuffer[mCurrentBufferIdx] = (float)mMouseLastRel.x;
  125. mVerticalHistoryBuffer[mCurrentBufferIdx] = (float)mMouseLastRel.y;
  126. mTimesHistoryBuffer[mCurrentBufferIdx] = currentTime;
  127. int i = 0;
  128. int idx = mCurrentBufferIdx;
  129. float currentWeight = 1.0f;
  130. float horizontalTotal = 0.0f;
  131. float verticalTotal = 0.0f;
  132. while(i < HISTORY_BUFFER_SIZE)
  133. {
  134. float timeWeight = 1.0f - (currentTime - mTimesHistoryBuffer[idx]) * 10.0f;
  135. if(timeWeight < 0.0f)
  136. timeWeight = 0.0f;
  137. horizontalTotal += mHorizontalHistoryBuffer[idx] * currentWeight * timeWeight;
  138. verticalTotal += mVerticalHistoryBuffer[idx] * currentWeight * timeWeight;
  139. currentWeight *= WEIGHT_MODIFIER;
  140. idx = (idx + 1) % HISTORY_BUFFER_SIZE;
  141. i++;
  142. }
  143. mCurrentBufferIdx = (mCurrentBufferIdx + 1) % HISTORY_BUFFER_SIZE;
  144. mSmoothHorizontalAxis = Math::Clamp(horizontalTotal / HISTORY_BUFFER_SIZE, -1.0f, 1.0f);
  145. mSmoothVerticalAxis = Math::Clamp(verticalTotal / HISTORY_BUFFER_SIZE, -1.0f, 1.0f);
  146. mMouseLastRel = Int2(0, 0);
  147. }
  148. Input& gInput()
  149. {
  150. return Input::instance();
  151. }
  152. }