foxygit / doom Log in
commit 0229002e75ce6b0a374e78f80cbff6db1a8d14b6
Author:     Michael Day <contact@michaelcday.com>
AuthorDate: Mon Aug 14 11:54:15 2023 -0400
Commit:     Turo Lamminen <turol@users.noreply.github.com>
CommitDate: Wed Aug 23 11:42:50 2023 +0300

    Add configurable joystick axis dead zones
---
 src/i_joystick.c        | 55 +++++++++++++++++++++++++++++++++----------------
 src/m_config.c          | 28 +++++++++++++++++++++++++
 src/setup/joystick.c    | 15 ++++++++++++++
 src/setup/txt_joyaxis.c | 18 ++++++++++------
 src/setup/txt_joyaxis.h |  4 ++--
 5 files changed, 94 insertions(+), 26 deletions(-)

diff --git a/src/i_joystick.c b/src/i_joystick.c
index f2b6e6f9..97aee817 100644
--- a/src/i_joystick.c
+++ b/src/i_joystick.c
@@ -32,11 +32,6 @@
 #include "m_config.h"
 #include "m_misc.h"

-// When an axis is within the dead zone, it is set to zero.
-// This is 5% of the full range:
-
-#define DEAD_ZONE (32768 / 3)
-
 static SDL_GameController *gamepad = NULL;
 static SDL_Joystick *joystick = NULL;

@@ -78,6 +73,13 @@ static int joystick_strafe_invert = 0;
 static int joystick_look_axis = -1;
 static int joystick_look_invert = 0;

+// Configurable dead zone for each axis, specified as a percentage of the axis
+// max value.
+static int joystick_x_dead_zone = 33;
+static int joystick_y_dead_zone = 33;
+static int joystick_strafe_dead_zone = 33;
+static int joystick_look_dead_zone = 33;
+
 // Virtual to physical button joystick button mapping. By default this
 // is a straight mapping.
 static int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS] = {
@@ -274,7 +276,7 @@ static int GetButtonsStateGamepad(void)

 // Read the state of an axis, inverting if necessary.

-static int GetAxisStateGamepad(int axis, int invert)
+static int GetAxisStateGamepad(int axis, int invert, int dead_zone)
 {
     int result;

@@ -285,9 +287,12 @@ static int GetAxisStateGamepad(int axis, int invert)
         return 0;
     }

+    // Dead zone is expressed as percentage of axis max value
+    dead_zone = 32768 * dead_zone / 100;
+
     result = SDL_GameControllerGetAxis(gamepad, axis);

-    if (result < DEAD_ZONE && result > -DEAD_ZONE)
+    if (result < dead_zone && result > -dead_zone)
     {
         result = 0;
     }
@@ -308,12 +313,15 @@ void I_UpdateGamepad(void)

         ev.type = ev_joystick;
         ev.data1 = GetButtonsStateGamepad();
-        ev.data2 = GetAxisStateGamepad(joystick_x_axis, joystick_x_invert);
-        ev.data3 = GetAxisStateGamepad(joystick_y_axis, joystick_y_invert);
+        ev.data2 = GetAxisStateGamepad(joystick_x_axis, joystick_x_invert,
+                                       joystick_x_dead_zone);
+        ev.data3 = GetAxisStateGamepad(joystick_y_axis, joystick_y_invert,
+                                       joystick_y_dead_zone);
         ev.data4 =
-            GetAxisStateGamepad(joystick_strafe_axis, joystick_strafe_invert);
-        ev.data5 =
-            GetAxisStateGamepad(joystick_look_axis, joystick_look_invert);
+            GetAxisStateGamepad(joystick_strafe_axis, joystick_strafe_invert,
+                                joystick_strafe_dead_zone);
+        ev.data5 = GetAxisStateGamepad(joystick_look_axis, joystick_look_invert,
+                                       joystick_look_dead_zone);

         D_PostEvent(&ev);
     }
@@ -535,7 +543,7 @@ static int GetButtonsState(void)

 // Read the state of an axis, inverting if necessary.

-static int GetAxisState(int axis, int invert)
+static int GetAxisState(int axis, int invert, int dead_zone)
 {
     int result;

@@ -594,7 +602,10 @@ static int GetAxisState(int axis, int invert)
     {
         result = SDL_JoystickGetAxis(joystick, axis);

-        if (result < DEAD_ZONE && result > -DEAD_ZONE)
+        // Dead zone is expressed as percentage of axis max value
+        dead_zone = 32768 * dead_zone / 100;
+
+        if (result < dead_zone && result > -dead_zone)
         {
             result = 0;
         }
@@ -622,10 +633,14 @@ void I_UpdateJoystick(void)

         ev.type = ev_joystick;
         ev.data1 = GetButtonsState();
-        ev.data2 = GetAxisState(joystick_x_axis, joystick_x_invert);
-        ev.data3 = GetAxisState(joystick_y_axis, joystick_y_invert);
-        ev.data4 = GetAxisState(joystick_strafe_axis, joystick_strafe_invert);
-        ev.data5 = GetAxisState(joystick_look_axis, joystick_look_invert);
+        ev.data2 = GetAxisState(joystick_x_axis, joystick_x_invert,
+                                joystick_x_dead_zone);
+        ev.data3 = GetAxisState(joystick_y_axis, joystick_y_invert,
+                                joystick_y_dead_zone);
+        ev.data4 = GetAxisState(joystick_strafe_axis, joystick_strafe_invert,
+                                joystick_strafe_dead_zone);
+        ev.data5 = GetAxisState(joystick_look_axis, joystick_look_invert,
+                                joystick_look_dead_zone);

         D_PostEvent(&ev);
     }
@@ -648,6 +663,10 @@ void I_BindJoystickVariables(void)
     M_BindIntVariable("joystick_strafe_invert",&joystick_strafe_invert);
     M_BindIntVariable("joystick_look_axis",    &joystick_look_axis);
     M_BindIntVariable("joystick_look_invert",  &joystick_look_invert);
+    M_BindIntVariable("joystick_x_dead_zone", &joystick_x_dead_zone);
+    M_BindIntVariable("joystick_y_dead_zone", &joystick_y_dead_zone);
+    M_BindIntVariable("joystick_strafe_dead_zone", &joystick_strafe_dead_zone);
+    M_BindIntVariable("joystick_look_dead_zone", &joystick_look_dead_zone);

     for (i = 0; i < NUM_VIRTUAL_BUTTONS; ++i)
     {
diff --git a/src/m_config.c b/src/m_config.c
index 109601b0..7c3e0e8a 100644
--- a/src/m_config.c
+++ b/src/m_config.c
@@ -1382,6 +1382,34 @@ static default_t extra_defaults_list[] =

     CONFIG_VARIABLE_INT(gamepad_type),

+    //!
+    // Joystick x axis dead zone, specified as a percentage of the axis max
+    // value.
+    //
+
+    CONFIG_VARIABLE_INT(joystick_x_dead_zone),
+
+    //!
+    // Joystick y axis dead zone, specified as a percentage of the axis max
+    // value.
+    //
+
+    CONFIG_VARIABLE_INT(joystick_y_dead_zone),
+
+    //!
+    // Joystick strafe axis dead zone, specified as a percentage of the axis
+    // max value.
+    //
+
+    CONFIG_VARIABLE_INT(joystick_strafe_dead_zone),
+
+    //!
+    // Joystick look axis dead zone, specified as a percentage of the axis max
+    // value.
+    //
+
+    CONFIG_VARIABLE_INT(joystick_look_dead_zone),
+
     //!
     // Joystick virtual button to make the player strafe left.
     //
diff --git a/src/setup/joystick.c b/src/setup/joystick.c
index 8d787443..62589cda 100644
--- a/src/setup/joystick.c
+++ b/src/setup/joystick.c
@@ -85,6 +85,13 @@ static int joystick_strafe_invert = 0;
 static int joystick_look_axis = -1;
 static int joystick_look_invert = 0;

+// Configurable dead zone for each axis, specified as a percentage of the axis
+// max value.
+static int joystick_x_dead_zone = 33;
+static int joystick_y_dead_zone = 33;
+static int joystick_strafe_dead_zone = 33;
+static int joystick_look_dead_zone = 33;
+
 // Virtual to physical mapping.
 int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS] = {
     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
@@ -1146,6 +1153,7 @@ void ConfigJoystick(TXT_UNCAST_ARG(widget), void *user_data)
                    TXT_NewLabel("Forward/backward"),
                    y_axis_widget = TXT_NewJoystickAxis(&joystick_y_axis,
                                                        &joystick_y_invert,
+                                                       &joystick_y_dead_zone,
                                                        JOYSTICK_AXIS_VERTICAL),
                    TXT_TABLE_OVERFLOW_RIGHT,
                    TXT_TABLE_OVERFLOW_RIGHT,
@@ -1156,6 +1164,7 @@ void ConfigJoystick(TXT_UNCAST_ARG(widget), void *user_data)
                    x_axis_widget =
                         TXT_NewJoystickAxis(&joystick_x_axis,
                                             &joystick_x_invert,
+                                            &joystick_x_dead_zone,
                                             JOYSTICK_AXIS_HORIZONTAL),
                    TXT_TABLE_OVERFLOW_RIGHT,
                    TXT_TABLE_OVERFLOW_RIGHT,
@@ -1165,6 +1174,7 @@ void ConfigJoystick(TXT_UNCAST_ARG(widget), void *user_data)
                    TXT_NewLabel("Strafe left/right"),
                    TXT_NewJoystickAxis(&joystick_strafe_axis,
                                        &joystick_strafe_invert,
+                                       &joystick_strafe_dead_zone,
                                         JOYSTICK_AXIS_HORIZONTAL),
                    TXT_TABLE_OVERFLOW_RIGHT,
                    TXT_TABLE_OVERFLOW_RIGHT,
@@ -1178,6 +1188,7 @@ void ConfigJoystick(TXT_UNCAST_ARG(widget), void *user_data)
                    TXT_NewLabel("Look up/down"),
                    TXT_NewJoystickAxis(&joystick_look_axis,
                                        &joystick_look_invert,
+                                       &joystick_look_dead_zone,
                                         JOYSTICK_AXIS_VERTICAL),
                    TXT_TABLE_OVERFLOW_RIGHT,
                    TXT_TABLE_OVERFLOW_RIGHT,
@@ -1254,6 +1265,10 @@ void BindJoystickVariables(void)
     M_BindIntVariable("joystick_strafe_invert", &joystick_strafe_invert);
     M_BindIntVariable("joystick_look_axis",   &joystick_look_axis);
     M_BindIntVariable("joystick_look_invert", &joystick_look_invert);
+    M_BindIntVariable("joystick_x_dead_zone", &joystick_x_dead_zone);
+    M_BindIntVariable("joystick_y_dead_zone", &joystick_y_dead_zone);
+    M_BindIntVariable("joystick_strafe_dead_zone", &joystick_strafe_dead_zone);
+    M_BindIntVariable("joystick_look_dead_zone", &joystick_look_dead_zone);

     for (i = 0; i < NUM_VIRTUAL_BUTTONS; ++i)
     {
diff --git a/src/setup/txt_joyaxis.c b/src/setup/txt_joyaxis.c
index 59bc85aa..87de88f8 100644
--- a/src/setup/txt_joyaxis.c
+++ b/src/setup/txt_joyaxis.c
@@ -420,14 +420,19 @@ void TXT_ConfigureGamepadAxis(txt_joystick_axis_t *joystick_axis,
     // Build the prompt window.

     joystick_axis->config_window = TXT_NewWindow("Configure axis");
-    TXT_SetColumnWidths(joystick_axis->config_window, 14);
-    TXT_AddWidgets(joystick_axis->config_window, TXT_NewStrut(0, 1),
+    TXT_SetTableColumns(joystick_axis->config_window, 2);
+    TXT_SetColumnWidths(joystick_axis->config_window, 10, 5);
+    TXT_AddWidgets(joystick_axis->config_window,
                    TXT_NewCheckBox("Invert", joystick_axis->invert),
-                   TXT_NewStrut(0, 1), NULL);
+                   TXT_TABLE_EMPTY,
+                   TXT_NewLabel("Dead zone"),
+                   TXT_NewSpinControl(joystick_axis->dead_zone, 10, 90),
+                   NULL);

     TXT_SetWindowAction(joystick_axis->config_window, TXT_HORIZ_LEFT, NULL);
-    TXT_SetWindowAction(joystick_axis->config_window, TXT_HORIZ_CENTER,
-                        TXT_NewWindowAbortAction(joystick_axis->config_window));
+    TXT_SetWindowAction(
+        joystick_axis->config_window, TXT_HORIZ_CENTER,
+        TXT_NewWindowEscapeAction(joystick_axis->config_window));
     TXT_SetWindowAction(joystick_axis->config_window, TXT_HORIZ_RIGHT, NULL);
     TXT_SetWidgetAlign(joystick_axis->config_window, TXT_HORIZ_CENTER);
 }
@@ -623,7 +628,7 @@ txt_widget_class_t txt_gamepad_axis_class =
     NULL,
 };

-txt_joystick_axis_t *TXT_NewJoystickAxis(int *axis, int *invert,
+txt_joystick_axis_t *TXT_NewJoystickAxis(int *axis, int *invert, int *dead_zone,
                                          txt_joystick_axis_direction_t dir)
 {
     txt_joystick_axis_t *joystick_axis;
@@ -640,6 +645,7 @@ txt_joystick_axis_t *TXT_NewJoystickAxis(int *axis, int *invert,
     }
     joystick_axis->axis = axis;
     joystick_axis->invert = invert;
+    joystick_axis->dead_zone = dead_zone;
     joystick_axis->dir = dir;
     joystick_axis->bad_axis = NULL;

diff --git a/src/setup/txt_joyaxis.h b/src/setup/txt_joyaxis.h
index 1f41d0e8..f0527c5b 100644
--- a/src/setup/txt_joyaxis.h
+++ b/src/setup/txt_joyaxis.h
@@ -45,7 +45,7 @@ typedef void (*txt_joystick_axis_callback_t)(void);
 struct txt_joystick_axis_s
 {
     txt_widget_t widget;
-    int *axis, *invert;
+    int *axis, *invert, *dead_zone;
     txt_joystick_axis_direction_t dir;

     // Only used when configuring:
@@ -75,7 +75,7 @@ struct txt_joystick_axis_s
     txt_joystick_axis_callback_t callback;
 };

-txt_joystick_axis_t *TXT_NewJoystickAxis(int *axis, int *invert,
+txt_joystick_axis_t *TXT_NewJoystickAxis(int *axis, int *invert, int *dead_zone,
                                          txt_joystick_axis_direction_t dir);

 // Configure a joystick axis widget.