Update key code strings for game controllers

With the SDL_GameController interface, buttons and axes have actual
names we can refer to. This also allows for advanced mappings using both
sticks (this probably needs script changes) as well as the triggers.
liquid_container
Lukas Werling 2016-02-13 23:28:00 +01:00
parent bd3f020068
commit 937ddaf722
2 changed files with 140 additions and 82 deletions

View File

@ -836,31 +836,41 @@
# Contents Menu
[Assignment]
Key=Joy1F
Key=Controller1b
GUIGroup=50
Control=Contents
[Assignment]
Key=Controller1leftshoulder
GUIGroup=50
Control=InventoryShiftBackward
[Assignment]
Key=Controller1rightshoulder
GUIGroup=50
Control=InventoryShiftForward
# Menu
[Assignment]
Key=Joy1J
Key=Controller1y
GUIGroup=50
Control=PlayerMenu
[Assignment]
Key=Joy1C
Key=Controller1a
GUIGroup=50
Control=MenuOK
[Assignment]
Key=Joy1B
Key=Controller1b
GUIGroup=50
Control=MenuCancel
# Movement
[Assignment]
Key=Joy1Left
Key=Controller1AxisleftxMin
Priority=50
GUIName=$KEY_Left$
GUIDesc=$KEY_Left_Desc$
@ -868,7 +878,7 @@
Control=Left
[Assignment]
Key=Joy1Right
Key=Controller1AxisleftxMax
Priority=50
GUIName=$KEY_Right$
GUIDesc=$KEY_Right_Desc$
@ -876,7 +886,7 @@
Control=Right
[Assignment]
Key=Joy1Down
Key=Controller1AxisleftyMax
Priority=50
GUIName=$KEY_Down$
GUIDesc=$KEY_Down_Desc$
@ -884,7 +894,7 @@
Control=Down
[Assignment]
Key=Joy1Up
Key=Controller1AxisleftyMin
Priority=50
GUIName=$KEY_Up$
GUIDesc=$KEY_Up_Desc$
@ -892,34 +902,40 @@
Control=Up
[Assignment]
Key=Joy1C
Key=Controller1rightstick
Priority=10
GUIGroup=10
Control=Jump
[Assignment]
Key=Joy1Axis1Min
Key=Controller1dpdown
Priority=10
GUIGroup=10
Control=FallThrough
[Assignment]
Key=Controller1AxisrightxMin
GUIDesc=$KEY_AimAxis_Desc$
Priority=80
GUIGroup=30
Control=AimAxisLeft
[Assignment]
Key=Joy1Axis1Max
Key=Controller1AxisrightxMax
GUIDesc=$KEY_AimAxis_Desc$
Priority=80
GUIGroup=30
Control=AimAxisRight
[Assignment]
Key=Joy1Axis2Max
Key=Controller1AxisrightyMax
GUIDesc=$KEY_AimAxis_Desc$
Priority=80
GUIGroup=30
Control=AimAxisDown
[Assignment]
Key=Joy1Axis2Min
Key=Controller1AxisrightyMin
GUIDesc=$KEY_AimAxis_Desc$
Priority=80
GUIGroup=30
@ -928,41 +944,57 @@
# Object interaction
[Assignment]
Key=Joy1B
Key=Controller1a
Priority=35
GUIGroup=40
Control=Interact
[Assignment]
Key=Controller1x
Control=PickUp
GUIGroup=50
# Crew
[Assignment]
Key=Joy1I
Key=Controller1dpright
Control=NextCrew
GUIGroup=70
[Assignment]
Key=Controller1dpleft
Control=PreviousCrew
GUIGroup=70
# Use, Throw, Drop
[Assignment]
Key=Joy1A
Key=Controller1AxisrighttriggerMax
GUIName=$KEY_GamepadUse$
GUIDesc=$KEY_GamepadUse_Desc$
GUIGroup=20
Priority=100
Control=UseDelayed
# Zoom
[Assignment]
Key=Joy1H
Key=Controller1AxislefttriggerMax
GUIGroup=20
Priority=100
GUIGroup=60
Control=ZoomIn
Control=ThrowDelayed
[Assignment]
Key=Joy1G
Priority=100
GUIGroup=60
Control=ZoomOut
# TODO: Zoom
#[Assignment]
#Key=Joy1H
#Priority=100
#GUIGroup=60
#Control=ZoomIn
#[Assignment]
#Key=Joy1G
#Priority=100
#GUIGroup=60
#Control=ZoomOut

View File

@ -31,8 +31,10 @@
#endif
#include <algorithm>
#include <regex>
#include <string>
#ifdef USE_SDL_MAINLOOP
#ifdef HAVE_SDL
#include <SDL.h>
#endif
@ -215,47 +217,32 @@ C4KeyCode C4KeyCodeEx::String2KeyCode(const StdStrBuf &sName)
// scan code
if (*sName.getData() == '$') return GetKeyByScanCode(sName.getData());
// direct gamepad code
#ifdef _WIN32
if (!strnicmp(sName.getData(), "Joy", 3))
#else
if (!strncasecmp(sName.getData(), "Joy", 3))
#endif
std::regex controller_re(R"/(^Controller(\d+)(Axis)?([a-z]+)(Min|Max)?$)/");
std::cmatch matches;
if (std::regex_match(sName.getData(), matches, controller_re))
{
int iGamepad;
if (sscanf(sName.getData(), "Joy%d", &iGamepad) == 1)
#ifdef HAVE_SDL
int iGamepad = std::stoi(matches[1]);
if (matches[2] == "Axis")
{
// skip Joy[number]
const char *key_str = sName.getData()+4;
while (isdigit(*key_str)) ++key_str;
// check for button (single, uppercase letter) (e.g. Joy1A)
if (*key_str && !key_str[1])
int axis = SDL_GameControllerGetAxisFromString(matches[3].str().c_str());
if (axis != SDL_CONTROLLER_AXIS_INVALID)
{
char cGamepadButton = toupper(*key_str);
if (Inside(cGamepadButton, 'A', 'Z'))
{
cGamepadButton = cGamepadButton - 'A';
return KEY_Gamepad(iGamepad-1, KEY_JOY_Button(cGamepadButton));
}
}
else
{
// check for standard axis (e.g. Joy1Left)
if (!stricmp(key_str, "Left")) return KEY_Gamepad(iGamepad-1, KEY_JOY_Left);
if (!stricmp(key_str, "Up")) return KEY_Gamepad(iGamepad-1, KEY_JOY_Up);
if (!stricmp(key_str, "Down")) return KEY_Gamepad(iGamepad-1, KEY_JOY_Down);
if (!stricmp(key_str, "Right")) return KEY_Gamepad(iGamepad-1, KEY_JOY_Right);
// check for specific axis (e.g. Joy1Axis1Min)
int iAxis;
if (sscanf(key_str, "Axis%d", &iAxis) == 1 && iAxis>0)
{
--iAxis; // axis is 0-based internally but written 1-based in config
key_str += 5;
while (isdigit(*key_str)) ++key_str;
if (!stricmp(key_str, "Min")) return KEY_Gamepad(iGamepad-1, KEY_JOY_Axis(iAxis, false));
if (!stricmp(key_str, "Max")) return KEY_Gamepad(iGamepad-1, KEY_JOY_Axis(iAxis, true));
}
if (matches[4] == "Min") return KEY_Gamepad(iGamepad-1, KEY_JOY_Axis(axis, false));
if (matches[4] == "Max") return KEY_Gamepad(iGamepad-1, KEY_JOY_Axis(axis, true));
}
}
else
{
int gamepad_button = SDL_GameControllerGetButtonFromString(matches[3].str().c_str());
if (gamepad_button != SDL_CONTROLLER_BUTTON_INVALID)
{
return KEY_Gamepad(iGamepad-1, KEY_JOY_Button(gamepad_button));
}
}
#else
return KEY_Undefined;
#endif
}
bool is_mouse_key;
#ifdef _WIN32
@ -327,30 +314,69 @@ StdStrBuf C4KeyCodeEx::KeyCode2String(C4KeyCode wCode, bool fHumanReadable, bool
if (Key_IsGamepad(wCode))
{
int iGamepad = Key_GetGamepad(wCode);
int gamepad_event = Key_GetGamepadEvent(wCode);
switch (gamepad_event)
if (Key_IsGamepadAxis(wCode))
{
case KEY_JOY_Left: return FormatString("Joy%dLeft", iGamepad+1);
case KEY_JOY_Up: return FormatString("Joy%dUp", iGamepad+1);
case KEY_JOY_Down: return FormatString("Joy%dDown", iGamepad+1);
case KEY_JOY_Right: return FormatString("Joy%dRight", iGamepad+1);
default:
if (Key_IsGamepadAxis(wCode))
int index = Key_GetGamepadAxisIndex(wCode);
const char *axis = "Unknown";
if (fHumanReadable)
{
if (fHumanReadable)
// This is still not great, but it is not really possible to assign unknown axes to "left/right" "up/down"...
return FormatString("[%d] %s", int(1 + Key_GetGamepadAxisIndex(wCode)), Key_IsGamepadAxisHigh(wCode) ? "Max" : "Min");
else
return FormatString("Joy%dAxis%d%s", iGamepad+1, static_cast<int>(Key_GetGamepadAxisIndex(wCode)+1), Key_IsGamepadAxisHigh(wCode) ? "Max" : "Min");
#ifdef HAVE_SDL
switch (index)
{
case SDL_CONTROLLER_AXIS_LEFTX: axis = "Left Stick X"; break;
case SDL_CONTROLLER_AXIS_LEFTY: axis = "Left Stick Y"; break;
case SDL_CONTROLLER_AXIS_RIGHTX: axis = "Right Stick X"; break;
case SDL_CONTROLLER_AXIS_RIGHTY: axis = "Right Stick Y"; break;
case SDL_CONTROLLER_AXIS_TRIGGERLEFT: axis = "Left Trigger"; break;
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: axis = "Right Trigger"; break;
}
#endif
// This is still not great, but it is not really possible to assign unknown axes to "left/right" "up/down"...
return FormatString("[%s] %s", axis, Key_IsGamepadAxisHigh(wCode) ? "Max" : "Min");
}
else
{
// button
if (fHumanReadable)
// If there should be gamepads around with A B C D... on the buttons, we might create a display option to show letters instead...
return FormatString("< %d >", int(1 + Key_GetGamepadButtonIndex(wCode)));
else
return FormatString("Joy%d%c", iGamepad+1, static_cast<char>(Key_GetGamepadButtonIndex(wCode) + 'A'));
#ifdef HAVE_SDL
axis = SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis) index);
#endif
return FormatString("Controller%dAxis%s%s", iGamepad+1, axis, Key_IsGamepadAxisHigh(wCode) ? "Max" : "Min");
}
}
else
{
// button
const char *button = "Unknown";
int index = Key_GetGamepadButtonIndex(wCode);
if (fHumanReadable)
{
#ifdef HAVE_SDL
switch (index)
{
case SDL_CONTROLLER_BUTTON_A: button = "A"; break;
case SDL_CONTROLLER_BUTTON_B: button = "B"; break;
case SDL_CONTROLLER_BUTTON_X: button = "X"; break;
case SDL_CONTROLLER_BUTTON_Y: button = "Y"; break;
case SDL_CONTROLLER_BUTTON_BACK: button = "Back"; break;
case SDL_CONTROLLER_BUTTON_GUIDE: button = "Guide"; break;
case SDL_CONTROLLER_BUTTON_START: button = "Start"; break;
case SDL_CONTROLLER_BUTTON_LEFTSTICK: button = "Left Stick Click"; break;
case SDL_CONTROLLER_BUTTON_RIGHTSTICK: button = "Right Stick Click"; break;
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: button = "Left Shoulder"; break;
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: button = "Right Shoulder"; break;
case SDL_CONTROLLER_BUTTON_DPAD_UP: button = "D-pad Up"; break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN: button = "D-pad Down"; break;
case SDL_CONTROLLER_BUTTON_DPAD_LEFT: button = "D-pad Left"; break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: button = "D-pad Right"; break;
}
#endif
return FormatString("< %s >", button);
}
else
{
#ifdef HAVE_SDL
button = SDL_GameControllerGetStringForButton((SDL_GameControllerButton) index);
#endif
return FormatString("Controller%d%s", iGamepad+1, button);
}
}
}