| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
- //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
- #include "Input/BsRawInputHandler.h"
- #include "Input/BsMouse.h"
- #include "Input/BsKeyboard.h"
- #include "Input/BsGamepad.h"
- #include "Utility/BsTime.h"
- #include "RenderAPI/BsRenderWindow.h"
- #include "Math/BsMath.h"
- namespace bs
- {
- RawInputHandler::RawInputHandler(UINT64 windowHandle)
- : mMouseSmoothingEnabled(false), mWindowHandle(windowHandle), mMouse(nullptr), mKeyboard(nullptr)
- {
- mMouseSampleAccumulator[0] = 0;
- mMouseSampleAccumulator[1] = 0;
- mTotalMouseSamplingTime[0] = 1.0f / 125.0f; // Use 125Hz as initial pooling rate for mice
- mTotalMouseSamplingTime[1] = 1.0f / 125.0f;
- mTotalMouseNumSamples[0] = 1;
- mTotalMouseNumSamples[1] = 1;
- mMouseSmoothedAxis[0] = 0.0f;
- mMouseSmoothedAxis[1] = 0.0f;
- mMouseZeroTime[0] = 0.0f;
- mMouseZeroTime[1] = 0.0f;
- initialize();
- mTimestampClockOffset = gTime().getStartTimeMs();
- }
- RawInputHandler::~RawInputHandler()
- {
- if (mMouse != nullptr)
- bs_delete(mMouse);
- if (mKeyboard != nullptr)
- bs_delete(mKeyboard);
- for (auto& gamepad : mGamepads)
- bs_delete(gamepad);
- cleanUp();
- }
- void RawInputHandler::_update()
- {
- if (mMouse != nullptr)
- mMouse->capture();
- if (mKeyboard != nullptr)
- mKeyboard->capture();
- for (auto& gamepad : mGamepads)
- gamepad->capture();
- float rawXValue = 0.0f;
- float rawYValue = 0.0f;
- // Smooth mouse axes if needed
- if (mMouseSmoothingEnabled)
- {
- rawXValue = smoothMouse((float)mMouseSampleAccumulator[0], 0);
- rawYValue = smoothMouse((float)mMouseSampleAccumulator[1], 1);
- }
- else
- {
- rawXValue = (float)mMouseSampleAccumulator[0];
- rawYValue = (float)mMouseSampleAccumulator[1];
- }
- rawXValue *= 0.1f;
- rawYValue *= 0.1f;
- mMouseSampleAccumulator[0] = 0;
- mMouseSampleAccumulator[1] = 0;
- RawAxisState xState;
- xState.rel = -rawXValue;
- onAxisMoved(0, xState, (UINT32)InputAxis::MouseX);
- RawAxisState yState;
- yState.rel = -rawYValue;
-
- onAxisMoved(0, yState, (UINT32)InputAxis::MouseY);
- }
- void RawInputHandler::_inputWindowChanged(const RenderWindow& win)
- {
- UINT64 hWnd = 0;
- win.getCustomAttribute("WINDOW", &hWnd);
- mKeyboard->changeCaptureContext(hWnd);
- mMouse->changeCaptureContext(hWnd);
- for (auto& gamepad : mGamepads)
- gamepad->changeCaptureContext(hWnd);
- }
- void RawInputHandler::_notifyMouseMoved(INT32 relX, INT32 relY, INT32 relZ)
- {
- mMouseSampleAccumulator[0] += relX;
- mMouseSampleAccumulator[1] += relY;
- mTotalMouseNumSamples[0] += Math::roundToInt(Math::abs((float)relX));
- mTotalMouseNumSamples[1] += Math::roundToInt(Math::abs((float)relY));
- // Update sample times used for determining sampling rate. But only if something was
- // actually sampled, and only if this isn't the first non-zero sample.
- if (mLastMouseUpdateFrame != gTime().getFrameIdx())
- {
- if (relX != 0 && !Math::approxEquals(mMouseSmoothedAxis[0], 0.0f))
- mTotalMouseSamplingTime[0] += gTime().getFrameDelta();
- if (relY != 0 && !Math::approxEquals(mMouseSmoothedAxis[1], 0.0f))
- mTotalMouseSamplingTime[1] += gTime().getFrameDelta();
- mLastMouseUpdateFrame = gTime().getFrameIdx();
- }
- RawAxisState zState;
- zState.rel = (float)relZ;
- onAxisMoved(0, zState, (UINT32)InputAxis::MouseZ);
- }
- void RawInputHandler::_notifyAxisMoved(UINT32 gamepadIdx, UINT32 axisIdx, INT32 value)
- {
- // Move axis values into [-1.0f, 1.0f] range
- float axisRange = Math::abs((float)Gamepad::MAX_AXIS) + Math::abs((float)Gamepad::MIN_AXIS);
- RawAxisState axisState;
- axisState.rel = ((value + Math::abs((float)Gamepad::MIN_AXIS)) / axisRange) * 2.0f - 1.0f;
- onAxisMoved(gamepadIdx, axisState, axisIdx);
- }
- void RawInputHandler::_notifyButtonPressed(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp)
- {
- onButtonDown(deviceIdx, code, timestamp - mTimestampClockOffset);
- }
- void RawInputHandler::_notifyButtonReleased(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp)
- {
- onButtonUp(deviceIdx, code, timestamp - mTimestampClockOffset);
- }
- float RawInputHandler::smoothMouse(float value, UINT32 idx)
- {
- UINT32 sampleCount = 1;
- float deltaTime = gTime().getFrameDelta();
- if (deltaTime < 0.25f)
- {
- float secondsPerSample = mTotalMouseSamplingTime[idx] / mTotalMouseNumSamples[idx];
- if (value == 0.0f)
- {
- mMouseZeroTime[idx] += deltaTime;
- if (mMouseZeroTime[idx] < secondsPerSample)
- value = mMouseSmoothedAxis[idx] * deltaTime / secondsPerSample;
- else
- mMouseSmoothedAxis[idx] = 0;
- }
- else
- {
- mMouseZeroTime[idx] = 0;
- if (mMouseSmoothedAxis[idx] != 0)
- {
- if (deltaTime < secondsPerSample * (sampleCount + 1))
- value = value * deltaTime / (secondsPerSample * sampleCount);
- else
- sampleCount = Math::roundToInt(deltaTime / secondsPerSample);
- }
- mMouseSmoothedAxis[idx] = value / sampleCount;
- }
- }
- else
- {
- mMouseSmoothedAxis[idx] = 0.0f;
- mMouseZeroTime[idx] = 0.0f;
- }
- return value;
- }
- }
|