CmInput.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #include "CmInput.h"
  2. #include "CmTime.h"
  3. #include "CmMath.h"
  4. #include "CmRect.h"
  5. #include "CmDebug.h"
  6. #include "CmRenderWindowManager.h"
  7. #include <boost/bind.hpp>
  8. namespace CamelotFramework
  9. {
  10. const int Input::HISTORY_BUFFER_SIZE = 10; // Size of buffer used for input smoothing
  11. const float Input::WEIGHT_MODIFIER = 0.5f;
  12. Input::Input()
  13. :mSmoothHorizontalAxis(0.0f), mSmoothVerticalAxis(0.0f), mCurrentBufferIdx(0), mMouseLastRel(0, 0), mRawInputHandler(nullptr)
  14. {
  15. mHorizontalHistoryBuffer = cm_newN<float>(HISTORY_BUFFER_SIZE);
  16. mVerticalHistoryBuffer = cm_newN<float>(HISTORY_BUFFER_SIZE);
  17. mTimesHistoryBuffer = cm_newN<float>(HISTORY_BUFFER_SIZE);
  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 < BC_Count; i++)
  25. mKeyState[i] = false;
  26. mOSInputHandler = cm_shared_ptr<OSInputHandler>();
  27. mOSInputHandler->onCharInput.connect(boost::bind(&Input::charInput, this, _1));
  28. mOSInputHandler->onMouseMoved.connect(boost::bind(&Input::mouseMoved, this, _1));
  29. RenderWindowManager::instance().onFocusGained.connect(boost::bind(&Input::inputWindowChanged, this, _1));
  30. }
  31. Input::~Input()
  32. {
  33. cm_deleteN(mHorizontalHistoryBuffer, HISTORY_BUFFER_SIZE);
  34. cm_deleteN(mVerticalHistoryBuffer, HISTORY_BUFFER_SIZE);
  35. cm_deleteN(mTimesHistoryBuffer, HISTORY_BUFFER_SIZE);
  36. }
  37. void Input::registerRawInputHandler(std::shared_ptr<RawInputHandler> inputHandler)
  38. {
  39. if(mRawInputHandler != inputHandler)
  40. {
  41. mRawInputHandler = inputHandler;
  42. if(mRawInputHandler != nullptr)
  43. {
  44. mRawInputHandler->onButtonDown.connect(boost::bind(&Input::buttonDown, this, _1));
  45. mRawInputHandler->onButtonUp.connect(boost::bind(&Input::buttonUp, this, _1));
  46. mRawInputHandler->onAxisMoved.connect(boost::bind(&Input::axisMoved, this, _1, _2));
  47. }
  48. }
  49. }
  50. void Input::update()
  51. {
  52. if(mRawInputHandler == nullptr)
  53. {
  54. LOGERR("Raw input handler not initialized!");
  55. return;
  56. }
  57. else
  58. mRawInputHandler->update();
  59. if(mOSInputHandler == nullptr)
  60. {
  61. LOGERR("OS input handler not initialized!");
  62. return;
  63. }
  64. else
  65. mOSInputHandler->update();
  66. Vector<ButtonCode>::type simulatedUp;
  67. Vector<ButtonCode>::type simulatedDown;
  68. {
  69. CM_LOCK_MUTEX(mSimulatedInputMutex);
  70. simulatedUp = mSimulatedButtonUp;
  71. simulatedDown = mSimulatedButtonDown;
  72. mSimulatedButtonUp.clear();
  73. mSimulatedButtonDown.clear();
  74. }
  75. for(auto& buttonCode : simulatedDown)
  76. buttonDown(buttonCode);
  77. for(auto& buttonCode : simulatedUp)
  78. buttonUp(buttonCode);
  79. updateSmoothInput();
  80. }
  81. void Input::inputWindowChanged(RenderWindow& win)
  82. {
  83. if(mRawInputHandler != nullptr)
  84. mRawInputHandler->inputWindowChanged(win);
  85. if(mOSInputHandler != nullptr)
  86. mOSInputHandler->inputWindowChanged(win);
  87. }
  88. void Input::buttonDown(ButtonCode code)
  89. {
  90. mKeyState[code & 0x0000FFFF] = true;
  91. if(!onButtonDown.empty())
  92. {
  93. ButtonEvent btnEvent;
  94. btnEvent.buttonCode = code;
  95. onButtonDown(btnEvent);
  96. }
  97. }
  98. void Input::buttonUp(ButtonCode code)
  99. {
  100. mKeyState[code & 0x0000FFFF] = false;
  101. if(!onButtonUp.empty())
  102. {
  103. ButtonEvent btnEvent;
  104. btnEvent.buttonCode = code;
  105. onButtonUp(btnEvent);
  106. }
  107. }
  108. void Input::axisMoved(const RawAxisState& state, RawInputAxis axis)
  109. {
  110. if(axis == RawInputAxis::Mouse_XY)
  111. mMouseLastRel = Int2(-state.rel.x, -state.rel.y);
  112. mAxes[(int)axis] = state;
  113. }
  114. void Input::mouseMoved(const Int2& screenPos)
  115. {
  116. mMouseAbsPos = screenPos;
  117. if(!onMouseMoved.empty())
  118. {
  119. MouseEvent mouseEvent;
  120. mouseEvent.screenPos = screenPos;
  121. onMouseMoved(mouseEvent);
  122. }
  123. }
  124. void Input::charInput(UINT32 chr)
  125. {
  126. if(!onCharInput.empty())
  127. {
  128. TextInputEvent textInputEvent;
  129. textInputEvent.textChar = chr;
  130. onCharInput(textInputEvent);
  131. }
  132. }
  133. float Input::getHorizontalAxis() const
  134. {
  135. return mSmoothHorizontalAxis;
  136. }
  137. float Input::getVerticalAxis() const
  138. {
  139. return mSmoothVerticalAxis;
  140. }
  141. bool Input::isButtonDown(ButtonCode button) const
  142. {
  143. return mKeyState[button & 0x0000FFFF];
  144. }
  145. void Input::simulateButtonDown(ButtonCode code)
  146. {
  147. CM_LOCK_MUTEX(mSimulatedInputMutex);
  148. mSimulatedButtonDown.push_back(code);
  149. }
  150. void Input::simulateButtonUp(ButtonCode code)
  151. {
  152. CM_LOCK_MUTEX(mSimulatedInputMutex);
  153. mSimulatedButtonUp.push_back(code);
  154. }
  155. void Input::updateSmoothInput()
  156. {
  157. float currentTime = gTime().getTime();
  158. mHorizontalHistoryBuffer[mCurrentBufferIdx] = (float)mMouseLastRel.x;
  159. mVerticalHistoryBuffer[mCurrentBufferIdx] = (float)mMouseLastRel.y;
  160. mTimesHistoryBuffer[mCurrentBufferIdx] = currentTime;
  161. int i = 0;
  162. int idx = mCurrentBufferIdx;
  163. float currentWeight = 1.0f;
  164. float horizontalTotal = 0.0f;
  165. float verticalTotal = 0.0f;
  166. while(i < HISTORY_BUFFER_SIZE)
  167. {
  168. float timeWeight = 1.0f - (currentTime - mTimesHistoryBuffer[idx]) * 10.0f;
  169. if(timeWeight < 0.0f)
  170. timeWeight = 0.0f;
  171. horizontalTotal += mHorizontalHistoryBuffer[idx] * currentWeight * timeWeight;
  172. verticalTotal += mVerticalHistoryBuffer[idx] * currentWeight * timeWeight;
  173. currentWeight *= WEIGHT_MODIFIER;
  174. idx = (idx + 1) % HISTORY_BUFFER_SIZE;
  175. i++;
  176. }
  177. mCurrentBufferIdx = (mCurrentBufferIdx + 1) % HISTORY_BUFFER_SIZE;
  178. mSmoothHorizontalAxis = Math::Clamp(horizontalTotal / HISTORY_BUFFER_SIZE, -1.0f, 1.0f);
  179. mSmoothVerticalAxis = Math::Clamp(verticalTotal / HISTORY_BUFFER_SIZE, -1.0f, 1.0f);
  180. mMouseLastRel = Int2(0, 0);
  181. }
  182. Input& gInput()
  183. {
  184. return Input::instance();
  185. }
  186. }