diff --git a/Core/TiltEventProcessor.cpp b/Core/TiltEventProcessor.cpp index 703d64184e..5e352a5996 100644 --- a/Core/TiltEventProcessor.cpp +++ b/Core/TiltEventProcessor.cpp @@ -34,6 +34,8 @@ void GenerateDPadEvent(int digitalX, int digitalY); void GenerateActionButtonEvent(int digitalX, int digitalY); void GenerateTriggerButtonEvent(int digitalX, int digitalY); +} + // deadzone is normalized - 0 to 1 // sensitivity controls how fast the deadzone reaches max value inline float ApplyDeadzoneAxis(float x, float deadzone) { @@ -51,32 +53,35 @@ inline float ApplyDeadzoneAxis(float x, float deadzone) { } } -inline void ApplyDeadzoneXY(float tiltX, float tiltY, float *adjustedTiltX, float *adjustedTiltY, float deadzone, bool circular) { + +inline void ApplyDeadzoneXY(float x, float y, float *adjustedX, float *adjustedY, float deadzone, bool circular) { if (circular) { - if (tiltX == 0.0f && tiltY == 0.0f) { - *adjustedTiltX = 0.0f; - *adjustedTiltY = 0.0f; + if (x == 0.0f && y == 0.0f) { + *adjustedX = 0.0f; + *adjustedY = 0.0f; return; } - float magnitude = sqrtf(tiltX * tiltX + tiltY * tiltY); + float magnitude = sqrtf(x * x + y * y); if (magnitude <= deadzone + 0.00001f) { - *adjustedTiltX = 0.0f; - *adjustedTiltY = 0.0f; + *adjustedX = 0.0f; + *adjustedY = 0.0f; return; } float factor = 1.0f / (1.0f - deadzone); float newMagnitude = (magnitude - deadzone) * factor; - *adjustedTiltX = (tiltX / magnitude) * newMagnitude; - *adjustedTiltY = (tiltY / magnitude) * newMagnitude; + *adjustedX = (x / magnitude) * newMagnitude; + *adjustedY = (y / magnitude) * newMagnitude; } else { - *adjustedTiltX = ApplyDeadzoneAxis(tiltX, deadzone); - *adjustedTiltY = ApplyDeadzoneAxis(tiltY, deadzone); + *adjustedX = ApplyDeadzoneAxis(x, deadzone); + *adjustedY = ApplyDeadzoneAxis(y, deadzone); } } +namespace TiltEventProcessor { + // Also clamps to -1.0..1.0. // This applies a (circular if desired) inverse deadzone. inline void ApplyInverseDeadzone(float x, float y, float *outX, float *outY, float inverseDeadzone, bool circular) { @@ -310,39 +315,64 @@ namespace MouseEventProcessor { // But, the cost isn't high. std::mutex g_mouseMutex; -float g_mouseDeltaX = 0; -float g_mouseDeltaY = 0; +float g_mouseDeltaXAccum = 0; +float g_mouseDeltaYAccum = 0; -void ProcessDelta(float dx, float dy) { - std::unique_lock lock(g_mouseMutex); - // Accumulate mouse deltas, for some kind of smoothing. - g_mouseDeltaX += dx; - g_mouseDeltaY += dy; -} +float g_mouseDeltaX; +float g_mouseDeltaY; -void MouseDeltaToAxes(double now, float *mx, float *my) { - std::unique_lock lock(g_mouseMutex); +void DecayMouse(double now) { + g_mouseDeltaX = g_mouseDeltaXAccum; + g_mouseDeltaY = g_mouseDeltaYAccum; + + const float decay = g_Config.fMouseSmoothing; static double lastTime = 0.0f; if (lastTime == 0.0) { lastTime = now; - *mx = 0.0f; - *my = 0.0f; return; } double dt = now - lastTime; lastTime = now; + // Decay the mouse deltas. We do an approximation of the old polling. + // Should be able to use a smooth exponential here, when I get around to doing + // the math. + static double accumDt = 0.0; + accumDt += dt; + const double oldPollInterval = 1.0 / 250.0; // See Windows "PollControllers". + while (accumDt > oldPollInterval) { + accumDt -= oldPollInterval; + g_mouseDeltaXAccum *= decay; + g_mouseDeltaYAccum *= decay; + } +} + +void ProcessDelta(double now, float dx, float dy) { + std::unique_lock lock(g_mouseMutex); + + // Accumulate mouse deltas, for some kind of smoothing. + g_mouseDeltaXAccum += dx; + g_mouseDeltaYAccum += dy; + + DecayMouse(now); +} + +void MouseDeltaToAxes(double now, float *mx, float *my) { + std::unique_lock lock(g_mouseMutex); + float scaleFactor_x = g_display.dpi_scale_x * 0.1 * g_Config.fMouseSensitivity; float scaleFactor_y = g_display.dpi_scale_y * 0.1 * g_Config.fMouseSensitivity; - *mx = clamp_value(g_mouseDeltaX * scaleFactor_x, -1.0f, 1.0f); - *my = clamp_value(g_mouseDeltaY * scaleFactor_y, -1.0f, 1.0f); + DecayMouse(now); - // Decay the mouse deltas. This is where we should use dt. - float decay = expf(-dt * 50.0f * (1.0f - g_Config.fMouseSmoothing)); - g_mouseDeltaX *= decay; - g_mouseDeltaY *= decay; + // TODO: Make configurable. + float mouseDeadZone = 0.1f; + + float outX = clamp_value(g_mouseDeltaX * scaleFactor_x, -1.0f, 1.0f); + float outY = clamp_value(g_mouseDeltaY * scaleFactor_y, -1.0f, 1.0f); + + ApplyDeadzoneXY(outX, outY, mx, my, mouseDeadZone, true); } } // namespace diff --git a/Core/TiltEventProcessor.h b/Core/TiltEventProcessor.h index 793a5b1272..3fb0ef7671 100644 --- a/Core/TiltEventProcessor.h +++ b/Core/TiltEventProcessor.h @@ -19,7 +19,7 @@ extern float rawTiltAnalogY; namespace MouseEventProcessor { -void ProcessDelta(float dx, float dy); +void ProcessDelta(double now, float dx, float dy); void MouseDeltaToAxes(double now, float *mx, float *my); } // namespace diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index a087c10f13..eac395444e 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1329,7 +1329,7 @@ void NativeMouseDelta(float dx, float dy) { if (!g_Config.bMouseControl) return; - MouseEventProcessor::ProcessDelta(dx, dy); + MouseEventProcessor::ProcessDelta(time_now_d(), dx, dy); } // Called from NativeFrame. diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 8a693f3c59..2e3e8809e7 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -77,7 +77,7 @@ void WindowsInputManager::Init() { } void WindowsInputManager::PollControllers() { - static const int CHECK_FREQUENCY = 71; + static const int CHECK_FREQUENCY = 71; // Just an arbitrary prime to try to not collide with other periodic checks. if (checkCounter_++ > CHECK_FREQUENCY) { #ifndef _M_ARM size_t newCount = DinputDevice::getNumPads();