shithub: choc

Download patch

ref: 15c0779ec829d8a0d83ecf33ce19e681e34f1b89
parent: 4d547c03611410f8c6912ad8081a3718f0ad079c
author: Simon Howard <[email protected]>
date: Mon Apr 28 17:52:24 EDT 2014

joystick: Add "hat axis" support.

Just as some controllers have D-pads that are presented as a set of
buttons, some other controllers actually present their D-pads as
joystick hats. Add "hat axis" support where the hat number and
axis can be packed into a single integer value.

--- a/src/i_joystick.c
+++ b/src/i_joystick.c
@@ -96,6 +96,11 @@
         return true;
     }
 
+    if (IS_HAT_AXIS(axis))
+    {
+        return HAT_AXIS_HAT(axis) < SDL_JoystickNumHats(joystick);
+    }
+
     num_axes = SDL_JoystickNumAxes(joystick);
 
     return axis < num_axes;
@@ -187,12 +192,13 @@
         return 0;
     }
 
-    // Is this a button axis? If so, we need to handle it specially.
+    // Is this a button axis, or a hat axis?
+    // If so, we need to handle it specially.
 
+    result = 0;
+
     if (IS_BUTTON_AXIS(axis))
     {
-        result = 0;
-
         if (SDL_JoystickGetButton(joystick, BUTTON_AXIS_NEG(axis)))
         {
             result -= 32767;
@@ -202,19 +208,47 @@
             result += 32767;
         }
     }
-    else
+    else if (IS_HAT_AXIS(axis))
     {
-        result = SDL_JoystickGetAxis(joystick, axis);
+        int direction = HAT_AXIS_DIRECTION(axis);
+        int hatval = SDL_JoystickGetHat(joystick, HAT_AXIS_HAT(axis));
 
-        if (invert)
+        if (direction == HAT_AXIS_HORIZONTAL)
         {
-            result = -result;
+            if ((hatval & SDL_HAT_LEFT) != 0)
+            {
+                result -= 32767;
+            }
+            else if ((hatval & SDL_HAT_RIGHT) != 0)
+            {
+                result += 32767;
+            }
         }
+        else if (direction == HAT_AXIS_VERTICAL)
+        {
+            if ((hatval & SDL_HAT_UP) != 0)
+            {
+                result -= 32767;
+            }
+            else if ((hatval & SDL_HAT_DOWN) != 0)
+            {
+                result += 32767;
+            }
+        }
+    }
+    else
+    {
+        result = SDL_JoystickGetAxis(joystick, axis);
 
         if (result < DEAD_ZONE && result > -DEAD_ZONE)
         {
             result = 0;
         }
+    }
+
+    if (invert)
+    {
+        result = -result;
     }
 
     return result;
--- a/src/i_joystick.h
+++ b/src/i_joystick.h
@@ -45,6 +45,24 @@
 // Create a button axis value from two button values.
 #define CREATE_BUTTON_AXIS(neg, pos) (BUTTON_AXIS | (neg) | ((pos) << 8))
 
+// If this bit is set in an axis value, the axis is not actually a
+// joystick axis, but is a "hat" axis. This means that we read (one of)
+// the hats on the joystick.
+#define HAT_AXIS    0x20000
+
+#define IS_HAT_AXIS(axis) ((axis) >= 0 && ((axis) & HAT_AXIS) != 0)
+
+// Get the hat number from a hat axis value.
+#define HAT_AXIS_HAT(axis)         ((axis) & 0xff)
+// Which axis of the hat? (horizonal or vertical)
+#define HAT_AXIS_DIRECTION(axis)   (((axis) >> 8) & 0xff)
+
+#define CREATE_HAT_AXIS(hat, direction) \
+    (HAT_AXIS | (hat) | ((direction) << 8))
+
+#define HAT_AXIS_HORIZONTAL 1
+#define HAT_AXIS_VERTICAL   2
+
 void I_InitJoystick(void);
 void I_ShutdownJoystick(void);
 void I_UpdateJoystick(void);