BsRawInputHandler.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Input/BsRawInputHandler.h"
  4. #include "Input/BsMouse.h"
  5. #include "Input/BsKeyboard.h"
  6. #include "Input/BsGamepad.h"
  7. #include "Utility/BsTime.h"
  8. #include "RenderAPI/BsRenderWindow.h"
  9. #include "Math/BsMath.h"
  10. namespace bs
  11. {
  12. RawInputHandler::RawInputHandler(UINT64 windowHandle)
  13. : mMouseSmoothingEnabled(false), mWindowHandle(windowHandle), mMouse(nullptr), mKeyboard(nullptr)
  14. {
  15. mMouseSampleAccumulator[0] = 0;
  16. mMouseSampleAccumulator[1] = 0;
  17. mTotalMouseSamplingTime[0] = 1.0f / 125.0f; // Use 125Hz as initial pooling rate for mice
  18. mTotalMouseSamplingTime[1] = 1.0f / 125.0f;
  19. mTotalMouseNumSamples[0] = 1;
  20. mTotalMouseNumSamples[1] = 1;
  21. mMouseSmoothedAxis[0] = 0.0f;
  22. mMouseSmoothedAxis[1] = 0.0f;
  23. mMouseZeroTime[0] = 0.0f;
  24. mMouseZeroTime[1] = 0.0f;
  25. initialize();
  26. mTimestampClockOffset = gTime().getStartTimeMs();
  27. }
  28. RawInputHandler::~RawInputHandler()
  29. {
  30. if (mMouse != nullptr)
  31. bs_delete(mMouse);
  32. if (mKeyboard != nullptr)
  33. bs_delete(mKeyboard);
  34. for (auto& gamepad : mGamepads)
  35. bs_delete(gamepad);
  36. cleanUp();
  37. }
  38. void RawInputHandler::_update()
  39. {
  40. if (mMouse != nullptr)
  41. mMouse->capture();
  42. if (mKeyboard != nullptr)
  43. mKeyboard->capture();
  44. for (auto& gamepad : mGamepads)
  45. gamepad->capture();
  46. float rawXValue = 0.0f;
  47. float rawYValue = 0.0f;
  48. // Smooth mouse axes if needed
  49. if (mMouseSmoothingEnabled)
  50. {
  51. rawXValue = smoothMouse((float)mMouseSampleAccumulator[0], 0);
  52. rawYValue = smoothMouse((float)mMouseSampleAccumulator[1], 1);
  53. }
  54. else
  55. {
  56. rawXValue = (float)mMouseSampleAccumulator[0];
  57. rawYValue = (float)mMouseSampleAccumulator[1];
  58. }
  59. rawXValue *= 0.1f;
  60. rawYValue *= 0.1f;
  61. mMouseSampleAccumulator[0] = 0;
  62. mMouseSampleAccumulator[1] = 0;
  63. RawAxisState xState;
  64. xState.rel = -rawXValue;
  65. onAxisMoved(0, xState, (UINT32)InputAxis::MouseX);
  66. RawAxisState yState;
  67. yState.rel = -rawYValue;
  68. onAxisMoved(0, yState, (UINT32)InputAxis::MouseY);
  69. }
  70. void RawInputHandler::_inputWindowChanged(const RenderWindow& win)
  71. {
  72. UINT64 hWnd = 0;
  73. win.getCustomAttribute("WINDOW", &hWnd);
  74. mKeyboard->changeCaptureContext(hWnd);
  75. mMouse->changeCaptureContext(hWnd);
  76. for (auto& gamepad : mGamepads)
  77. gamepad->changeCaptureContext(hWnd);
  78. }
  79. void RawInputHandler::_notifyMouseMoved(INT32 relX, INT32 relY, INT32 relZ)
  80. {
  81. mMouseSampleAccumulator[0] += relX;
  82. mMouseSampleAccumulator[1] += relY;
  83. mTotalMouseNumSamples[0] += Math::roundToInt(Math::abs((float)relX));
  84. mTotalMouseNumSamples[1] += Math::roundToInt(Math::abs((float)relY));
  85. // Update sample times used for determining sampling rate. But only if something was
  86. // actually sampled, and only if this isn't the first non-zero sample.
  87. if (mLastMouseUpdateFrame != gTime().getFrameIdx())
  88. {
  89. if (relX != 0 && !Math::approxEquals(mMouseSmoothedAxis[0], 0.0f))
  90. mTotalMouseSamplingTime[0] += gTime().getFrameDelta();
  91. if (relY != 0 && !Math::approxEquals(mMouseSmoothedAxis[1], 0.0f))
  92. mTotalMouseSamplingTime[1] += gTime().getFrameDelta();
  93. mLastMouseUpdateFrame = gTime().getFrameIdx();
  94. }
  95. RawAxisState zState;
  96. zState.rel = (float)relZ;
  97. onAxisMoved(0, zState, (UINT32)InputAxis::MouseZ);
  98. }
  99. void RawInputHandler::_notifyAxisMoved(UINT32 gamepadIdx, UINT32 axisIdx, INT32 value)
  100. {
  101. // Move axis values into [-1.0f, 1.0f] range
  102. float axisRange = Math::abs((float)Gamepad::MAX_AXIS) + Math::abs((float)Gamepad::MIN_AXIS);
  103. RawAxisState axisState;
  104. axisState.rel = ((value + Math::abs((float)Gamepad::MIN_AXIS)) / axisRange) * 2.0f - 1.0f;
  105. onAxisMoved(gamepadIdx, axisState, axisIdx);
  106. }
  107. void RawInputHandler::_notifyButtonPressed(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp)
  108. {
  109. onButtonDown(deviceIdx, code, timestamp - mTimestampClockOffset);
  110. }
  111. void RawInputHandler::_notifyButtonReleased(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp)
  112. {
  113. onButtonUp(deviceIdx, code, timestamp - mTimestampClockOffset);
  114. }
  115. float RawInputHandler::smoothMouse(float value, UINT32 idx)
  116. {
  117. UINT32 sampleCount = 1;
  118. float deltaTime = gTime().getFrameDelta();
  119. if (deltaTime < 0.25f)
  120. {
  121. float secondsPerSample = mTotalMouseSamplingTime[idx] / mTotalMouseNumSamples[idx];
  122. if (value == 0.0f)
  123. {
  124. mMouseZeroTime[idx] += deltaTime;
  125. if (mMouseZeroTime[idx] < secondsPerSample)
  126. value = mMouseSmoothedAxis[idx] * deltaTime / secondsPerSample;
  127. else
  128. mMouseSmoothedAxis[idx] = 0;
  129. }
  130. else
  131. {
  132. mMouseZeroTime[idx] = 0;
  133. if (mMouseSmoothedAxis[idx] != 0)
  134. {
  135. if (deltaTime < secondsPerSample * (sampleCount + 1))
  136. value = value * deltaTime / (secondsPerSample * sampleCount);
  137. else
  138. sampleCount = Math::roundToInt(deltaTime / secondsPerSample);
  139. }
  140. mMouseSmoothedAxis[idx] = value / sampleCount;
  141. }
  142. }
  143. else
  144. {
  145. mMouseSmoothedAxis[idx] = 0.0f;
  146. mMouseZeroTime[idx] = 0.0f;
  147. }
  148. return value;
  149. }
  150. }