diff --git a/Packaging/OpenDingux/build.sh b/Packaging/OpenDingux/build.sh index 90025e903..c89bace2e 100755 --- a/Packaging/OpenDingux/build.sh +++ b/Packaging/OpenDingux/build.sh @@ -128,8 +128,8 @@ build() { -DKBCTRL_BUTTON_RIGHTSHOULDER=SDLK_BACKSPACE -DKBCTRL_BUTTON_LEFTSHOULDER=SDLK_TAB -DKBCTRL_BUTTON_START=SDLK_RETURN - -DKBCTRL_BUTTON_BACK=SDLK_ESCAPE - -DKBCTRL_MODIFIER_KEY=SDLK_END + -DKBCTRL_BUTTON_LEFTSTICK=SDLK_END # Suspend + -DKBCTRL_MODIFIER_KEY=SDLK_ESCAPE # Select ) fi cmake .. ${defs[@]} \ diff --git a/Packaging/OpenDingux/devilutionx-retrofw.man.txt b/Packaging/OpenDingux/devilutionx-retrofw.man.txt index 7e5c3a7fe..2c35e68a0 100644 --- a/Packaging/OpenDingux/devilutionx-retrofw.man.txt +++ b/Packaging/OpenDingux/devilutionx-retrofw.man.txt @@ -12,8 +12,10 @@ Controls: - Y: cast spell, go to previous screen when talking to people and in shops, delete character while in main menu - R1: inventory - L1: character -- Suspend + R1: Drink health potion -- Suspend + R2: Drink mana potion -- Suspend + Y: Quest log -- Select: automap +- Select + R1: Drink health potion +- Select + R2: Drink mana potion +- Select + D-pad: Move map/cursor +- Select + A: Left click +- Select + Y: Quest log +- Suspend: Map - Start: game Menu, skip intro diff --git a/Packaging/OpenDingux/readme.gcw0.txt b/Packaging/OpenDingux/readme.gcw0.txt index 97ee8a8df..dbb7546bb 100644 --- a/Packaging/OpenDingux/readme.gcw0.txt +++ b/Packaging/OpenDingux/readme.gcw0.txt @@ -18,9 +18,9 @@ Controls: - L1: character - R2: drink mana potion - L2: drink health potion -- Left analog click: quest log +- Left analog click: map - Right analog click: left mouse click -- Select: automap +- Select: quest log - Start: game Menu, skip intro Source: https://github.com/diasurgical/devilutionX/ diff --git a/SourceX/controls/README.md b/SourceX/controls/README.md index 8689f41c3..9168aad7a 100644 --- a/SourceX/controls/README.md +++ b/SourceX/controls/README.md @@ -18,3 +18,22 @@ Low-level gamepad handling is abstracted and 3 implementations are provided: This can be used for testing, or on devices where this is the only or the easiest API to use (e.g. RetroFW). + +Example keyboard-as-controller build flags: + +```bash +cmake .. -DUSE_SDL1=ON -DHAS_KBCTRL=1 \ +-DKBCTRL_BUTTON_DPAD_LEFT=SDLK_LEFT \ +-DKBCTRL_BUTTON_DPAD_RIGHT=SDLK_RIGHT \ +-DKBCTRL_BUTTON_DPAD_UP=SDLK_UP \ +-DKBCTRL_BUTTON_DPAD_DOWN=SDLK_DOWN \ +-DKBCTRL_BUTTON_X=SDLK_y \ +-DKBCTRL_BUTTON_Y=SDLK_x \ +-DKBCTRL_BUTTON_B=SDLK_a \ +-DKBCTRL_BUTTON_A=SDLK_b \ +-DKBCTRL_BUTTON_RIGHTSHOULDER=SDLK_RIGHTBRACKET \ +-DKBCTRL_BUTTON_LEFTSHOULDER=SDLK_LEFTBRACKET \ +-DKBCTRL_BUTTON_LEFTSTICK=SDLK_TAB \ +-DKBCTRL_BUTTON_START=SDLK_RETURN \ +-DKBCTRL_MODIFIER_KEY=SDLK_LSHIFT +``` diff --git a/SourceX/controls/controller_buttons.h b/SourceX/controls/controller_buttons.h index 4f5a136fa..3da3ad2c6 100644 --- a/SourceX/controls/controller_buttons.h +++ b/SourceX/controls/controller_buttons.h @@ -9,6 +9,7 @@ namespace dvl { // A<->B and X<->Y are reversed on a Nintendo controller. enum class ControllerButton { NONE = 0, + IGNORE, AXIS_TRIGGERLEFT, // ZL (aka L2) AXIS_TRIGGERRIGHT, // ZR (aka R2) BUTTON_A, // Bottom button diff --git a/SourceX/controls/controller_motion.cpp b/SourceX/controls/controller_motion.cpp index 731c35108..8b9772d20 100644 --- a/SourceX/controls/controller_motion.cpp +++ b/SourceX/controls/controller_motion.cpp @@ -2,6 +2,7 @@ #include "controls/devices/game_controller.h" #include "controls/devices/joystick.h" +#include "controls/devices/kbcontroller.h" namespace dvl { @@ -88,6 +89,10 @@ bool ProcessControllerMotion(const SDL_Event &event) #endif if (ProcessJoystickAxisMotion(event)) return true; +#if HAS_KBCTRL == 1 + if (ProcessKbCtrlAxisMotion(event)) + return true; +#endif return false; } diff --git a/SourceX/controls/devices/kbcontroller.cpp b/SourceX/controls/devices/kbcontroller.cpp index 299c4cea7..419c6f292 100644 --- a/SourceX/controls/devices/kbcontroller.cpp +++ b/SourceX/controls/devices/kbcontroller.cpp @@ -1,26 +1,8 @@ #include "controls/devices/kbcontroller.h" -#if defined(RETROFW) -#define HAS_KBCTRL 1 - -#define KBCTRL_BUTTON_DPAD_LEFT SDLK_LEFT -#define KBCTRL_BUTTON_DPAD_RIGHT SDLK_RIGHT -#define KBCTRL_BUTTON_DPAD_UP SDLK_UP -#define KBCTRL_BUTTON_DPAD_DOWN SDLK_DOWN - -#define KBCTRL_BUTTON_B SDLK_LCTRL -#define KBCTRL_BUTTON_A SDLK_LALT -#define KBCTRL_BUTTON_Y SDLK_SPACE -#define KBCTRL_BUTTON_X SDLK_LSHIFT -#define KBCTRL_BUTTON_RIGHTSHOULDER SDLK_BACKSPACE -#define KBCTRL_BUTTON_LEFTSHOULDER SDLK_TAB -#define KBCTRL_BUTTON_START SDLK_RETURN -#define KBCTRL_BUTTON_BACK SDLK_ESCAPE -#define KBCTRL_MODIFIER_KEY SDLK_END // The suspend key on RG300 -#endif - #if HAS_KBCTRL == 1 +#include "controls/controller_motion.h" #include "sdl2_to_1_2_backports.h" #include "sdl_compat.h" #include "stubs.h" @@ -46,24 +28,28 @@ ControllerButton KbCtrlToControllerButton(const SDL_Event &event) case SDL_KEYDOWN: case SDL_KEYUP: switch (event.key.keysym.sym) { +#ifdef KBCTRL_MODIFIER_KEY + case KBCTRL_MODIFIER_KEY: + return ControllerButton::IGNORE; +#endif #ifdef KBCTRL_BUTTON_A case KBCTRL_BUTTON_A: return ControllerButton::BUTTON_A; #endif #ifdef KBCTRL_BUTTON_B - case KBCTRL_BUTTON_B: + case KBCTRL_BUTTON_B: // Right button + if (IsModifierKey()) + return ControllerButton::BUTTON_RIGHTSTICK; return ControllerButton::BUTTON_B; #endif #ifdef KBCTRL_BUTTON_X - case KBCTRL_BUTTON_X: + case KBCTRL_BUTTON_X: // Left button if (IsModifierKey()) - return ControllerButton::BUTTON_LEFTSTICK; + return ControllerButton::BUTTON_BACK; return ControllerButton::BUTTON_X; #endif #ifdef KBCTRL_BUTTON_Y case KBCTRL_BUTTON_Y: - if (IsModifierKey()) - return ControllerButton::BUTTON_RIGHTSTICK; return ControllerButton::BUTTON_Y; #endif #ifdef KBCTRL_BUTTON_LEFTSTICK @@ -96,18 +82,26 @@ ControllerButton KbCtrlToControllerButton(const SDL_Event &event) #endif #ifdef KBCTRL_BUTTON_DPAD_UP case KBCTRL_BUTTON_DPAD_UP: + if (IsModifierKey()) + return ControllerButton::IGNORE; return ControllerButton::BUTTON_DPAD_UP; #endif #ifdef KBCTRL_BUTTON_DPAD_DOWN case KBCTRL_BUTTON_DPAD_DOWN: + if (IsModifierKey()) + return ControllerButton::IGNORE; return ControllerButton::BUTTON_DPAD_DOWN; #endif #ifdef KBCTRL_BUTTON_DPAD_LEFT case KBCTRL_BUTTON_DPAD_LEFT: + if (IsModifierKey()) + return ControllerButton::IGNORE; return ControllerButton::BUTTON_DPAD_LEFT; #endif #ifdef KBCTRL_BUTTON_DPAD_RIGHT case KBCTRL_BUTTON_DPAD_RIGHT: + if (IsModifierKey()) + return ControllerButton::IGNORE; return ControllerButton::BUTTON_DPAD_RIGHT; #endif default: @@ -186,9 +180,7 @@ int ControllerButtonToKbCtrlKeyCode(ControllerButton button) } } -} // namespace - -bool IsKbCtrlButtonPressed(ControllerButton button) +bool IsButtonPressed(ControllerButton button) { int key_code = ControllerButtonToKbCtrlKeyCode(button); if (key_code == -1) @@ -200,5 +192,44 @@ bool IsKbCtrlButtonPressed(ControllerButton button) #endif } +} // namespace + +bool IsKbCtrlButtonPressed(ControllerButton button) +{ + if (IsModifierKey() && (button == ControllerButton::BUTTON_DPAD_UP || button == ControllerButton::BUTTON_DPAD_DOWN || button == ControllerButton::BUTTON_DPAD_LEFT || button == ControllerButton::BUTTON_DPAD_RIGHT)) + return false; + return IsButtonPressed(button); +} + +bool ProcessKbCtrlAxisMotion(const SDL_Event &event) +{ + if (!IsModifierKey()) { + rightStickX = 0; + rightStickY = 0; + return false; + } + if (event.type != SDL_KEYUP && event.type != SDL_KEYDOWN) + return false; + const auto sym = event.key.keysym.sym; + if (sym != KBCTRL_BUTTON_DPAD_UP && sym != KBCTRL_BUTTON_DPAD_DOWN && sym != KBCTRL_BUTTON_DPAD_LEFT && sym != KBCTRL_BUTTON_DPAD_RIGHT) + return false; + if (IsButtonPressed(ControllerButton::BUTTON_DPAD_LEFT)) { + rightStickX = -1; + } else if (IsButtonPressed(ControllerButton::BUTTON_DPAD_RIGHT)) { + rightStickX = 1; + } else { + rightStickX = 0; + } + if (IsButtonPressed(ControllerButton::BUTTON_DPAD_UP)) { + rightStickY = 1; + } else if (IsButtonPressed(ControllerButton::BUTTON_DPAD_DOWN)) { + rightStickY = -1; + } else { + rightStickY = 0; + } + return true; +} + + } // namespace dvl #endif diff --git a/SourceX/controls/devices/kbcontroller.h b/SourceX/controls/devices/kbcontroller.h index 663979916..7bf75c9f5 100644 --- a/SourceX/controls/devices/kbcontroller.h +++ b/SourceX/controls/devices/kbcontroller.h @@ -19,5 +19,7 @@ ControllerButton KbCtrlToControllerButton(const SDL_Event &event); bool IsKbCtrlButtonPressed(ControllerButton button); +bool ProcessKbCtrlAxisMotion(const SDL_Event &event); + } // namespace dvl #endif diff --git a/SourceX/controls/game_controls.cpp b/SourceX/controls/game_controls.cpp index d0ec198b6..d8e61d9bb 100644 --- a/SourceX/controls/game_controls.cpp +++ b/SourceX/controls/game_controls.cpp @@ -47,6 +47,8 @@ bool GetGameAction(const SDL_Event &event, GameAction *action) { const ControllerButtonEvent ctrl_event = ToControllerButtonEvent(event); switch (ctrl_event.button) { + case ControllerButton::IGNORE: + return true; case ControllerButton::AXIS_TRIGGERLEFT: // ZL (aka L2) if (!ctrl_event.up) *action = GameAction(GameActionType::USE_HEALTH_POTION); diff --git a/SourceX/controls/menu_controls.cpp b/SourceX/controls/menu_controls.cpp index fe8bad3e1..daddf813f 100644 --- a/SourceX/controls/menu_controls.cpp +++ b/SourceX/controls/menu_controls.cpp @@ -10,6 +10,8 @@ MenuAction GetMenuAction(const SDL_Event &event) sgbControllerActive = true; if (!ctrl_event.up) { switch (ctrl_event.button) { + case ControllerButton::IGNORE: + return MenuAction::NONE; case ControllerButton::BUTTON_B: // Right button case ControllerButton::BUTTON_START: return MenuAction::SELECT; @@ -34,7 +36,7 @@ MenuAction GetMenuAction(const SDL_Event &event) break; } } - if (event.type < SDL_JOYAXISMOTION || event.type >= 0x700) + if (ctrl_event.button == ControllerButton::NONE && (event.type < SDL_JOYAXISMOTION || event.type >= 0x700)) sgbControllerActive = false; #if HAS_KBCTRL == 0