foxygit / doom Log in
commit 74e1b8b7548e6d14eb9be748279e8100a766cf04
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Sat Apr 19 01:12:13 2014 -0400
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Sat Apr 19 01:12:13 2014 -0400

    joystick: Add an axis to allow strafing.

    Modern gamepads typically have 2-3 D-pads and joysticks. This means
    that it's desirable to be able to use one joystick for turning and
    another for strafing. Add another axis in addition to the current X
    and y axes that performs strafe movement.
---
 src/d_event.h        | 28 ++++++++++++++++++++++++----
 src/doom/g_game.c    | 20 ++++++++++++--------
 src/heretic/g_game.c |  8 +++++---
 src/hexen/g_game.c   |  8 +++++---
 src/i_joystick.c     | 20 ++++++++++++++++++--
 src/m_config.c       | 13 +++++++++++++
 src/setup/joystick.c |  7 +++++++
 src/strife/g_game.c  | 20 ++++++++++++--------
 8 files changed, 96 insertions(+), 28 deletions(-)

diff --git a/src/d_event.h b/src/d_event.h
index 25334a96..230f3fa5 100644
--- a/src/d_event.h
+++ b/src/d_event.h
@@ -49,10 +49,30 @@ typedef enum
 // Event structure.
 typedef struct
 {
-    evtype_t	type;
-    int		data1;		// keys / mouse/joystick buttons
-    int		data2;		// mouse/joystick x move
-    int		data3;		// mouse/joystick y move
+    evtype_t type;
+
+    // Event-related data that depends on the type of event:
+    //
+    // ev_keydown/ev_keyup:
+    //    data1: Key code (from doomkeys.h) of the key that was
+    //           pressed or released.
+    //    data2: Ascii text of the character that was pressed,
+    //           shifted appropriately (eg. '$' if 4 was pressed
+    //           while shift was held).
+    //
+    // ev_mouse:
+    //    data1: Bitfield of buttons currently held down.
+    //           (bit 0 = left; bit 1 = right; bit 2 = middle).
+    //    data2: X axis mouse movement (turn).
+    //    data3: Y axis mouse movement (forward/backward).
+    //
+    // ev_joystick:
+    //    data1: Bitfield of buttons currently pressed.
+    //    data2: X axis mouse movement (turn).
+    //    data3: Y axis mouse movement (forward/backward).
+    //    data4: Third axis mouse movement (strafe).
+
+    int data1, data2, data3, data4;
 } event_t;


diff --git a/src/doom/g_game.c b/src/doom/g_game.c
index 8dca36d9..7ff54f46 100644
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -223,6 +223,7 @@ static int      dclicks2;
 // joystick values are repeated
 static int      joyxmove;
 static int      joyymove;
+static int      joystrafemove;
 static boolean  joyarray[MAX_JOY_BUTTONS + 1];
 static boolean *joybuttons = &joyarray[1];		// allow [-1]

@@ -418,14 +419,16 @@ void G_BuildTiccmd (ticcmd_t* cmd, int maketic)

     if (gamekeydown[key_strafeleft]
      || joybuttons[joybstrafeleft]
-     || mousebuttons[mousebstrafeleft])
+     || mousebuttons[mousebstrafeleft]
+     || joystrafemove < 0)
     {
         side -= sidemove[speed];
     }

     if (gamekeydown[key_straferight]
      || joybuttons[joybstraferight]
-     || mousebuttons[mousebstraferight])
+     || mousebuttons[mousebstraferight]
+     || joystrafemove > 0)
     {
         side += sidemove[speed];
     }
@@ -638,12 +641,12 @@ void G_DoLoadLevel (void)

     // clear cmd building stuff

-    memset (gamekeydown, 0, sizeof(gamekeydown));
-    joyxmove = joyymove = 0;
-    mousex = mousey = 0;
-    sendpause = sendsave = paused = false;
-    memset(mousearray, 0, sizeof(mousearray));
-    memset(joyarray, 0, sizeof(joyarray));
+    memset (gamekeydown, 0, sizeof(gamekeydown));
+    joyxmove = joyymove = joystrafemove = 0;
+    mousex = mousey = 0;
+    sendpause = sendsave = paused = false;
+    memset(mousearray, 0, sizeof(mousearray));
+    memset(joyarray, 0, sizeof(joyarray));

     if (testcontrols)
     {
@@ -814,6 +817,7 @@ boolean G_Responder (event_t* ev)
         SetJoyButtons(ev->data1);
 	joyxmove = ev->data2;
 	joyymove = ev->data3;
+        joystrafemove = ev->data4;
 	return true;    // eat events

       default:
diff --git a/src/heretic/g_game.c b/src/heretic/g_game.c
index 64186769..3b86fa6b 100644
--- a/src/heretic/g_game.c
+++ b/src/heretic/g_game.c
@@ -195,6 +195,7 @@ int dclicktime2, dclickstate2, dclicks2;
 #define MAX_JOY_BUTTONS 20

 int joyxmove, joyymove;         // joystick values are repeated
+int joystrafemove;
 boolean joyarray[MAX_JOY_BUTTONS + 1];
 boolean *joybuttons = &joyarray[1];     // allow [-1]

@@ -379,10 +380,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, int maketic)
     if (joyymove > 0)
         forward -= forwardmove[speed];
     if (gamekeydown[key_straferight] || mousebuttons[mousebstraferight]
-     || joybuttons[joybstraferight])
+     || joybuttons[joybstraferight] || joystrafemove > 0)
         side += sidemove[speed];
     if (gamekeydown[key_strafeleft] || mousebuttons[mousebstrafeleft]
-     || joybuttons[joybstrafeleft])
+     || joybuttons[joybstrafeleft] || joystrafemove < 0)
         side -= sidemove[speed];

     // Look up/down/center keys
@@ -663,7 +664,7 @@ void G_DoLoadLevel(void)
 //

     memset(gamekeydown, 0, sizeof(gamekeydown));
-    joyxmove = joyymove = 0;
+    joyxmove = joyymove = joystrafemove = 0;
     mousex = mousey = 0;
     sendpause = sendsave = paused = false;
     memset(mousearray, 0, sizeof(mousearray));
@@ -879,6 +880,7 @@ boolean G_Responder(event_t * ev)
             SetJoyButtons(ev->data1);
             joyxmove = ev->data2;
             joyymove = ev->data3;
+            joystrafemove = ev->data4;
             return (true);      // eat events

         default:
diff --git a/src/hexen/g_game.c b/src/hexen/g_game.c
index c7c7b531..da7d11df 100644
--- a/src/hexen/g_game.c
+++ b/src/hexen/g_game.c
@@ -162,6 +162,7 @@ int dclicktime2, dclickstate2, dclicks2;
 #define MAX_JOY_BUTTONS 20

 int joyxmove, joyymove;         // joystick values are repeated
+int joystrafemove;
 boolean joyarray[MAX_JOY_BUTTONS + 1];
 boolean *joybuttons = &joyarray[1];     // allow [-1]

@@ -313,11 +314,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, int maketic)
     {
         forward -= forwardmove[pClass][speed];
     }
-    if (gamekeydown[key_straferight])
+    if (gamekeydown[key_straferight] || joystrafemove > 0)
     {
         side += sidemove[pClass][speed];
     }
-    if (gamekeydown[key_strafeleft])
+    if (gamekeydown[key_strafeleft] || joystrafemove < 0)
     {
         side -= sidemove[pClass][speed];
     }
@@ -659,7 +660,7 @@ void G_DoLoadLevel(void)
 //

     memset(gamekeydown, 0, sizeof(gamekeydown));
-    joyxmove = joyymove = 0;
+    joyxmove = joyymove = joystrafemove = 0;
     mousex = mousey = 0;
     sendpause = sendsave = paused = false;
     memset(mousearray, 0, sizeof(mousearray));
@@ -876,6 +877,7 @@ boolean G_Responder(event_t * ev)
             SetJoyButtons(ev->data1);
             joyxmove = ev->data2;
             joyymove = ev->data3;
+            joystrafemove = ev->data4;
             return (true);      // eat events

         default:
diff --git a/src/i_joystick.c b/src/i_joystick.c
index 4bc6a1e9..8d77c9d6 100644
--- a/src/i_joystick.c
+++ b/src/i_joystick.c
@@ -67,6 +67,11 @@ static int joystick_x_invert = 0;
 static int joystick_y_axis = 1;
 static int joystick_y_invert = 0;

+// Which joystick axis to use for strafing?
+
+static int joystick_strafe_axis = -1;
+static int joystick_strafe_invert = 0;
+
 void I_ShutdownJoystick(void)
 {
     if (joystick != NULL)
@@ -112,8 +117,9 @@ void I_InitJoystick(void)

     num_axes = SDL_JoystickNumAxes(joystick);

-    if (joystick_x_axis < 0 || joystick_x_axis >= num_axes
-     || joystick_y_axis < 0 || joystick_y_axis >= num_axes)
+    if (joystick_x_axis >= num_axes
+     || joystick_y_axis >= num_axes
+     || joystick_strafe_axis >= num_axes)
     {
         printf("I_InitJoystick: Invalid joystick axis for joystick #%i "
                "(run joystick setup again)\n",
@@ -159,6 +165,13 @@ static int GetAxisState(int axis, int invert)
 {
     int result;

+    // Axis -1 means disabled.
+
+    if (axis < 0)
+    {
+        return 0;
+    }
+
     result = SDL_JoystickGetAxis(joystick, axis);

     if (invert)
@@ -184,6 +197,7 @@ void I_UpdateJoystick(void)
         ev.data1 = GetButtonState();
         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);

         D_PostEvent(&ev);
     }
@@ -195,7 +209,9 @@ void I_BindJoystickVariables(void)
     M_BindVariable("joystick_index",        &joystick_index);
     M_BindVariable("joystick_x_axis",       &joystick_x_axis);
     M_BindVariable("joystick_y_axis",       &joystick_y_axis);
+    M_BindVariable("joystick_strafe_axis",  &joystick_strafe_axis);
     M_BindVariable("joystick_x_invert",     &joystick_x_invert);
     M_BindVariable("joystick_y_invert",     &joystick_y_invert);
+    M_BindVariable("joystick_strafe_invert",&joystick_strafe_invert);
 }

diff --git a/src/m_config.c b/src/m_config.c
index 02817041..ac4eb304 100644
--- a/src/m_config.c
+++ b/src/m_config.c
@@ -925,6 +925,19 @@ static default_t extra_defaults_list[] =

     CONFIG_VARIABLE_INT(joystick_y_invert),

+    //!
+    // Joystick axis to use to for strafing movement.
+    //
+
+    CONFIG_VARIABLE_INT(joystick_strafe_axis),
+
+    //!
+    // If non-zero, movement on the joystick axis used for strafing
+    // is inverted.
+    //
+
+    CONFIG_VARIABLE_INT(joystick_strafe_invert),
+
     //!
     // Joystick button to strafe left.
     //
diff --git a/src/setup/joystick.c b/src/setup/joystick.c
index 064ff99d..9e04ba0b 100644
--- a/src/setup/joystick.c
+++ b/src/setup/joystick.c
@@ -63,6 +63,11 @@ static int joystick_x_invert = 0;
 static int joystick_y_axis = 1;
 static int joystick_y_invert = 0;

+// Strafe axis.
+
+static int joystick_strafe_axis = -1;
+static int joystick_strafe_invert = 0;
+
 static txt_button_t *joystick_button;

 static int *all_joystick_buttons[] = {
@@ -438,7 +443,9 @@ void BindJoystickVariables(void)
     M_BindVariable("joystick_index",        &joystick_index);
     M_BindVariable("joystick_x_axis",       &joystick_x_axis);
     M_BindVariable("joystick_y_axis",       &joystick_y_axis);
+    M_BindVariable("joystick_strafe_axis",  &joystick_strafe_axis);
     M_BindVariable("joystick_x_invert",     &joystick_x_invert);
     M_BindVariable("joystick_y_invert",     &joystick_y_invert);
+    M_BindVariable("joystick_strafe_invert",&joystick_strafe_invert);
 }

diff --git a/src/strife/g_game.c b/src/strife/g_game.c
index c67d7be1..f90034ff 100644
--- a/src/strife/g_game.c
+++ b/src/strife/g_game.c
@@ -226,6 +226,7 @@ static int      dclicks2;
 // joystick values are repeated
 static int      joyxmove;
 static int      joyymove;
+static int      joystrafemove;
 static boolean  joyarray[MAX_JOY_BUTTONS + 1];
 static boolean *joybuttons = &joyarray[1];		// allow [-1]

@@ -468,14 +469,16 @@ void G_BuildTiccmd (ticcmd_t* cmd, int maketic)

     if (gamekeydown[key_strafeleft]
      || joybuttons[joybstrafeleft]
-     || mousebuttons[mousebstrafeleft])
+     || mousebuttons[mousebstrafeleft]
+     || joystrafemove < 0)
     {
         side -= sidemove[speed];
     }

     if (gamekeydown[key_straferight]
      || joybuttons[joybstraferight]
-     || mousebuttons[mousebstraferight])
+     || mousebuttons[mousebstraferight]
+     || joystrafemove > 0)
     {
         side += sidemove[speed];
     }
@@ -699,12 +702,12 @@ void G_DoLoadLevel (void)

     // clear cmd building stuff

-    memset (gamekeydown, 0, sizeof(gamekeydown));
-    joyxmove = joyymove = 0;
-    mousex = mousey = 0;
-    sendpause = sendsave = paused = false;
-    memset(mousearray, 0, sizeof(mousearray));
-    memset(joyarray, 0, sizeof(joyarray));
+    memset (gamekeydown, 0, sizeof(gamekeydown));
+    joyxmove = joyymove = joystrafemove = 0;
+    mousex = mousey = 0;
+    sendpause = sendsave = paused = false;
+    memset(mousearray, 0, sizeof(mousearray));
+    memset(joyarray, 0, sizeof(joyarray));

     if (testcontrols)
     {
@@ -880,6 +883,7 @@ boolean G_Responder (event_t* ev)
         SetJoyButtons(ev->data1);
         joyxmove = ev->data2;
         joyymove = ev->data3;
+        joystrafemove = ev->data4;
         return true;    // eat events

     default: