6153: Handle ordinal joystick hat keys as combined cardinal hat keys r=def- a=Robyt3

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.

## Checklist

- [X] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Robert Müller <robytemueller@gmail.com>
This commit is contained in:
bors[bot] 2022-12-17 16:58:31 +00:00 committed by GitHub
commit c4fdf20df9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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,22 +459,26 @@ 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)
{
m_aInputState[CurrentKey] = true;
m_aInputCount[CurrentKey] = m_InputCounter;
AddEvent(0, CurrentKey, IInput::FLAG_PRESS);
if(CurrentKey != KEY_UNKNOWN && !m_aInputState[CurrentKey])
{
m_aInputState[CurrentKey] = true;
m_aInputCount[CurrentKey] = m_InputCounter;
AddEvent(0, CurrentKey, IInput::FLAG_PRESS);
}
}
}

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,
};