From dfb9d0df28ba4664fd7cf51caa35c49fc1d8c99e Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 30 Jan 2025 22:42:13 -0500 Subject: [PATCH 1/2] Tie axis data to the button map The main benefit of this is to remove the requirement of going to the gamepad menu for binding analog sticks, and going to a keybinds menu for binding literally everything else; now it's all bound in the same location. This also means that axes can both register as a digital button press, and be used as an analog value for movement separately. Before, using analog movement would not register BT_FORWARD, BT_BACK, etc Currently, only the code that creates the JoyMap menu items has been removed, and action functions relating to them have been dummied out. I'm not quite sure how backwards compatibility is supposed to be handled here, or if it's OK to break. --- src/common/console/c_buttons.cpp | 49 ++++++ src/common/console/c_buttons.h | 26 +++- src/common/engine/m_joy.cpp | 18 --- src/common/engine/m_joy.h | 18 +-- src/common/menu/joystickmenu.cpp | 4 +- .../platform/posix/cocoa/i_joystick.cpp | 139 ++++++++---------- src/common/platform/posix/sdl/i_joystick.cpp | 61 ++++---- src/common/platform/win32/i_dijoy.cpp | 105 +++---------- src/common/platform/win32/i_input.cpp | 7 +- src/common/platform/win32/i_input.h | 2 +- src/common/platform/win32/i_rawps2.cpp | 93 ++++-------- src/common/platform/win32/i_xinput.cpp | 100 +++++-------- src/g_game.cpp | 67 +++++---- .../zscript/engine/ui/menu/joystickmenu.zs | 2 - 14 files changed, 307 insertions(+), 384 deletions(-) diff --git a/src/common/console/c_buttons.cpp b/src/common/console/c_buttons.cpp index 3464553e3c..49145d5f92 100644 --- a/src/common/console/c_buttons.cpp +++ b/src/common/console/c_buttons.cpp @@ -39,6 +39,7 @@ #include "printf.h" #include "cmdlib.h" #include "c_console.h" +#include "m_joy.h" ButtonMap buttonMap; @@ -150,6 +151,23 @@ void ButtonMap::ResetButtonStates () // //============================================================================= +void ButtonMap::GetAxes () +{ + float joyaxes[NUM_KEYS]; + I_GetAxes(joyaxes); + + for (auto &btn : Buttons) + { + btn.AddAxes(joyaxes); + } +} + +//============================================================================= +// +// +// +//============================================================================= + bool FButtonStatus::PressKey (int keynum) { int i, open; @@ -246,6 +264,37 @@ bool FButtonStatus::ReleaseKey (int keynum) // //============================================================================= +void FButtonStatus::AddAxes (float joyaxes[NUM_KEYS]) +{ + int i, open; + + bIsAxis = false; + Axis = 0.0f; + + for (i = 0; i < MAX_KEYS; i++) + { + if (Keys[i] == 0) + { + break; + } + + float axis_value = joyaxes[ Keys[i] ]; + if (axis_value > 0.0f) + { + bIsAxis = true; + Axis += axis_value; + } + } + + Axis = clamp(Axis, 0.0f, 1.0f); +} + +//============================================================================= +// +// +// +//============================================================================= + void ButtonMap::AddButtonTabCommands() { // Add all the action commands for tab completion diff --git a/src/common/console/c_buttons.h b/src/common/console/c_buttons.h index 3bfbbd0fb0..18511cc2af 100644 --- a/src/common/console/c_buttons.h +++ b/src/common/console/c_buttons.h @@ -3,6 +3,7 @@ #include #include "tarray.h" #include "name.h" +#include "keydef.h" // Actions struct FButtonStatus @@ -14,13 +15,18 @@ struct FButtonStatus bool bWentDown; // Button went down this tic bool bWentUp; // Button went up this tic bool bReleaseLock; // Lock ReleaseKey call in ResetButtonStates + + bool bIsAxis; // Whenever or not this button is being controlled by any axis. + float Axis; // How far the button has been pressed. Updated by I_GetAxes. + void (*PressHandler)(); // for optional game-side customization void (*ReleaseHandler)(); bool PressKey (int keynum); // Returns true if this key caused the button to be pressed. bool ReleaseKey (int keynum); // Returns true if this key is no longer pressed. + void AddAxes (float joyaxes[NUM_KEYS]); // Update joystick axis information. void ResetTriggers () { bWentDown = bWentUp = false; } - void Reset () { bDown = bWentDown = bWentUp = false; } + void Reset () { bDown = bWentDown = bWentUp = bIsAxis = false; Axis = 0.0f; } }; class ButtonMap @@ -53,6 +59,7 @@ public: void ResetButtonTriggers(); // Call ResetTriggers for all buttons void ResetButtonStates(); // Same as above, but also clear bDown + void GetAxes(); // Call AddAxes for all buttons int ListActionCommands(const char* pattern); void AddButtonTabCommands(); @@ -62,6 +69,23 @@ public: return Buttons[x].bDown; } + bool DigitalButtonDown(int x) const + { + // Like ButtonDown, but only for digital buttons. Axes are excluded. + return (Buttons[x].bIsAxis == false && Buttons[x].bDown == true); + } + + float AnalogButtonDown(int x) const + { + // Gets the analog value of a button when it is bound to an axis. + if (Buttons[x].bIsAxis == true) + { + return Buttons[x].Axis; + } + + return 0.0f; + } + bool ButtonPressed(int x) const { return Buttons[x].bWentDown; diff --git a/src/common/engine/m_joy.cpp b/src/common/engine/m_joy.cpp index 1e4b2f3e0e..c5d110ea7a 100644 --- a/src/common/engine/m_joy.cpp +++ b/src/common/engine/m_joy.cpp @@ -162,18 +162,6 @@ bool M_LoadJoystickConfig(IJoystickConfig *joy) { joy->SetAxisScale(i, (float)atof(value)); } - - mysnprintf(key + axislen, countof(key) - axislen, "map"); - value = GameConfig->GetValueForKey(key); - if (value) - { - EJoyAxis gameaxis = (EJoyAxis)atoi(value); - if (gameaxis < JOYAXIS_None || gameaxis >= NUM_JOYAXIS) - { - gameaxis = JOYAXIS_None; - } - joy->SetAxisMap(i, gameaxis); - } } return true; } @@ -227,12 +215,6 @@ void M_SaveJoystickConfig(IJoystickConfig *joy) mysnprintf(value, countof(value), "%g", joy->GetAxisScale(i)); GameConfig->SetValueForKey(key, value); } - if (!joy->IsAxisMapDefault(i)) - { - mysnprintf(key + axislen, countof(key) - axislen, "map"); - mysnprintf(value, countof(value), "%d", joy->GetAxisMap(i)); - GameConfig->SetValueForKey(key, value); - } } // If the joystick is entirely at its defaults, delete this section // so that we don't write out a lone section header. diff --git a/src/common/engine/m_joy.h b/src/common/engine/m_joy.h index e8d9d3b137..ca0c0bb6a3 100644 --- a/src/common/engine/m_joy.h +++ b/src/common/engine/m_joy.h @@ -4,18 +4,7 @@ #include "basics.h" #include "tarray.h" #include "c_cvars.h" - -enum EJoyAxis -{ - JOYAXIS_None = -1, - JOYAXIS_Yaw, - JOYAXIS_Pitch, - JOYAXIS_Forward, - JOYAXIS_Side, - JOYAXIS_Up, -// JOYAXIS_Roll, // Ha ha. No roll for you. - NUM_JOYAXIS, -}; +#include "keydef.h" // Generic configuration interface for a controller. struct IJoystickConfig @@ -28,12 +17,10 @@ struct IJoystickConfig virtual int GetNumAxes() = 0; virtual float GetAxisDeadZone(int axis) = 0; - virtual EJoyAxis GetAxisMap(int axis) = 0; virtual const char *GetAxisName(int axis) = 0; virtual float GetAxisScale(int axis) = 0; virtual void SetAxisDeadZone(int axis, float zone) = 0; - virtual void SetAxisMap(int axis, EJoyAxis gameaxis) = 0; virtual void SetAxisScale(int axis, float scale) = 0; virtual bool GetEnabled() = 0; @@ -46,7 +33,6 @@ struct IJoystickConfig // Used by the saver to not save properties that are at their defaults. virtual bool IsSensitivityDefault() = 0; virtual bool IsAxisDeadZoneDefault(int axis) = 0; - virtual bool IsAxisMapDefault(int axis) = 0; virtual bool IsAxisScaleDefault(int axis) = 0; virtual void SetDefaultConfig() = 0; @@ -64,7 +50,7 @@ int Joy_XYAxesToButtons(double x, double y); double Joy_RemoveDeadZone(double axisval, double deadzone, uint8_t *buttons); // These ought to be provided by a system-specific i_input.cpp. -void I_GetAxes(float axes[NUM_JOYAXIS]); +void I_GetAxes(float axes[NUM_KEYS]); void I_GetJoysticks(TArray &sticks); IJoystickConfig *I_UpdateDeviceList(); extern void UpdateJoystickMenu(IJoystickConfig *); diff --git a/src/common/menu/joystickmenu.cpp b/src/common/menu/joystickmenu.cpp index 3d3e881b16..1783361d22 100644 --- a/src/common/menu/joystickmenu.cpp +++ b/src/common/menu/joystickmenu.cpp @@ -88,7 +88,7 @@ DEFINE_ACTION_FUNCTION(IJoystickConfig, GetAxisMap) { PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig); PARAM_INT(axis); - ACTION_RETURN_INT(self->GetAxisMap(axis)); + ACTION_RETURN_INT(-1); // JOYAXIS_None's old value } DEFINE_ACTION_FUNCTION(IJoystickConfig, SetAxisMap) @@ -96,7 +96,7 @@ DEFINE_ACTION_FUNCTION(IJoystickConfig, SetAxisMap) PARAM_SELF_STRUCT_PROLOGUE(IJoystickConfig); PARAM_INT(axis); PARAM_INT(map); - self->SetAxisMap(axis, (EJoyAxis)map); + //self->SetAxisMap(axis, (EJoyAxis)map); return 0; } diff --git a/src/common/platform/posix/cocoa/i_joystick.cpp b/src/common/platform/posix/cocoa/i_joystick.cpp index 44d1fb961b..b9adf1b205 100644 --- a/src/common/platform/posix/cocoa/i_joystick.cpp +++ b/src/common/platform/posix/cocoa/i_joystick.cpp @@ -91,17 +91,14 @@ public: virtual int GetNumAxes(); virtual float GetAxisDeadZone(int axis); - virtual EJoyAxis GetAxisMap(int axis); virtual const char* GetAxisName(int axis); virtual float GetAxisScale(int axis); virtual void SetAxisDeadZone(int axis, float deadZone); - virtual void SetAxisMap(int axis, EJoyAxis gameAxis); virtual void SetAxisScale(int axis, float scale); virtual bool IsSensitivityDefault(); virtual bool IsAxisDeadZoneDefault(int axis); - virtual bool IsAxisMapDefault(int axis); virtual bool IsAxisScaleDefault(int axis); virtual bool GetEnabled(); @@ -114,7 +111,7 @@ public: virtual void SetDefaultConfig(); virtual FString GetIdentifier(); - void AddAxes(float axes[NUM_JOYAXIS]) const; + void AddAxes(float axes[NUM_KEYS]) const; void Update(); @@ -147,8 +144,8 @@ private: float sensitivity; float defaultSensitivity; - EJoyAxis gameAxis; - EJoyAxis defaultGameAxis; + int keys[2]; + uint8_t buttonValue; AnalogAxis() { @@ -371,11 +368,6 @@ float IOKitJoystick::GetAxisDeadZone(int axis) return IS_AXIS_VALID ? m_axes[axis].deadZone : 0.0f; } -EJoyAxis IOKitJoystick::GetAxisMap(int axis) -{ - return IS_AXIS_VALID ? m_axes[axis].gameAxis : JOYAXIS_None; -} - const char* IOKitJoystick::GetAxisName(int axis) { return IS_AXIS_VALID ? m_axes[axis].name : "Invalid"; @@ -394,16 +386,6 @@ void IOKitJoystick::SetAxisDeadZone(int axis, float deadZone) } } -void IOKitJoystick::SetAxisMap(int axis, EJoyAxis gameAxis) -{ - if (IS_AXIS_VALID) - { - m_axes[axis].gameAxis = (gameAxis> JOYAXIS_None && gameAxis = 3) - { - m_axes[0].gameAxis = JOYAXIS_Side; - m_axes[1].gameAxis = JOYAXIS_Forward; - m_axes[2].gameAxis = JOYAXIS_Yaw; - - // Four axes? First two are movement, last two are looking around. - - if (axisCount >= 4) - { - m_axes[3].gameAxis = JOYAXIS_Pitch; -// ??? m_axes[3].sensitivity = 0.75f; - - // Five axes? Use the fifth one for moving up and down. - - if (axisCount >= 5) - { - m_axes[4].gameAxis = JOYAXIS_Up; - } - } - } - - // If there is only one axis, then we make no assumptions about how - // the user might want to use it. - // Preserve defaults for config saving. for (size_t i = 0; i < axisCount; ++i) { m_axes[i].defaultDeadZone = m_axes[i].deadZone; m_axes[i].defaultSensitivity = m_axes[i].sensitivity; - m_axes[i].defaultGameAxis = m_axes[i].gameAxis; } } @@ -517,18 +455,27 @@ FString IOKitJoystick::GetIdentifier() } -void IOKitJoystick::AddAxes(float axes[NUM_JOYAXIS]) const +void IOKitJoystick::AddAxes(float axes[NUM_KEYS]) const { for (size_t i = 0, count = m_axes.Size(); i < count; ++i) { - const EJoyAxis axis = m_axes[i].gameAxis; + // Add to the game axis. + float axis_value = m_axes[i].value; + int axis_key = 0; - if (JOYAXIS_None == axis) + if (axis_value > 0.0f) { - continue; + axis_key = m_axes[i].keys[0]; + } + else if (axis_value < 0.0f) + { + axis_key = m_axes[i].keys[1]; } - axes[axis] -= m_axes[i].value; + if (axis_key > 0 && axis_key < NUM_KEYS) + { + axes[axis_key] += fabs(axis_value); + } } } @@ -591,6 +538,17 @@ void IOKitJoystick::ProcessAxes() for (size_t i = 0, count = m_axes.Size(); i < count; ++i) { AnalogAxis& axis = m_axes[i]; + uint8_t buttonstate = 0; + + if (i < NUM_JOYAXISBUTTONS) + { + axis.keys[0] = KEY_JOYAXIS1PLUS + (i * 2); + axis.keys[1] = KEY_JOYAXIS1PLUS + (i * 2) + 1; + } + else + { + axis.keys[0] = axis.keys[1] = 0; + } static const double scaledMin = -1; static const double scaledMax = 1; @@ -601,7 +559,7 @@ void IOKitJoystick::ProcessAxes() { const double scaledValue = scaledMin + (event.value - axis.minValue) * (scaledMax - scaledMin) / (axis.maxValue - axis.minValue); - const double filteredValue = Joy_RemoveDeadZone(scaledValue, axis.deadZone, NULL); + const double filteredValue = Joy_RemoveDeadZone(scaledValue, axis.deadZone, &buttonstate); axis.value = static_cast(filteredValue * m_sensitivity * axis.sensitivity); } @@ -609,6 +567,19 @@ void IOKitJoystick::ProcessAxes() { axis.value = 0.0f; } + + if (i < NUM_JOYAXISBUTTONS && (i > 2 || m_axes.Size() == 1)) + { + Joy_GenerateButtonEvents(axis.buttonValue, buttonstate, 2, KEY_JOYAXIS1PLUS + i*2); + } + else if (i == 1) + { + // Since we sorted the axes, we know that the first two are definitely X and Y. + // They are probably a single stick, so use angular position to determine buttons. + buttonstate = Joy_XYAxesToButtons(m_axes[0].value, axis.value); + Joy_GenerateButtonEvents(axis.buttonValue, buttonstate, 4, KEY_JOYAXIS1PLUS); + } + axis.buttonValue = buttonstate; } } @@ -628,16 +599,32 @@ bool IOKitJoystick::ProcessAxis(const IOHIDEventStruct& event) } AnalogAxis& axis = m_axes[i]; + uint8_t buttonstate = 0; + + if (i < NUM_JOYAXISBUTTONS) + { + axis.keys[0] = KEY_JOYAXIS1PLUS + (i * 2); + axis.keys[1] = KEY_JOYAXIS1PLUS + (i * 2) + 1; + } + else + { + axis.keys[0] = axis.keys[1] = 0; + } static const double scaledMin = -1; static const double scaledMax = 1; const double scaledValue = scaledMin + (event.value - axis.minValue) * (scaledMax - scaledMin) / (axis.maxValue - axis.minValue); - const double filteredValue = Joy_RemoveDeadZone(scaledValue, axis.deadZone, NULL); + const double filteredValue = Joy_RemoveDeadZone(scaledValue, axis.deadZone, &buttonstate); axis.value = static_cast(filteredValue * m_sensitivity * axis.sensitivity); + if (i < NUM_JOYAXISBUTTONS) + { + Joy_GenerateButtonEvents(axis.buttonValue, buttonstate, 2, KEY_JOYAXIS1PLUS + i*2); + } + axis.buttonValue = buttonstate; return true; } @@ -966,7 +953,7 @@ public: void GetJoysticks(TArray& joysticks) const; - void AddAxes(float axes[NUM_JOYAXIS]) const; + void AddAxes(float axes[NUM_KEYS]) const; // Updates axes/buttons states void Update(); @@ -1057,7 +1044,7 @@ void IOKitJoystickManager::GetJoysticks(TArray& joysticks) con } } -void IOKitJoystickManager::AddAxes(float axes[NUM_JOYAXIS]) const +void IOKitJoystickManager::AddAxes(float axes[NUM_KEYS]) const { for (size_t i = 0, count = m_joysticks.Size(); i < count; ++i) { @@ -1220,9 +1207,9 @@ void I_GetJoysticks(TArray& sticks) } } -void I_GetAxes(float axes[NUM_JOYAXIS]) +void I_GetAxes(float axes[NUM_KEYS]) { - for (size_t i = 0; i < NUM_JOYAXIS; ++i) + for (size_t i = 0; i < NUM_KEYS; ++i) { axes[i] = 0.0f; } diff --git a/src/common/platform/posix/sdl/i_joystick.cpp b/src/common/platform/posix/sdl/i_joystick.cpp index 42837ecba6..c8f89cdfe3 100644 --- a/src/common/platform/posix/sdl/i_joystick.cpp +++ b/src/common/platform/posix/sdl/i_joystick.cpp @@ -90,10 +90,6 @@ public: { return Axes[axis].DeadZone; } - EJoyAxis GetAxisMap(int axis) - { - return Axes[axis].GameAxis; - } const char *GetAxisName(int axis) { return Axes[axis].Name.GetChars(); @@ -107,10 +103,6 @@ public: { Axes[axis].DeadZone = clamp(zone, MIN_DEADZONE, 1.f); } - void SetAxisMap(int axis, EJoyAxis gameaxis) - { - Axes[axis].GameAxis = gameaxis; - } void SetAxisScale(int axis, float scale) { Axes[axis].Multiplier = scale; @@ -125,12 +117,6 @@ public: { return Axes[axis].DeadZone <= MIN_DEADZONE; } - bool IsAxisMapDefault(int axis) - { - if(axis >= 5) - return Axes[axis].GameAxis == JOYAXIS_None; - return Axes[axis].GameAxis == DefaultAxes[axis]; - } bool IsAxisScaleDefault(int axis) { return Axes[axis].Multiplier == 1.0f; @@ -149,10 +135,7 @@ public: info.Multiplier = 1.0f; info.Value = 0.0; info.ButtonValue = 0; - if(i >= 5) - info.GameAxis = JOYAXIS_None; - else - info.GameAxis = DefaultAxes[i]; + info.Keys[0] = info.Keys[1] = 0; Axes.Push(info); } } @@ -178,13 +161,27 @@ public: return id; } - void AddAxes(float axes[NUM_JOYAXIS]) + void AddAxes(float axes[NUM_KEYS]) { // Add to game axes. for (int i = 0; i < GetNumAxes(); ++i) { - if(Axes[i].GameAxis != JOYAXIS_None) - axes[Axes[i].GameAxis] -= float(Axes[i].Value * Multiplier * Axes[i].Multiplier); + float axis_value = float(Axes[i].Value * Multiplier * Axes[i].Multiplier); + int axis_key = 0; + + if (axis_value > 0.0f) + { + axis_key = Axes[i].Keys[0]; + } + else if (axis_value < 0.0f) + { + axis_key = Axes[i].Keys[1]; + } + + if (axis_key > 0 && axis_key < NUM_KEYS) + { + axes[axis_key] += fabs(axis_value); + } } } @@ -196,6 +193,16 @@ public: { buttonstate = 0; + if (i < NUM_JOYAXISBUTTONS) + { + Axes[i].Keys[0] = KEY_JOYAXIS1PLUS + (i * 2); + Axes[i].Keys[1] = KEY_JOYAXIS1PLUS + (i * 2) + 1; + } + else + { + Axes[i].Keys[0] = Axes[i].Keys[1] = 0; + } + Axes[i].Value = SDL_JoystickGetAxis(Device, i)/32767.0; Axes[i].Value = Joy_RemoveDeadZone(Axes[i].Value, Axes[i].DeadZone, &buttonstate); @@ -255,11 +262,10 @@ protected: FString Name; float DeadZone; float Multiplier; - EJoyAxis GameAxis; + int Keys[2]; double Value; uint8_t ButtonValue; }; - static const EJoyAxis DefaultAxes[5]; int DeviceIndex; SDL_Joystick *Device; @@ -273,9 +279,6 @@ protected: friend class SDLInputJoystickManager; }; -// [Nash 4 Feb 2024] seems like on Linux, the third axis is actually the Left Trigger, resulting in the player uncontrollably looking upwards. -const EJoyAxis SDLInputJoystick::DefaultAxes[5] = {JOYAXIS_Side, JOYAXIS_Forward, JOYAXIS_None, JOYAXIS_Yaw, JOYAXIS_Pitch}; - class SDLInputJoystickManager { public: @@ -296,7 +299,7 @@ public: delete Joysticks[i]; } - void AddAxes(float axes[NUM_JOYAXIS]) + void AddAxes(float axes[NUM_KEYS]) { for(unsigned int i = 0;i < Joysticks.Size();i++) Joysticks[i]->AddAxes(axes); @@ -344,9 +347,9 @@ void I_GetJoysticks(TArray &sticks) JoystickManager->GetDevices(sticks); } -void I_GetAxes(float axes[NUM_JOYAXIS]) +void I_GetAxes(float axes[NUM_KEYS]) { - for (int i = 0; i < NUM_JOYAXIS; ++i) + for (int i = 0; i < NUM_KEYS; ++i) { axes[i] = 0; } diff --git a/src/common/platform/win32/i_dijoy.cpp b/src/common/platform/win32/i_dijoy.cpp index 33c4574c97..2ee4dd1ec4 100644 --- a/src/common/platform/win32/i_dijoy.cpp +++ b/src/common/platform/win32/i_dijoy.cpp @@ -158,7 +158,7 @@ public: bool GetDevice(); void ProcessInput(); - void AddAxes(float axes[NUM_JOYAXIS]); + void AddAxes(float axes[NUM_KEYS]); // IJoystickConfig interface FString GetName(); @@ -167,17 +167,14 @@ public: int GetNumAxes(); float GetAxisDeadZone(int axis); - EJoyAxis GetAxisMap(int axis); const char *GetAxisName(int axis); float GetAxisScale(int axis); void SetAxisDeadZone(int axis, float deadzone); - void SetAxisMap(int axis, EJoyAxis gameaxis); void SetAxisScale(int axis, float scale); bool IsSensitivityDefault(); bool IsAxisDeadZoneDefault(int axis); - bool IsAxisMapDefault(int axis); bool IsAxisScaleDefault(int axis); bool GetEnabled(); @@ -201,7 +198,7 @@ protected: float Value; float DeadZone, DefaultDeadZone; float Multiplier, DefaultMultiplier; - EJoyAxis GameAxis, DefaultGameAxis; + int Keys[2]; // 0: positive, 1: negative uint8_t ButtonValue; }; struct ButtonInfo @@ -244,7 +241,7 @@ public: bool GetDevice(); void ProcessInput(); - void AddAxes(float axes[NUM_JOYAXIS]); + void AddAxes(float axes[NUM_KEYS]); void GetDevices(TArray &sticks); IJoystickConfig *Rescan(); @@ -450,6 +447,9 @@ void FDInputJoystick::ProcessInput() double axisval; uint8_t buttonstate = 0; + info->Keys[0] = KEY_JOYAXIS1PLUS + (i * 2); + info->Keys[1] = KEY_JOYAXIS1PLUS + (i * 2) + 1; + // Scale to [-1.0, 1.0] axisval = (value - info->Min) * 2.0 / (info->Max - info->Min) - 1.0; // Cancel out dead zone @@ -512,12 +512,27 @@ void FDInputJoystick::ProcessInput() // //=========================================================================== -void FDInputJoystick::AddAxes(float axes[NUM_JOYAXIS]) +void FDInputJoystick::AddAxes(float axes[NUM_KEYS]) { for (unsigned i = 0; i < Axes.Size(); ++i) { // Add to the game axis. - axes[Axes[i].GameAxis] -= float(Axes[i].Value * Multiplier * Axes[i].Multiplier); + float axis_value = float(Axes[i].Value * Multiplier * Axes[i].Multiplier); + int axis_key = 0; + + if (axis_value > 0.0f) + { + axis_key = Axes[i].Keys[0]; + } + else if (axis_value < 0.0f) + { + axis_key = Axes[i].Keys[1]; + } + + if (axis_key > 0 && axis_key < NUM_KEYS) + { + axes[axis_key] += fabs(axis_value); + } } } @@ -593,7 +608,6 @@ BOOL CALLBACK FDInputJoystick::EnumObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpd info.Ofs = 0; info.Min = diprg.lMin; info.Max = diprg.lMax; - info.GameAxis = JOYAXIS_None; info.Value = 0; info.ButtonValue = 0; joy->Axes.Push(info); @@ -766,45 +780,18 @@ void FDInputJoystick::SetDefaultConfig() { Axes[i].DeadZone = DEFAULT_DEADZONE; Axes[i].Multiplier = 1; - Axes[i].GameAxis = JOYAXIS_None; } // Triggers on a 360 controller have a much smaller deadzone. if (Axes.Size() == 5 && Axes[4].Guid == GUID_ZAxis) { Axes[4].DeadZone = 30 / 256.f; } - // Two axes? Horizontal is yaw and vertical is forward. - if (Axes.Size() == 2) - { - Axes[0].GameAxis = JOYAXIS_Yaw; - Axes[1].GameAxis = JOYAXIS_Forward; - } - // Three axes? First two are movement, third is yaw. - else if (Axes.Size() >= 3) - { - Axes[0].GameAxis = JOYAXIS_Side; - Axes[1].GameAxis = JOYAXIS_Forward; - Axes[2].GameAxis = JOYAXIS_Yaw; - // Four axes? First two are movement, last two are looking around. - if (Axes.Size() >= 4) - { - Axes[3].GameAxis = JOYAXIS_Pitch; Axes[3].Multiplier = 0.75f; - // Five axes? Use the fifth one for moving up and down. - if (Axes.Size() >= 5) - { - Axes[4].GameAxis = JOYAXIS_Up; - } - } - } - // If there is only one axis, then we make no assumptions about how - // the user might want to use it. // Preserve defaults for config saving. for (i = 0; i < Axes.Size(); ++i) { Axes[i].DefaultDeadZone = Axes[i].DeadZone; Axes[i].DefaultMultiplier = Axes[i].Multiplier; - Axes[i].DefaultGameAxis = Axes[i].GameAxis; } } @@ -878,21 +865,6 @@ float FDInputJoystick::GetAxisDeadZone(int axis) return Axes[axis].DeadZone; } -//=========================================================================== -// -// FDInputJoystick :: GetAxisMap -// -//=========================================================================== - -EJoyAxis FDInputJoystick::GetAxisMap(int axis) -{ - if (unsigned(axis) >= Axes.Size()) - { - return JOYAXIS_None; - } - return Axes[axis].GameAxis; -} - //=========================================================================== // // FDInputJoystick :: GetAxisName @@ -937,20 +909,6 @@ void FDInputJoystick::SetAxisDeadZone(int axis, float deadzone) } } -//=========================================================================== -// -// FDInputJoystick :: SetAxisMap -// -//=========================================================================== - -void FDInputJoystick::SetAxisMap(int axis, EJoyAxis gameaxis) -{ - if (unsigned(axis) < Axes.Size()) - { - Axes[axis].GameAxis = (unsigned(gameaxis) < NUM_JOYAXIS) ? gameaxis : JOYAXIS_None; - } -} - //=========================================================================== // // FDInputJoystick :: SetAxisScale @@ -1017,21 +975,6 @@ void FDInputJoystick::SetEnabled(bool enabled) Enabled = enabled; } -//=========================================================================== -// -// FDInputJoystick :: IsAxisMapDefault -// -//=========================================================================== - -bool FDInputJoystick::IsAxisMapDefault(int axis) -{ - if (unsigned(axis) < Axes.Size()) - { - return Axes[axis].GameAxis == Axes[axis].DefaultGameAxis; - } - return true; -} - //=========================================================================== // // FDInputJoystickManager - Constructor @@ -1099,7 +1042,7 @@ void FDInputJoystickManager::ProcessInput() // //=========================================================================== -void FDInputJoystickManager :: AddAxes(float axes[NUM_JOYAXIS]) +void FDInputJoystickManager :: AddAxes(float axes[NUM_KEYS]) { for (unsigned i = 0; i < Devices.Size(); ++i) { diff --git a/src/common/platform/win32/i_input.cpp b/src/common/platform/win32/i_input.cpp index fb6ff300f2..4affab854b 100644 --- a/src/common/platform/win32/i_input.cpp +++ b/src/common/platform/win32/i_input.cpp @@ -631,14 +631,15 @@ void I_StartFrame () } } -void I_GetAxes(float axes[NUM_JOYAXIS]) +void I_GetAxes(float axes[NUM_KEYS]) { int i; - for (i = 0; i < NUM_JOYAXIS; ++i) + for (i = 0; i < NUM_KEYS; ++i) { - axes[i] = 0; + axes[i] = 0.0f; } + if (use_joystick) { for (i = 0; i < NUM_JOYDEVICES; ++i) diff --git a/src/common/platform/win32/i_input.h b/src/common/platform/win32/i_input.h index 16a276ce83..3942944a3a 100644 --- a/src/common/platform/win32/i_input.h +++ b/src/common/platform/win32/i_input.h @@ -118,7 +118,7 @@ protected: class FJoystickCollection : public FInputDevice { public: - virtual void AddAxes(float axes[NUM_JOYAXIS]) = 0; + virtual void AddAxes(float axes[NUM_KEYS]) = 0; virtual void GetDevices(TArray &sticks) = 0; virtual IJoystickConfig *Rescan() = 0; }; diff --git a/src/common/platform/win32/i_rawps2.cpp b/src/common/platform/win32/i_rawps2.cpp index 2f89739bd7..30f175672e 100644 --- a/src/common/platform/win32/i_rawps2.cpp +++ b/src/common/platform/win32/i_rawps2.cpp @@ -91,7 +91,7 @@ public: ~FRawPS2Controller(); bool ProcessInput(RAWHID *raw, int code); - void AddAxes(float axes[NUM_JOYAXIS]); + void AddAxes(float axes[NUM_KEYS]); bool IsConnected() { return Connected; } // IJoystickConfig interface @@ -101,17 +101,14 @@ public: int GetNumAxes(); float GetAxisDeadZone(int axis); - EJoyAxis GetAxisMap(int axis); const char *GetAxisName(int axis); float GetAxisScale(int axis); void SetAxisDeadZone(int axis, float deadzone); - void SetAxisMap(int axis, EJoyAxis gameaxis); void SetAxisScale(int axis, float scale); bool IsSensitivityDefault(); bool IsAxisDeadZoneDefault(int axis); - bool IsAxisMapDefault(int axis); bool IsAxisScaleDefault(int axis); bool GetEnabled(); @@ -130,12 +127,11 @@ protected: float Value; float DeadZone; float Multiplier; - EJoyAxis GameAxis; + int Keys[2]; uint8_t ButtonValue; }; struct DefaultAxisConfig { - EJoyAxis GameAxis; float Multiplier; }; enum @@ -179,7 +175,7 @@ public: bool GetDevice(); bool ProcessRawInput(RAWINPUT *raw, int code); - void AddAxes(float axes[NUM_JOYAXIS]); + void AddAxes(float axes[NUM_KEYS]); void GetDevices(TArray &sticks); IJoystickConfig *Rescan(); @@ -357,11 +353,11 @@ static const char *AxisNames[] = FRawPS2Controller::DefaultAxisConfig FRawPS2Controller::DefaultAxes[NUM_AXES] = { - // Game axis, multiplier - { JOYAXIS_Side, 1 }, // ThumbLX - { JOYAXIS_Forward, 1 }, // ThumbLY - { JOYAXIS_Yaw, 1 }, // ThumbRX - { JOYAXIS_Pitch, 0.75 }, // ThumbRY + // multiplier + { 1 }, // ThumbLX + { 1 }, // ThumbLY + { 1 }, // ThumbRX + { 0.75 }, // ThumbRY }; // CODE -------------------------------------------------------------------- @@ -548,6 +544,11 @@ void FRawPS2Controller::ProcessThumbstick(int value1, AxisInfo *axis1, int value uint8_t buttonstate; double axisval1, axisval2; + axis1->Keys[0] = base; + axis1->Keys[1] = base + 1; + axis2->Keys[0] = base + 2; + axis2->Keys[1] = base + 3; + axisval1 = value1 * (2.0 / 255) - 1.0; axisval2 = value2 * (2.0 / 255) - 1.0; axisval1 = Joy_RemoveDeadZone(axisval1, axis1->DeadZone, NULL); @@ -627,12 +628,27 @@ void FRawPS2Controller::NeutralInput() // //========================================================================== -void FRawPS2Controller::AddAxes(float axes[NUM_JOYAXIS]) +void FRawPS2Controller::AddAxes(float axes[NUM_KEYS]) { - // Add to game axes. for (int i = 0; i < NUM_AXES; ++i) { - axes[Axes[i].GameAxis] -= float(Axes[i].Value * Multiplier * Axes[i].Multiplier); + // Add to the game axis. + float axis_value = float(Axes[i].Value * Multiplier * Axes[i].Multiplier); + int axis_key = 0; + + if (axis_value > 0.0f) + { + axis_key = Axes[i].Keys[0]; + } + else if (axis_value < 0.0f) + { + axis_key = Axes[i].Keys[1]; + } + + if (axis_key > 0 && axis_key < NUM_KEYS) + { + axes[axis_key] += fabs(axis_value); + } } } @@ -648,7 +664,6 @@ void FRawPS2Controller::SetDefaultConfig() for (int i = 0; i < NUM_AXES; ++i) { Axes[i].DeadZone = DEFAULT_DEADZONE; - Axes[i].GameAxis = DefaultAxes[i].GameAxis; Axes[i].Multiplier = DefaultAxes[i].Multiplier; } } @@ -741,21 +756,6 @@ float FRawPS2Controller::GetAxisDeadZone(int axis) return 0; } -//========================================================================== -// -// FRawPS2Controller :: GetAxisMap -// -//========================================================================== - -EJoyAxis FRawPS2Controller::GetAxisMap(int axis) -{ - if (unsigned(axis) < NUM_AXES) - { - return Axes[axis].GameAxis; - } - return JOYAXIS_None; -} - //========================================================================== // // FRawPS2Controller :: GetAxisName @@ -800,20 +800,6 @@ void FRawPS2Controller::SetAxisDeadZone(int axis, float deadzone) } } -//========================================================================== -// -// FRawPS2Controller :: SetAxisMap -// -//========================================================================== - -void FRawPS2Controller::SetAxisMap(int axis, EJoyAxis gameaxis) -{ - if (unsigned(axis) < NUM_AXES) - { - Axes[axis].GameAxis = (unsigned(gameaxis) < NUM_JOYAXIS) ? gameaxis : JOYAXIS_None; - } -} - //========================================================================== // // FRawPS2Controller :: SetAxisScale @@ -880,21 +866,6 @@ void FRawPS2Controller::SetEnabled(bool enabled) Enabled = enabled; } -//=========================================================================== -// -// FRawPS2Controller :: IsAxisMapDefault -// -//=========================================================================== - -bool FRawPS2Controller::IsAxisMapDefault(int axis) -{ - if (unsigned(axis) < NUM_AXES) - { - return Axes[axis].GameAxis == DefaultAxes[axis].GameAxis; - } - return true; -} - //========================================================================== // // FRawPS2Manager - Constructor @@ -956,7 +927,7 @@ bool FRawPS2Manager::GetDevice() // //=========================================================================== -void FRawPS2Manager::AddAxes(float axes[NUM_JOYAXIS]) +void FRawPS2Manager::AddAxes(float axes[NUM_KEYS]) { for (unsigned i = 0; i < Devices.Size(); ++i) { diff --git a/src/common/platform/win32/i_xinput.cpp b/src/common/platform/win32/i_xinput.cpp index 0f3c192378..30148d6ae3 100644 --- a/src/common/platform/win32/i_xinput.cpp +++ b/src/common/platform/win32/i_xinput.cpp @@ -81,7 +81,7 @@ public: ~FXInputController(); void ProcessInput(); - void AddAxes(float axes[NUM_JOYAXIS]); + void AddAxes(float axes[NUM_KEYS]); bool IsConnected() { return Connected; } // IJoystickConfig interface @@ -91,17 +91,14 @@ public: int GetNumAxes(); float GetAxisDeadZone(int axis); - EJoyAxis GetAxisMap(int axis); const char *GetAxisName(int axis); float GetAxisScale(int axis); void SetAxisDeadZone(int axis, float deadzone); - void SetAxisMap(int axis, EJoyAxis gameaxis); void SetAxisScale(int axis, float scale); bool IsSensitivityDefault(); bool IsAxisDeadZoneDefault(int axis); - bool IsAxisMapDefault(int axis); bool IsAxisScaleDefault(int axis); bool GetEnabled(); @@ -120,13 +117,12 @@ protected: float Value; float DeadZone; float Multiplier; - EJoyAxis GameAxis; + int Keys[2]; uint8_t ButtonValue; }; struct DefaultAxisConfig { float DeadZone; - EJoyAxis GameAxis; float Multiplier; }; enum @@ -166,7 +162,7 @@ public: bool GetDevice(); void ProcessInput(); bool WndProcHook(HWND hWnd, uint32_t message, WPARAM wParam, LPARAM lParam, LRESULT *result); - void AddAxes(float axes[NUM_JOYAXIS]); + void AddAxes(float axes[NUM_KEYS]); void GetDevices(TArray &sticks); IJoystickConfig *Rescan(); @@ -211,13 +207,13 @@ static const char *AxisNames[] = FXInputController::DefaultAxisConfig FXInputController::DefaultAxes[NUM_AXES] = { - // Dead zone, game axis, multiplier - { XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE / 32768.f, JOYAXIS_Side, 1 }, // ThumbLX - { XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE / 32768.f, JOYAXIS_Forward, 1 }, // ThumbLY - { XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE / 32768.f, JOYAXIS_Yaw, 1 }, // ThumbRX - { XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE / 32768.f, JOYAXIS_Pitch, 0.75 }, // ThumbRY - { XINPUT_GAMEPAD_TRIGGER_THRESHOLD / 256.f, JOYAXIS_None, 0 }, // LeftTrigger - { XINPUT_GAMEPAD_TRIGGER_THRESHOLD / 256.f, JOYAXIS_None, 0 } // RightTrigger + // Dead zone, multiplier + { XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE / 32768.f, 1 }, // ThumbLX + { XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE / 32768.f, 1 }, // ThumbLY + { XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE / 32768.f, 1 }, // ThumbRX + { XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE / 32768.f, 0.75 }, // ThumbRY + { XINPUT_GAMEPAD_TRIGGER_THRESHOLD / 256.f, 0 }, // LeftTrigger + { XINPUT_GAMEPAD_TRIGGER_THRESHOLD / 256.f, 0 } // RightTrigger }; // CODE -------------------------------------------------------------------- @@ -323,6 +319,11 @@ void FXInputController::ProcessThumbstick(int value1, AxisInfo *axis1, uint8_t buttonstate; double axisval1, axisval2; + axis1->Keys[0] = base; + axis1->Keys[1] = base + 1; + axis2->Keys[0] = base + 2; + axis2->Keys[1] = base + 3; + axisval1 = (value1 - SHRT_MIN) * 2.0 / 65536 - 1.0; axisval2 = (value2 - SHRT_MIN) * 2.0 / 65536 - 1.0; axisval1 = Joy_RemoveDeadZone(axisval1, axis1->DeadZone, NULL); @@ -350,6 +351,9 @@ void FXInputController::ProcessTrigger(int value, AxisInfo *axis, int base) uint8_t buttonstate; double axisval; + axis->Keys[0] = base; + axis->Keys[1] = 0; + axisval = Joy_RemoveDeadZone(value / 256.0, axis->DeadZone, &buttonstate); Joy_GenerateButtonEvents(axis->ButtonValue, buttonstate, 1, base); axis->ButtonValue = buttonstate; @@ -414,12 +418,27 @@ void FXInputController::Detached() // //========================================================================== -void FXInputController::AddAxes(float axes[NUM_JOYAXIS]) +void FXInputController::AddAxes(float axes[NUM_KEYS]) { - // Add to game axes. for (int i = 0; i < NUM_AXES; ++i) { - axes[Axes[i].GameAxis] -= float(Axes[i].Value * Multiplier * Axes[i].Multiplier); + // Add to the game axis. + float axis_value = float(Axes[i].Value * Multiplier * Axes[i].Multiplier); + int axis_key = 0; + + if (axis_value > 0.0f) + { + axis_key = Axes[i].Keys[0]; + } + else if (axis_value < 0.0f) + { + axis_key = Axes[i].Keys[1]; + } + + if (axis_key > 0 && axis_key < NUM_KEYS) + { + axes[axis_key] += fabs(axis_value); + } } } @@ -435,7 +454,6 @@ void FXInputController::SetDefaultConfig() for (int i = 0; i < NUM_AXES; ++i) { Axes[i].DeadZone = DefaultAxes[i].DeadZone; - Axes[i].GameAxis = DefaultAxes[i].GameAxis; Axes[i].Multiplier = DefaultAxes[i].Multiplier; } } @@ -523,21 +541,6 @@ float FXInputController::GetAxisDeadZone(int axis) return 0; } -//========================================================================== -// -// FXInputController :: GetAxisMap -// -//========================================================================== - -EJoyAxis FXInputController::GetAxisMap(int axis) -{ - if (unsigned(axis) < NUM_AXES) - { - return Axes[axis].GameAxis; - } - return JOYAXIS_None; -} - //========================================================================== // // FXInputController :: GetAxisName @@ -582,20 +585,6 @@ void FXInputController::SetAxisDeadZone(int axis, float deadzone) } } -//========================================================================== -// -// FXInputController :: SetAxisMap -// -//========================================================================== - -void FXInputController::SetAxisMap(int axis, EJoyAxis gameaxis) -{ - if (unsigned(axis) < NUM_AXES) - { - Axes[axis].GameAxis = (unsigned(gameaxis) < NUM_JOYAXIS) ? gameaxis : JOYAXIS_None; - } -} - //========================================================================== // // FXInputController :: SetAxisScale @@ -662,21 +651,6 @@ void FXInputController::SetEnabled(bool enabled) Enabled = enabled; } -//=========================================================================== -// -// FXInputController :: IsAxisMapDefault -// -//=========================================================================== - -bool FXInputController::IsAxisMapDefault(int axis) -{ - if (unsigned(axis) < NUM_AXES) - { - return Axes[axis].GameAxis == DefaultAxes[axis].GameAxis; - } - return true; -} - //========================================================================== // // FXInputManager - Constructor @@ -766,7 +740,7 @@ void FXInputManager::ProcessInput() // //=========================================================================== -void FXInputManager::AddAxes(float axes[NUM_JOYAXIS]) +void FXInputManager::AddAxes(float axes[NUM_KEYS]) { for (int i = 0; i < XUSER_MAX_COUNT; ++i) { diff --git a/src/g_game.cpp b/src/g_game.cpp index 30274dd930..d43b52a21c 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -613,6 +613,9 @@ void G_BuildTiccmd (usercmd_t *cmd) base = G_BaseTiccmd (); *cmd = *base; + // Update axis polling for the button map + buttonMap.GetAxes(); + strafe = buttonMap.ButtonDown(Button_Strafe); speed = buttonMap.ButtonDown(Button_Speed) ^ (int)cl_run; @@ -621,7 +624,7 @@ void G_BuildTiccmd (usercmd_t *cmd) // [RH] only use two stage accelerative turning on the keyboard // and not the joystick, since we treat the joystick as // the analog device it is. - if (buttonMap.ButtonDown(Button_Left) || buttonMap.ButtonDown(Button_Right)) + if (buttonMap.DigitalButtonDown(Button_Left) || buttonMap.DigitalButtonDown(Button_Right)) turnheld += TicDup; else turnheld = 0; @@ -629,9 +632,9 @@ void G_BuildTiccmd (usercmd_t *cmd) // let movement keys cancel each other out if (strafe) { - if (buttonMap.ButtonDown(Button_Right)) + if (buttonMap.DigitalButtonDown(Button_Right)) side += sidemove[speed]; - if (buttonMap.ButtonDown(Button_Left)) + if (buttonMap.DigitalButtonDown(Button_Left)) side -= sidemove[speed]; } else @@ -641,48 +644,48 @@ void G_BuildTiccmd (usercmd_t *cmd) if (turnheld < SLOWTURNTICS) tspeed += 2; // slow turn - if (buttonMap.ButtonDown(Button_Right)) + if (buttonMap.DigitalButtonDown(Button_Right)) { G_AddViewAngle (*angleturn[tspeed]); } - if (buttonMap.ButtonDown(Button_Left)) + if (buttonMap.DigitalButtonDown(Button_Left)) { G_AddViewAngle (-*angleturn[tspeed]); } } - if (buttonMap.ButtonDown(Button_LookUp)) + if (buttonMap.DigitalButtonDown(Button_LookUp)) { G_AddViewPitch (lookspeed[speed]); } - if (buttonMap.ButtonDown(Button_LookDown)) + if (buttonMap.DigitalButtonDown(Button_LookDown)) { G_AddViewPitch (-lookspeed[speed]); } - if (buttonMap.ButtonDown(Button_MoveUp)) + if (buttonMap.DigitalButtonDown(Button_MoveUp)) fly += flyspeed[speed]; - if (buttonMap.ButtonDown(Button_MoveDown)) + if (buttonMap.DigitalButtonDown(Button_MoveDown)) fly -= flyspeed[speed]; if (buttonMap.ButtonDown(Button_Klook)) { - if (buttonMap.ButtonDown(Button_Forward)) + if (buttonMap.DigitalButtonDown(Button_Forward)) G_AddViewPitch (lookspeed[speed]); - if (buttonMap.ButtonDown(Button_Back)) + if (buttonMap.DigitalButtonDown(Button_Back)) G_AddViewPitch (-lookspeed[speed]); } else { - if (buttonMap.ButtonDown(Button_Forward)) + if (buttonMap.DigitalButtonDown(Button_Forward)) forward += forwardmove[speed]; - if (buttonMap.ButtonDown(Button_Back)) + if (buttonMap.DigitalButtonDown(Button_Back)) forward -= forwardmove[speed]; } - if (buttonMap.ButtonDown(Button_MoveRight)) + if (buttonMap.DigitalButtonDown(Button_MoveRight)) side += sidemove[speed]; - if (buttonMap.ButtonDown(Button_MoveLeft)) + if (buttonMap.DigitalButtonDown(Button_MoveLeft)) side -= sidemove[speed]; // buttons @@ -714,35 +717,37 @@ void G_BuildTiccmd (usercmd_t *cmd) if (buttonMap.ButtonDown(Button_ShowScores)) cmd->buttons |= BT_SHOWSCORES; if (speed) cmd->buttons |= BT_RUN; - // Handle joysticks/game controllers. - float joyaxes[NUM_JOYAXIS]; - - I_GetAxes(joyaxes); - // Remap some axes depending on button state. + float axis_yaw = buttonMap.AnalogButtonDown(Button_Left) - buttonMap.AnalogButtonDown(Button_Right); + float axis_pitch = buttonMap.AnalogButtonDown(Button_LookUp) - buttonMap.AnalogButtonDown(Button_LookDown); + float axis_forward = buttonMap.AnalogButtonDown(Button_Forward) - buttonMap.AnalogButtonDown(Button_Back); + float axis_side = buttonMap.AnalogButtonDown(Button_MoveLeft) - buttonMap.AnalogButtonDown(Button_MoveRight); + float axis_up = buttonMap.AnalogButtonDown(Button_MoveUp) - buttonMap.AnalogButtonDown(Button_MoveDown); + if (buttonMap.ButtonDown(Button_Strafe) || (buttonMap.ButtonDown(Button_Mlook) && lookstrafe)) { - joyaxes[JOYAXIS_Side] = joyaxes[JOYAXIS_Yaw]; - joyaxes[JOYAXIS_Yaw] = 0; + axis_side = axis_yaw; + axis_yaw = 0.0f; } + if (buttonMap.ButtonDown(Button_Mlook)) { - joyaxes[JOYAXIS_Pitch] = joyaxes[JOYAXIS_Forward]; - joyaxes[JOYAXIS_Forward] = 0; + axis_pitch = axis_forward; + axis_forward = 0.0f; } - if (joyaxes[JOYAXIS_Pitch] != 0) + if (axis_pitch != 0) { - G_AddViewPitch(joyint(joyaxes[JOYAXIS_Pitch] * 2048)); + G_AddViewPitch(joyint(axis_pitch * 2048)); } - if (joyaxes[JOYAXIS_Yaw] != 0) + if (axis_yaw != 0) { - G_AddViewAngle(joyint(-1280 * joyaxes[JOYAXIS_Yaw])); + G_AddViewAngle(joyint(-1280 * axis_yaw)); } - side -= joyint(sidemove[speed] * joyaxes[JOYAXIS_Side]); - forward += joyint(joyaxes[JOYAXIS_Forward] * forwardmove[speed]); - fly += joyint(joyaxes[JOYAXIS_Up] * 2048); + side -= joyint(sidemove[speed] * axis_side); + forward += joyint(axis_forward * forwardmove[speed]); + fly += joyint(axis_up * 2048); // Handle mice. if (!buttonMap.ButtonDown(Button_Mlook) && !freelook) diff --git a/wadsrc/static/zscript/engine/ui/menu/joystickmenu.zs b/wadsrc/static/zscript/engine/ui/menu/joystickmenu.zs index 02669c1a3a..1d7e5712fc 100644 --- a/wadsrc/static/zscript/engine/ui/menu/joystickmenu.zs +++ b/wadsrc/static/zscript/engine/ui/menu/joystickmenu.zs @@ -334,8 +334,6 @@ class OptionMenuItemJoyConfigMenu : OptionMenuItemSubmenu it = new("OptionMenuItemStaticText").Init(" ", false); opt.mItems.Push(it); - it = new("OptionMenuItemJoyMap").Init(joy.GetAxisName(i), i, "JoyAxisMapNames", false, joy); - opt.mItems.Push(it); it = new("OptionMenuSliderJoyScale").Init("$JOYMNU_OVRSENS", i, 0, 4, 0.1, 3, joy); opt.mItems.Push(it); it = new("OptionMenuItemInverter").Init("$JOYMNU_INVERT", i, false, joy); From 3e7ebadc42eeae15dd95f0a185af4b973b67bfb6 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 30 Jan 2025 23:19:58 -0500 Subject: [PATCH 2/2] Add client cvar for strafe running on analog stick --- src/g_game.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/g_game.cpp b/src/g_game.cpp index d43b52a21c..f0c3d71214 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -210,7 +210,9 @@ CVAR (Bool, freelook, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) // Always mlook? CVAR (Bool, lookstrafe, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) // Always strafe with mouse? CVAR (Float, m_forward, 1.f, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) CVAR (Float, m_side, 2.f, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) - + +CVAR (Bool, cl_analogstraferun, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) + int turnheld; // for accelerative turning EXTERN_CVAR (Bool, invertmouse) @@ -736,6 +738,30 @@ void G_BuildTiccmd (usercmd_t *cmd) axis_forward = 0.0f; } + if (cl_analogstraferun) + { + // Rescale diagonal analog input from roughly [0.77, 0.77] to [1.0, 1.0], + // which enables analog sticks to be able to strafe run like a keyboard can. + + // Disabled by default because it's inaccurate to how Linux Doom itself + // handled analog input, some analog sticks may be able to actually reach 1.0, + // some might remap a D-Pad to the stick, so on... + + const float sqrtOf2Frac = 0.41421356237309504880; // sqrt(2)'s fractional value + + float move_min = min(fabs(axis_side), fabs(axis_forward)); + float move_max = max(fabs(axis_side), fabs(axis_forward)); + + float scale = 1.0f; + if (move_max > EQUAL_EPSILON) + { + scale += (move_min / move_max) * sqrtOf2Frac; + } + + axis_forward = std::clamp(axis_forward * scale, -1.f, 1.f); + axis_side = std::clamp(axis_side * scale, -1.f, 1.f); + } + if (axis_pitch != 0) { G_AddViewPitch(joyint(axis_pitch * 2048));