From 4d84334e38ec83d2f3824f8ed4b058985578bc1c Mon Sep 17 00:00:00 2001 From: rsn8887 Date: Thu, 11 Jul 2019 15:25:56 -0500 Subject: [PATCH] Radial deadzones, fix automap scrolling, use sdl for axis events --- SourceX/miniwin/misc_msg.cpp | 154 +++++++++++++++++++++++++++++++---- 1 file changed, 138 insertions(+), 16 deletions(-) diff --git a/SourceX/miniwin/misc_msg.cpp b/SourceX/miniwin/misc_msg.cpp index 0a1956e38a03..8c61ae2c24aa 100644 --- a/SourceX/miniwin/misc_msg.cpp +++ b/SourceX/miniwin/misc_msg.cpp @@ -3,6 +3,7 @@ #include "devilution.h" #include "stubs.h" +#include /** @file * * @@ -12,17 +13,28 @@ namespace dvl { bool conInv = false; -float leftStickX; -float leftStickY; -float rightStickX; -float rightStickY; -float leftTrigger; -float rightTrigger; -float deadzoneX; -float deadzoneY; +float leftStickX = 0; +float leftStickY = 0; +float rightStickX = 0; +float rightStickY = 0; +float leftTrigger = 0; +float rightTrigger = 0; +float rightDeadzone = 0.07; +float leftDeadzone = 0.07; int doAttack = 0; -int doInv = 0; -int doChar = 0; +int doUse = 0; +int doChar = 0; + +static int leftStickXUnscaled = 0; // raw axis values reported by SDL_JOYAXISMOTION +static int leftStickYUnscaled = 0; +static int rightStickXUnscaled = 0; +static int rightStickYUnscaled = 0; +static int hiresDX = 0; // keep track of X/Y sub-pixel per frame mouse motion +static int hiresDY = 0; +static int64_t currentTime = 0; // used to update joystick mouse once per frame +static int64_t lastTime = 0; +static void ScaleJoystickAxes(float *x, float *y, float deadzone); +static void HandleJoystickAxes(); static std::deque message_queue; @@ -117,11 +129,12 @@ static WINBOOL false_avail() WINBOOL PeekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) { - static signed short rstick_x; - static signed short lstick_x; - static signed short rstick_y; - static signed short lstick_y; - static short lastmouseX, lastmouseY; + // update joystick mouse at maximally 60 fps + currentTime = SDL_GetTicks(); + if ((currentTime - lastTime) > 15) { + HandleJoystickAxes(); + lastTime = currentTime; + } if (wMsgFilterMin != 0) UNIMPLEMENTED(); @@ -156,7 +169,26 @@ WINBOOL PeekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilter switch (e.type) { case SDL_JOYAXISMOTION: - PollSwitchStick(); + switch (e.jaxis.axis) { + case 0: + leftStickXUnscaled = e.jaxis.value; + break; + case 1: + leftStickYUnscaled = -e.jaxis.value; + break; + case 2: + rightStickXUnscaled = e.jaxis.value; + break; + case 3: + rightStickYUnscaled = -e.jaxis.value; + break; + } + leftStickX = leftStickXUnscaled; + leftStickY = leftStickYUnscaled; + ScaleJoystickAxes(&leftStickX, &leftStickY, leftDeadzone); + rightStickX = rightStickXUnscaled; + rightStickY = rightStickYUnscaled; + ScaleJoystickAxes(&rightStickX, &rightStickY, rightDeadzone); lpMsg->message = e.type == SDL_KEYUP; lpMsg->lParam = 0; break; @@ -471,4 +503,94 @@ WINBOOL PostMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) return true; } +void ScaleJoystickAxes(float *x, float *y, float deadzone) +{ + //radial and scaled dead_zone + //http://www.third-helix.com/2013/04/12/doing-thumbstick-dead-zones-right.html + //input values go from -32767.0...+32767.0, output values are from -1.0 to 1.0; + + if (deadzone == 0) { + return; + } + if (deadzone >= 1.0) { + *x = 0; + *y = 0; + return; + } + + const float maximum = 32767.0f; + float analog_x = *x; + float analog_y = *y; + float dead_zone = deadzone * maximum; + + float magnitude = sqrtf(analog_x * analog_x + analog_y * analog_y); + if (magnitude >= dead_zone) { + // find scaled axis values with magnitudes between zero and maximum + float scalingFactor = 1.0 / magnitude * (magnitude - dead_zone) / (maximum - dead_zone); + analog_x = (analog_x * scalingFactor); + analog_y = (analog_y * scalingFactor); + + // clamp to ensure results will never exceed the max_axis value + float clamping_factor = 1.0f; + float abs_analog_x = fabs(analog_x); + float abs_analog_y = fabs(analog_y); + if (abs_analog_x > 1.0 || abs_analog_y > 1.0){ + if (abs_analog_x > abs_analog_y) { + clamping_factor = 1 / abs_analog_x; + } else { + clamping_factor = 1 / abs_analog_y; + } + } + *x = (clamping_factor * analog_x); + *y = (clamping_factor * analog_y); + } else { + *x = 0; + *y = 0; + } +} + +static void HandleJoystickAxes() +{ + // deadzone is handled in ScaleJoystickAxes() already + if (rightStickX != 0 || rightStickY != 0) { + // right joystick + if (automapflag) { // move map + if (rightStickY < -0.5) + AutomapUp(); + else if (rightStickY > 0.5) + AutomapDown(); + else if (rightStickX < -0.5) + AutomapRight(); + else if (rightStickX > 0.5) + AutomapLeft(); + } else { // move cursor + if (pcurs == CURSOR_NONE) { + SetCursor_(CURSOR_HAND); + newCurHidden = false; + } + + const int slowdown = 80; // increase/decrease this to decrease/increase mouse speed + + int x = MouseX; + int y = MouseY; + hiresDX += rightStickX * 256.0; + hiresDY += rightStickY * 256.0; + + x += hiresDX / slowdown; + y += -(hiresDY) / slowdown; + + hiresDX %= slowdown; // keep track of dx remainder for sub-pixel per frame mouse motion + hiresDY %= slowdown; // keep track of dy remainder for sub-pixel per frame mouse motion + + if (x < 0) + x = 0; + if (y < 0) + y = 0; + + SetCursorPos(x, y); + MouseX = x; + MouseY = y; + } + } +} }