Handle ordinal joystick hat keys as combined cardinal hat keys

Instead of considering diagonal hat inputs (e.g. up-left) as separate keys, consider them as inputs for both cardinal directions (e.g. up and left) at the same time.

This improves input with gamecontrollers that map the D-Pad to a joystick hat, as it was impossible with the previous handling to move with hat-left/right and jump with hat-up at the same time.

This means that diagonal hat buttons can no longer be used in binds, because they are no longer considered distinct buttons. It's unlikely that they would ever be useful in this game, as real joystick POV hats would not be used anyway.

Closes #6120.
This commit is contained in:
Robert Müller 2022-12-17 17:18:01 +01:00
parent f51dd365e4
commit 1eaa88b236
6 changed files with 78 additions and 90 deletions

View file

@ -64,22 +64,14 @@ print(f"\tKEY_JOYSTICK_BUTTON_9 = {int(highestid)},", file=f); keynames[highesti
print(f"\tKEY_JOYSTICK_BUTTON_10 = {int(highestid)},", file=f); keynames[highestid] = "joystick10"; highestid += 1
print(f"\tKEY_JOYSTICK_BUTTON_11 = {int(highestid)},", file=f); keynames[highestid] = "joystick11"; highestid += 1
print("", file=f)
print(f"\tKEY_JOY_HAT0_LEFTUP = {int(highestid)},", file=f); keynames[highestid] = "joy_hat0_leftup"; highestid += 1
print(f"\tKEY_JOY_HAT0_UP = {int(highestid)},", file=f); keynames[highestid] = "joy_hat0_up"; highestid += 1
print(f"\tKEY_JOY_HAT0_RIGHTUP = {int(highestid)},", file=f); keynames[highestid] = "joy_hat0_rightup"; highestid += 1
print(f"\tKEY_JOY_HAT0_LEFT = {int(highestid)},", file=f); keynames[highestid] = "joy_hat0_left"; highestid += 1
print(f"\tKEY_JOY_HAT0_RIGHT = {int(highestid)},", file=f); keynames[highestid] = "joy_hat0_right"; highestid += 1
print(f"\tKEY_JOY_HAT0_LEFTDOWN = {int(highestid)},", file=f); keynames[highestid] = "joy_hat0_leftdown"; highestid += 1
print(f"\tKEY_JOY_HAT0_DOWN = {int(highestid)},", file=f); keynames[highestid] = "joy_hat0_down"; highestid += 1
print(f"\tKEY_JOY_HAT0_RIGHTDOWN = {int(highestid)},", file=f); keynames[highestid] = "joy_hat0_rightdown"; highestid += 1
print(f"\tKEY_JOY_HAT1_LEFTUP = {int(highestid)},", file=f); keynames[highestid] = "joy_hat1_leftup"; highestid += 1
print(f"\tKEY_JOY_HAT1_UP = {int(highestid)},", file=f); keynames[highestid] = "joy_hat1_up"; highestid += 1
print(f"\tKEY_JOY_HAT1_RIGHTUP = {int(highestid)},", file=f); keynames[highestid] = "joy_hat1_rightup"; highestid += 1
print(f"\tKEY_JOY_HAT1_LEFT = {int(highestid)},", file=f); keynames[highestid] = "joy_hat1_left"; highestid += 1
print(f"\tKEY_JOY_HAT1_RIGHT = {int(highestid)},", file=f); keynames[highestid] = "joy_hat1_right"; highestid += 1
print(f"\tKEY_JOY_HAT1_LEFTDOWN = {int(highestid)},", file=f); keynames[highestid] = "joy_hat1_leftdown"; highestid += 1
print(f"\tKEY_JOY_HAT1_DOWN = {int(highestid)},", file=f); keynames[highestid] = "joy_hat1_down"; highestid += 1
print(f"\tKEY_JOY_HAT1_RIGHTDOWN = {int(highestid)},", file=f); keynames[highestid] = "joy_hat1_rightdown"; highestid += 1
print("", file=f)
print(f"\tKEY_JOY_AXIS_0_LEFT = {int(highestid)},", file=f); keynames[highestid] = "joy_axis0_left"; highestid += 1
print(f"\tKEY_JOY_AXIS_0_RIGHT = {int(highestid)},", file=f); keynames[highestid] = "joy_axis0_right"; highestid += 1
@ -112,8 +104,8 @@ print("\tNUM_JOYSTICK_BUTTONS = KEY_JOYSTICK_BUTTON_11 - KEY_JOYSTICK_BUTTON_0 +
print("\tNUM_JOYSTICK_AXES_BUTTONS = KEY_JOY_AXIS_11_RIGHT - KEY_JOY_AXIS_0_LEFT + 1,", file=f)
print("\tNUM_JOYSTICK_BUTTONS_PER_AXIS = KEY_JOY_AXIS_0_RIGHT - KEY_JOY_AXIS_0_LEFT + 1,", file=f)
print("\tNUM_JOYSTICK_AXES = NUM_JOYSTICK_AXES_BUTTONS / NUM_JOYSTICK_BUTTONS_PER_AXIS,", file=f)
print("\tNUM_JOYSTICK_HAT_BUTTONS = KEY_JOY_HAT1_RIGHTDOWN - KEY_JOY_HAT0_LEFTUP + 1,", file=f)
print("\tNUM_JOYSTICK_BUTTONS_PER_HAT = KEY_JOY_HAT1_RIGHTDOWN - KEY_JOY_HAT1_LEFTUP + 1,", file=f)
print("\tNUM_JOYSTICK_HAT_BUTTONS = KEY_JOY_HAT1_DOWN - KEY_JOY_HAT0_UP + 1,", file=f)
print("\tNUM_JOYSTICK_BUTTONS_PER_HAT = KEY_JOY_HAT1_DOWN - KEY_JOY_HAT1_UP + 1,", file=f)
print("\tNUM_JOYSTICK_HATS = NUM_JOYSTICK_HAT_BUTTONS / NUM_JOYSTICK_BUTTONS_PER_HAT,", file=f)
print("};", file=f)
@ -128,8 +120,6 @@ print('#ifndef KEYS_INCLUDE', file=f)
print('#error do not include this header!', file=f)
print('#endif', file=f)
print('', file=f)
print("#include <string.h>", file=f)
print("", file=f)
print("const char g_aaKeyStrings[512][20] = // NOLINT(misc-definitions-in-headers)", file=f)
print("{", file=f)
for n in keynames:

View file

@ -189,25 +189,26 @@ float CInput::CJoystick::GetAxisValue(int Axis)
return (SDL_JoystickGetAxis(m_pDelegate, Axis) - SDL_JOYSTICK_AXIS_MIN) / (float)(SDL_JOYSTICK_AXIS_MAX - SDL_JOYSTICK_AXIS_MIN) * 2.0f - 1.0f;
}
int CInput::CJoystick::GetJoystickHatKey(int Hat, int HatValue)
void CInput::CJoystick::GetJoystickHatKeys(int Hat, int HatValue, int (&HatKeys)[2])
{
switch(HatValue)
{
case SDL_HAT_LEFTUP: return KEY_JOY_HAT0_LEFTUP + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
case SDL_HAT_UP: return KEY_JOY_HAT0_UP + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
case SDL_HAT_RIGHTUP: return KEY_JOY_HAT0_RIGHTUP + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
case SDL_HAT_LEFT: return KEY_JOY_HAT0_LEFT + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
case SDL_HAT_RIGHT: return KEY_JOY_HAT0_RIGHT + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
case SDL_HAT_LEFTDOWN: return KEY_JOY_HAT0_LEFTDOWN + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
case SDL_HAT_DOWN: return KEY_JOY_HAT0_DOWN + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
case SDL_HAT_RIGHTDOWN: return KEY_JOY_HAT0_RIGHTDOWN + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
}
return -1;
if(HatValue & SDL_HAT_UP)
HatKeys[0] = KEY_JOY_HAT0_UP + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
else if(HatValue & SDL_HAT_DOWN)
HatKeys[0] = KEY_JOY_HAT0_DOWN + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
else
HatKeys[0] = KEY_UNKNOWN;
if(HatValue & SDL_HAT_LEFT)
HatKeys[1] = KEY_JOY_HAT0_LEFT + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
else if(HatValue & SDL_HAT_RIGHT)
HatKeys[1] = KEY_JOY_HAT0_RIGHT + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT;
else
HatKeys[1] = KEY_UNKNOWN;
}
int CInput::CJoystick::GetHatValue(int Hat)
void CInput::CJoystick::GetHatValue(int Hat, int (&HatKeys)[2])
{
return GetJoystickHatKey(Hat, SDL_JoystickGetHat(m_pDelegate, Hat));
return GetJoystickHatKeys(Hat, SDL_JoystickGetHat(m_pDelegate, Hat), HatKeys);
}
bool CInput::CJoystick::Relative(float *pX, float *pY)
@ -377,9 +378,10 @@ void CInput::UpdateJoystickState()
for(int Hat = 0; Hat < pJoystick->GetNumHats(); Hat++)
{
const int HatState = pJoystick->GetHatValue(Hat);
for(int Key = KEY_JOY_HAT0_LEFTUP + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT; Key <= KEY_JOY_HAT0_RIGHTDOWN + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT; Key++)
m_aInputState[Key] = Key == HatState;
int HatKeys[2];
pJoystick->GetHatValue(Hat, HatKeys);
for(int Key = KEY_JOY_HAT0_UP + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT; Key <= KEY_JOY_HAT0_DOWN + Hat * NUM_JOYSTICK_BUTTONS_PER_HAT; Key++)
m_aInputState[Key] = HatKeys[0] == Key || HatKeys[1] == Key;
}
}
@ -457,24 +459,28 @@ void CInput::HandleJoystickHatMotionEvent(const SDL_Event &Event)
if(Event.jhat.hat >= NUM_JOYSTICK_HATS)
return;
const int CurrentKey = CJoystick::GetJoystickHatKey(Event.jhat.hat, Event.jhat.value);
int HatKeys[2];
CJoystick::GetJoystickHatKeys(Event.jhat.hat, Event.jhat.value, HatKeys);
for(int Key = KEY_JOY_HAT0_LEFTUP + Event.jhat.hat * NUM_JOYSTICK_BUTTONS_PER_HAT; Key <= KEY_JOY_HAT0_RIGHTDOWN + Event.jhat.hat * NUM_JOYSTICK_BUTTONS_PER_HAT; Key++)
for(int Key = KEY_JOY_HAT0_UP + Event.jhat.hat * NUM_JOYSTICK_BUTTONS_PER_HAT; Key <= KEY_JOY_HAT0_DOWN + Event.jhat.hat * NUM_JOYSTICK_BUTTONS_PER_HAT; Key++)
{
if(Key != CurrentKey && m_aInputState[Key])
if(Key != HatKeys[0] && Key != HatKeys[1] && m_aInputState[Key])
{
m_aInputState[Key] = false;
AddEvent(0, Key, IInput::FLAG_RELEASE);
}
}
if(CurrentKey >= 0)
for(int CurrentKey : HatKeys)
{
if(CurrentKey != KEY_UNKNOWN && !m_aInputState[CurrentKey])
{
m_aInputState[CurrentKey] = true;
m_aInputCount[CurrentKey] = m_InputCounter;
AddEvent(0, CurrentKey, IInput::FLAG_PRESS);
}
}
}
bool CInput::GetIMEState()
{

View file

@ -40,11 +40,11 @@ public:
int GetNumBalls() const override { return m_NumBalls; }
int GetNumHats() const override { return m_NumHats; }
float GetAxisValue(int Axis) override;
int GetHatValue(int Hat) override;
void GetHatValue(int Hat, int (&HatKeys)[2]) override;
bool Relative(float *pX, float *pY) override;
bool Absolute(float *pX, float *pY) override;
static int GetJoystickHatKey(int Hat, int HatValue);
static void GetJoystickHatKeys(int Hat, int HatValue, int (&HatKeys)[2]);
};
private:

View file

@ -316,22 +316,14 @@ const char g_aaKeyStrings[512][20] = // NOLINT(misc-definitions-in-headers)
"joystick9",
"joystick10",
"joystick11",
"joy_hat0_leftup",
"joy_hat0_up",
"joy_hat0_rightup",
"joy_hat0_left",
"joy_hat0_right",
"joy_hat0_leftdown",
"joy_hat0_down",
"joy_hat0_rightdown",
"joy_hat1_leftup",
"joy_hat1_up",
"joy_hat1_rightup",
"joy_hat1_left",
"joy_hat1_right",
"joy_hat1_leftdown",
"joy_hat1_down",
"joy_hat1_rightdown",
"joy_axis0_left",
"joy_axis0_right",
"joy_axis1_left",
@ -356,6 +348,14 @@ const char g_aaKeyStrings[512][20] = // NOLINT(misc-definitions-in-headers)
"joy_axis10_right",
"joy_axis11_left",
"joy_axis11_right",
"&342",
"&343",
"&344",
"&345",
"&346",
"&347",
"&348",
"&349",
"&350",
"&351",
"&352",

View file

@ -86,7 +86,7 @@ public:
virtual int GetNumBalls() const = 0;
virtual int GetNumHats() const = 0;
virtual float GetAxisValue(int Axis) = 0;
virtual int GetHatValue(int Hat) = 0;
virtual void GetHatValue(int Hat, int (&HatKeys)[2]) = 0;
virtual bool Relative(float *pX, float *pY) = 0;
virtual bool Absolute(float *pX, float *pY) = 0;
};

View file

@ -276,47 +276,39 @@ enum
KEY_JOYSTICK_BUTTON_10 = 308,
KEY_JOYSTICK_BUTTON_11 = 309,
KEY_JOY_HAT0_LEFTUP = 310,
KEY_JOY_HAT0_UP = 311,
KEY_JOY_HAT0_RIGHTUP = 312,
KEY_JOY_HAT0_LEFT = 313,
KEY_JOY_HAT0_RIGHT = 314,
KEY_JOY_HAT0_LEFTDOWN = 315,
KEY_JOY_HAT0_DOWN = 316,
KEY_JOY_HAT0_RIGHTDOWN = 317,
KEY_JOY_HAT1_LEFTUP = 318,
KEY_JOY_HAT1_UP = 319,
KEY_JOY_HAT1_RIGHTUP = 320,
KEY_JOY_HAT1_LEFT = 321,
KEY_JOY_HAT1_RIGHT = 322,
KEY_JOY_HAT1_LEFTDOWN = 323,
KEY_JOY_HAT1_DOWN = 324,
KEY_JOY_HAT1_RIGHTDOWN = 325,
KEY_JOY_HAT0_UP = 310,
KEY_JOY_HAT0_LEFT = 311,
KEY_JOY_HAT0_RIGHT = 312,
KEY_JOY_HAT0_DOWN = 313,
KEY_JOY_HAT1_UP = 314,
KEY_JOY_HAT1_LEFT = 315,
KEY_JOY_HAT1_RIGHT = 316,
KEY_JOY_HAT1_DOWN = 317,
KEY_JOY_AXIS_0_LEFT = 326,
KEY_JOY_AXIS_0_RIGHT = 327,
KEY_JOY_AXIS_1_LEFT = 328,
KEY_JOY_AXIS_1_RIGHT = 329,
KEY_JOY_AXIS_2_LEFT = 330,
KEY_JOY_AXIS_2_RIGHT = 331,
KEY_JOY_AXIS_3_LEFT = 332,
KEY_JOY_AXIS_3_RIGHT = 333,
KEY_JOY_AXIS_4_LEFT = 334,
KEY_JOY_AXIS_4_RIGHT = 335,
KEY_JOY_AXIS_5_LEFT = 336,
KEY_JOY_AXIS_5_RIGHT = 337,
KEY_JOY_AXIS_6_LEFT = 338,
KEY_JOY_AXIS_6_RIGHT = 339,
KEY_JOY_AXIS_7_LEFT = 340,
KEY_JOY_AXIS_7_RIGHT = 341,
KEY_JOY_AXIS_8_LEFT = 342,
KEY_JOY_AXIS_8_RIGHT = 343,
KEY_JOY_AXIS_9_LEFT = 344,
KEY_JOY_AXIS_9_RIGHT = 345,
KEY_JOY_AXIS_10_LEFT = 346,
KEY_JOY_AXIS_10_RIGHT = 347,
KEY_JOY_AXIS_11_LEFT = 348,
KEY_JOY_AXIS_11_RIGHT = 349,
KEY_JOY_AXIS_0_LEFT = 318,
KEY_JOY_AXIS_0_RIGHT = 319,
KEY_JOY_AXIS_1_LEFT = 320,
KEY_JOY_AXIS_1_RIGHT = 321,
KEY_JOY_AXIS_2_LEFT = 322,
KEY_JOY_AXIS_2_RIGHT = 323,
KEY_JOY_AXIS_3_LEFT = 324,
KEY_JOY_AXIS_3_RIGHT = 325,
KEY_JOY_AXIS_4_LEFT = 326,
KEY_JOY_AXIS_4_RIGHT = 327,
KEY_JOY_AXIS_5_LEFT = 328,
KEY_JOY_AXIS_5_RIGHT = 329,
KEY_JOY_AXIS_6_LEFT = 330,
KEY_JOY_AXIS_6_RIGHT = 331,
KEY_JOY_AXIS_7_LEFT = 332,
KEY_JOY_AXIS_7_RIGHT = 333,
KEY_JOY_AXIS_8_LEFT = 334,
KEY_JOY_AXIS_8_RIGHT = 335,
KEY_JOY_AXIS_9_LEFT = 336,
KEY_JOY_AXIS_9_RIGHT = 337,
KEY_JOY_AXIS_10_LEFT = 338,
KEY_JOY_AXIS_10_RIGHT = 339,
KEY_JOY_AXIS_11_LEFT = 340,
KEY_JOY_AXIS_11_RIGHT = 341,
KEY_LAST = 512,
@ -324,8 +316,8 @@ enum
NUM_JOYSTICK_AXES_BUTTONS = KEY_JOY_AXIS_11_RIGHT - KEY_JOY_AXIS_0_LEFT + 1,
NUM_JOYSTICK_BUTTONS_PER_AXIS = KEY_JOY_AXIS_0_RIGHT - KEY_JOY_AXIS_0_LEFT + 1,
NUM_JOYSTICK_AXES = NUM_JOYSTICK_AXES_BUTTONS / NUM_JOYSTICK_BUTTONS_PER_AXIS,
NUM_JOYSTICK_HAT_BUTTONS = KEY_JOY_HAT1_RIGHTDOWN - KEY_JOY_HAT0_LEFTUP + 1,
NUM_JOYSTICK_BUTTONS_PER_HAT = KEY_JOY_HAT1_RIGHTDOWN - KEY_JOY_HAT1_LEFTUP + 1,
NUM_JOYSTICK_HAT_BUTTONS = KEY_JOY_HAT1_DOWN - KEY_JOY_HAT0_UP + 1,
NUM_JOYSTICK_BUTTONS_PER_HAT = KEY_JOY_HAT1_DOWN - KEY_JOY_HAT1_UP + 1,
NUM_JOYSTICK_HATS = NUM_JOYSTICK_HAT_BUTTONS / NUM_JOYSTICK_BUTTONS_PER_HAT,
};