ref: 05f22d03aa25c55f5b7251d474eee16054f37e9e
parent: 4890591ba50bfc8b11cda684b223cb7c551e6dd3
author: Simon Howard <fraggle@gmail.com>
date: Wed Apr 30 20:19:51 EDT 2014
setup: Configure joystick buttons with virtual mapping. Refactor how joystick buttons are reassigned. Define a fixed mapping from joyb* variables to virtual buttons, and change the button assignments at the virtual->physical mapping level.
--- a/src/m_controls.h
+++ b/src/m_controls.h
@@ -157,8 +157,6 @@
extern int joybprevweapon;
extern int joybnextweapon;
-extern int joy_physical_buttons[10];
-
extern int joybmenu;
extern int dclick_use;
--- a/src/setup/joystick.c
+++ b/src/setup/joystick.c
@@ -90,18 +90,12 @@
static int joystick_strafe_invert = 0;
// Virtual to physical mapping.
-static int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS] = {
+int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
};
static txt_button_t *joystick_button;
-static int *all_joystick_buttons[] = {
- &joybstraferight, &joybstrafeleft, &joybfire, &joybspeed,
- &joybuse, &joybstrafe, &joybprevweapon, &joybnextweapon, &joybjump,
- &joybmenu,
-};
-
//
// Calibration
//
@@ -580,27 +574,7 @@
SetCalibrationLabel();
}
-void JoyButtonSetCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(variable))
-{
- TXT_CAST_ARG(int, variable);
- unsigned int i;
-
- // Only allow a button to be bound to one action at a time. If
- // we assign a key that another action is using, set that other action
- // to -1.
-
- for (i=0; i<arrlen(all_joystick_buttons); ++i)
- {
- if (variable != all_joystick_buttons[i]
- && *variable == *all_joystick_buttons[i])
- {
- *all_joystick_buttons[i] = -1;
- }
- }
-}
-
-
-//
+//
// GUI
//
@@ -621,8 +595,6 @@
TXT_AddWidget(table, TXT_NewLabel(label));
TXT_AddWidget(table, joy_input);
-
- TXT_SignalConnect(joy_input, "set", JoyButtonSetCallback, var);
}
void ConfigJoystick(void)
--- a/src/setup/txt_joybinput.c
+++ b/src/setup/txt_joybinput.c
@@ -27,6 +27,9 @@
#include "doomkeys.h"
#include "joystick.h"
+#include "i_joystick.h"
+#include "i_system.h"
+#include "m_controls.h"
#include "m_misc.h"
#include "txt_joybinput.h"
@@ -38,6 +41,111 @@
#define JOYSTICK_INPUT_WIDTH 10
+extern int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS];
+
+// Joystick button variables.
+// The ordering of this array is important. We will always try to map
+// each variable to the virtual button with the same array index. For
+// example: joybfire should always be 0, and then we change
+// joystick_physical_buttons[0] to point to the physical joystick
+// button that the user wants to use for firing. We do this so that
+// the menus work (the game code is hard coded to interpret
+// button #0 = select menu item, button #1 = go back to previous menu).
+static int *all_joystick_buttons[] =
+{
+ &joybfire,
+ &joybuse,
+ &joybstrafe,
+ &joybspeed,
+ &joybstrafeleft,
+ &joybstraferight,
+ &joybprevweapon,
+ &joybnextweapon,
+ &joybjump,
+ &joybmenu,
+};
+
+static int PhysicalForVirtualButton(int vbutton)
+{
+ if (vbutton < NUM_VIRTUAL_BUTTONS)
+ {
+ return joystick_physical_buttons[vbutton];
+ }
+ else
+ {
+ return vbutton;
+ }
+}
+
+// Get the virtual button number for the given variable, ie. the
+// variable's index in all_joystick_buttons[].
+static int VirtualButtonForVariable(int *variable)
+{
+ int i;
+
+ for (i = 0; i < arrlen(all_joystick_buttons); ++i)
+ {
+ if (variable == all_joystick_buttons[i])
+ {
+ return i;
+ }
+ }
+
+ I_Error("Couldn't find virtual button");
+ return -1;
+}
+
+// Rearrange joystick button configuration to be in "canonical" form:
+// each joyb* variable should have a value equal to its index in
+// all_joystick_buttons[] above.
+static void CanonicalizeButtons(void)
+{
+ int new_mapping[NUM_VIRTUAL_BUTTONS];
+ int vbutton;
+ int i;
+
+ for (i = 0; i < arrlen(all_joystick_buttons); ++i)
+ {
+ vbutton = *all_joystick_buttons[i];
+
+ // Don't remap the speed key if it's bound to "always run".
+ // Also preserve "unbound" variables.
+ if ((all_joystick_buttons[i] == &joybspeed && vbutton >= 20)
+ || vbutton < 0)
+ {
+ new_mapping[i] = i;
+ }
+ else
+ {
+ new_mapping[i] = PhysicalForVirtualButton(vbutton);
+ *all_joystick_buttons[i] = i;
+ }
+ }
+
+ for (i = 0; i < NUM_VIRTUAL_BUTTONS; ++i)
+ {
+ joystick_physical_buttons[i] = new_mapping[i];
+ }
+}
+
+// Check all existing buttons and clear any using the specified physical
+// button.
+static void ClearVariablesUsingButton(int physbutton)
+{
+ int vbutton;
+ int i;
+
+ for (i = 0; i < arrlen(all_joystick_buttons); ++i)
+ {
+ vbutton = *all_joystick_buttons[i];
+
+ if (vbutton >= 0 && physbutton == PhysicalForVirtualButton(vbutton))
+ {
+ *all_joystick_buttons[i] = -1;
+ }
+ }
+}
+
// Called in response to SDL events when the prompt window is open:
static int EventCallback(SDL_Event *event, TXT_UNCAST_ARG(joystick_input))
@@ -48,13 +156,24 @@
if (event->type == SDL_JOYBUTTONDOWN)
{
- *joystick_input->variable = event->jbutton.button;
+ int vbutton, physbutton;
+ // Before changing anything, remap button configuration into
+ // canonical form, to avoid conflicts.
+ CanonicalizeButtons();
+
+ vbutton = VirtualButtonForVariable(joystick_input->variable);
+ physbutton = event->jbutton.button;
+
if (joystick_input->check_conflicts)
{
- TXT_EmitSignal(joystick_input, "set");
+ ClearVariablesUsingButton(physbutton);
}
+ // Set mapping.
+ *joystick_input->variable = vbutton;
+ joystick_physical_buttons[vbutton] = physbutton;
+
TXT_CloseWindow(joystick_input->prompt_window);
return 1;
}
@@ -125,9 +244,11 @@
joystick_input->widget.h = 1;
}
-static void GetJoystickButtonDescription(int button, char *buf, size_t buf_len)
+static void GetJoystickButtonDescription(int vbutton, char *buf,
+ size_t buf_len)
{
- M_snprintf(buf, buf_len, "BUTTON #%i", button + 1);
+ M_snprintf(buf, buf_len, "BUTTON #%i",
+ PhysicalForVirtualButton(vbutton) + 1);
}
static void TXT_JoystickInputDrawer(TXT_UNCAST_ARG(joystick_input))
@@ -148,9 +269,9 @@
TXT_SetWidgetBG(joystick_input);
TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
-
+
TXT_DrawString(buf);
-
+
for (i=strlen(buf); i<JOYSTICK_INPUT_WIDTH; ++i)
{
TXT_DrawString(" ");
@@ -185,7 +306,7 @@
static void TXT_JoystickInputMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b)
{
TXT_CAST_ARG(txt_joystick_input_t, widget);
-
+
// Clicking is like pressing enter
if (b == TXT_MOUSE_LEFT)