CmInput.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. }
  25. Input::~Input()
  26. {
  27. CM_DELETE_ARRAY(mHorizontalHistoryBuffer, float, HISTORY_BUFFER_SIZE, GenAlloc);
  28. CM_DELETE_ARRAY(mVerticalHistoryBuffer, float, HISTORY_BUFFER_SIZE, GenAlloc);
  29. CM_DELETE_ARRAY(mTimesHistoryBuffer, float, HISTORY_BUFFER_SIZE, GenAlloc);
  30. }
  31. void Input::initClipRect(Rect& clipRect)
  32. {
  33. mClipRect = clipRect;
  34. mUsingClipRect = (clipRect.width > 0 && clipRect.height > 0);
  35. }
  36. void Input::registerInputHandler(InputHandlerPtr inputHandler)
  37. {
  38. if(mInputHandler != inputHandler)
  39. {
  40. mInputHandler = inputHandler;
  41. if(mInputHandler != nullptr)
  42. {
  43. mInputHandler->onKeyDown.connect(boost::bind(&Input::keyDown, this, _1));
  44. mInputHandler->onKeyUp.connect(boost::bind(&Input::keyUp, this, _1));
  45. mInputHandler->onMouseMoved.connect(boost::bind(&Input::mouseMoved, this, _1));
  46. mInputHandler->onMouseDown.connect(boost::bind(&Input::mouseDown, this, _1, _2));
  47. mInputHandler->onMouseUp.connect(boost::bind(&Input::mouseUp, this, _1, _2));
  48. }
  49. }
  50. }
  51. void Input::update()
  52. {
  53. if(mInputHandler == nullptr)
  54. {
  55. LOGERR("Input handler not initialized!");
  56. return;
  57. }
  58. mInputHandler->update();
  59. updateSmoothInput();
  60. }
  61. void Input::keyDown(KeyCode keyCode)
  62. {
  63. onKeyDown(keyCode);
  64. }
  65. void Input::keyUp(KeyCode keyCode)
  66. {
  67. onKeyUp(keyCode);
  68. }
  69. void Input::mouseMoved(const MouseEvent& event)
  70. {
  71. if(mUsingClipRect)
  72. {
  73. if(!mClipRect.contains(event.coords))
  74. return;
  75. }
  76. onMouseMoved(event);
  77. mMouseLastRel = Int2(-event.relCoords.x, -event.relCoords.y);
  78. }
  79. void Input::mouseDown(const MouseEvent& event, MouseButton buttonID)
  80. {
  81. if(mUsingClipRect)
  82. {
  83. if(!mClipRect.contains(event.coords))
  84. return;
  85. }
  86. onMouseDown(event, buttonID);
  87. }
  88. void Input::mouseUp(const MouseEvent& event, MouseButton buttonID)
  89. {
  90. if(mUsingClipRect)
  91. {
  92. if(!mClipRect.contains(event.coords))
  93. return;
  94. }
  95. onMouseUp(event, buttonID);
  96. }
  97. float Input::getHorizontalAxis() const
  98. {
  99. return mSmoothHorizontalAxis;
  100. }
  101. float Input::getVerticalAxis() const
  102. {
  103. return mSmoothVerticalAxis;
  104. }
  105. void Input::updateSmoothInput()
  106. {
  107. float currentTime = gTime().getTime();
  108. mHorizontalHistoryBuffer[mCurrentBufferIdx] = (float)mMouseLastRel.x;
  109. mVerticalHistoryBuffer[mCurrentBufferIdx] = (float)mMouseLastRel.y;
  110. mTimesHistoryBuffer[mCurrentBufferIdx] = currentTime;
  111. int i = 0;
  112. int idx = mCurrentBufferIdx;
  113. float currentWeight = 1.0f;
  114. float horizontalTotal = 0.0f;
  115. float verticalTotal = 0.0f;
  116. while(i < HISTORY_BUFFER_SIZE)
  117. {
  118. float timeWeight = 1.0f - (currentTime - mTimesHistoryBuffer[idx]) * 10.0f;
  119. if(timeWeight < 0.0f)
  120. timeWeight = 0.0f;
  121. horizontalTotal += mHorizontalHistoryBuffer[idx] * currentWeight * timeWeight;
  122. verticalTotal += mVerticalHistoryBuffer[idx] * currentWeight * timeWeight;
  123. currentWeight *= WEIGHT_MODIFIER;
  124. idx = (idx + 1) % HISTORY_BUFFER_SIZE;
  125. i++;
  126. }
  127. mCurrentBufferIdx = (mCurrentBufferIdx + 1) % HISTORY_BUFFER_SIZE;
  128. mSmoothHorizontalAxis = Math::Clamp(horizontalTotal / HISTORY_BUFFER_SIZE, -1.0f, 1.0f);
  129. mSmoothVerticalAxis = Math::Clamp(verticalTotal / HISTORY_BUFFER_SIZE, -1.0f, 1.0f);
  130. mMouseLastRel = Int2(0, 0);
  131. }
  132. Input& gInput()
  133. {
  134. return Input::instance();
  135. }
  136. }