CmInput.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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), mRawInputHandler(nullptr)
  13. {
  14. mHorizontalHistoryBuffer = cm_newN<float>(HISTORY_BUFFER_SIZE);
  15. mVerticalHistoryBuffer = cm_newN<float>(HISTORY_BUFFER_SIZE);
  16. mTimesHistoryBuffer = cm_newN<float>(HISTORY_BUFFER_SIZE);
  17. for(int i = 0; i < HISTORY_BUFFER_SIZE; i++)
  18. {
  19. mHorizontalHistoryBuffer[i] = 0.0f;
  20. mVerticalHistoryBuffer[i] = 0.0f;
  21. mTimesHistoryBuffer[i] = 0.0f;
  22. }
  23. for(int i = 0; i < BC_Count; i++)
  24. mKeyState[i] = false;
  25. mOSInputHandler = cm_shared_ptr<OSInputHandler>();
  26. mOSInputHandler->onCharInput.connect(boost::bind(&Input::charInput, this, _1));
  27. mOSInputHandler->onMouseMoved.connect(boost::bind(&Input::mouseMoved, this, _1));
  28. }
  29. Input::~Input()
  30. {
  31. cm_deleteN(mHorizontalHistoryBuffer, HISTORY_BUFFER_SIZE);
  32. cm_deleteN(mVerticalHistoryBuffer, HISTORY_BUFFER_SIZE);
  33. cm_deleteN(mTimesHistoryBuffer, HISTORY_BUFFER_SIZE);
  34. }
  35. void Input::registerRawInputHandler(std::shared_ptr<RawInputHandler> inputHandler)
  36. {
  37. if(mRawInputHandler != inputHandler)
  38. {
  39. mRawInputHandler = inputHandler;
  40. if(mRawInputHandler != nullptr)
  41. {
  42. mRawInputHandler->onButtonDown.connect(boost::bind(&Input::buttonDown, this, _1));
  43. mRawInputHandler->onButtonUp.connect(boost::bind(&Input::buttonUp, this, _1));
  44. mRawInputHandler->onAxisMoved.connect(boost::bind(&Input::axisMoved, this, _1, _2));
  45. }
  46. }
  47. }
  48. void Input::update()
  49. {
  50. if(mOSInputHandler == nullptr)
  51. {
  52. LOGERR("OS input handler not initialized!");
  53. return;
  54. }
  55. else
  56. mOSInputHandler->update();
  57. if(mRawInputHandler == nullptr)
  58. {
  59. LOGERR("Raw input handler not initialized!");
  60. return;
  61. }
  62. else
  63. mRawInputHandler->update();
  64. updateSmoothInput();
  65. }
  66. void Input::inputWindowChanged(const RenderWindow& win)
  67. {
  68. if(mRawInputHandler != nullptr)
  69. mRawInputHandler->inputWindowChanged(win);
  70. if(mOSInputHandler != nullptr)
  71. mOSInputHandler->inputWindowChanged(win);
  72. }
  73. void Input::buttonDown(ButtonCode code)
  74. {
  75. mKeyState[code & 0x0000FFFF] = true;
  76. if(!onKeyDown.empty())
  77. {
  78. ButtonEvent btnEvent;
  79. btnEvent.buttonCode = code;
  80. onKeyDown(btnEvent);
  81. }
  82. }
  83. void Input::buttonUp(ButtonCode code)
  84. {
  85. mKeyState[code & 0x0000FFFF] = false;
  86. if(!onKeyUp.empty())
  87. {
  88. ButtonEvent btnEvent;
  89. btnEvent.buttonCode = code;
  90. onKeyUp(btnEvent);
  91. }
  92. }
  93. void Input::axisMoved(const RawAxisState& state, RawInputAxis axis)
  94. {
  95. if(axis == RawInputAxis::Mouse_XY)
  96. mMouseLastRel = Int2(-state.rel.x, -state.rel.y);
  97. mAxes[(int)axis] = state;
  98. }
  99. void Input::mouseMoved(const Int2& screenPos)
  100. {
  101. mMouseAbsPos = screenPos;
  102. if(!onMouseMoved.empty())
  103. {
  104. MouseEvent mouseEvent;
  105. mouseEvent.screenPos = screenPos;
  106. onMouseMoved(mouseEvent);
  107. }
  108. }
  109. void Input::charInput(UINT32 chr)
  110. {
  111. if(!onCharInput.empty())
  112. {
  113. TextInputEvent textInputEvent;
  114. textInputEvent.textChar = chr;
  115. onCharInput(textInputEvent);
  116. }
  117. }
  118. float Input::getHorizontalAxis() const
  119. {
  120. return mSmoothHorizontalAxis;
  121. }
  122. float Input::getVerticalAxis() const
  123. {
  124. return mSmoothVerticalAxis;
  125. }
  126. bool Input::isButtonDown(ButtonCode button) const
  127. {
  128. return mKeyState[button & 0x0000FFFF];
  129. }
  130. void Input::updateSmoothInput()
  131. {
  132. float currentTime = gTime().getTime();
  133. mHorizontalHistoryBuffer[mCurrentBufferIdx] = (float)mMouseLastRel.x;
  134. mVerticalHistoryBuffer[mCurrentBufferIdx] = (float)mMouseLastRel.y;
  135. mTimesHistoryBuffer[mCurrentBufferIdx] = currentTime;
  136. int i = 0;
  137. int idx = mCurrentBufferIdx;
  138. float currentWeight = 1.0f;
  139. float horizontalTotal = 0.0f;
  140. float verticalTotal = 0.0f;
  141. while(i < HISTORY_BUFFER_SIZE)
  142. {
  143. float timeWeight = 1.0f - (currentTime - mTimesHistoryBuffer[idx]) * 10.0f;
  144. if(timeWeight < 0.0f)
  145. timeWeight = 0.0f;
  146. horizontalTotal += mHorizontalHistoryBuffer[idx] * currentWeight * timeWeight;
  147. verticalTotal += mVerticalHistoryBuffer[idx] * currentWeight * timeWeight;
  148. currentWeight *= WEIGHT_MODIFIER;
  149. idx = (idx + 1) % HISTORY_BUFFER_SIZE;
  150. i++;
  151. }
  152. mCurrentBufferIdx = (mCurrentBufferIdx + 1) % HISTORY_BUFFER_SIZE;
  153. mSmoothHorizontalAxis = Math::Clamp(horizontalTotal / HISTORY_BUFFER_SIZE, -1.0f, 1.0f);
  154. mSmoothVerticalAxis = Math::Clamp(verticalTotal / HISTORY_BUFFER_SIZE, -1.0f, 1.0f);
  155. mMouseLastRel = Int2(0, 0);
  156. }
  157. Input& gInput()
  158. {
  159. return Input::instance();
  160. }
  161. }