11#include " graphics/presentation/window/hostInput.h"
22
3+ #include " SDL_gamecontroller.h"
34#include " SDL_keyboard.h"
45#include " SDL_keycode.h"
56#include " SDL_mouse.h"
@@ -55,9 +56,10 @@ static constexpr std::array CONTROL_INFO = {
5556constexpr std::size_t INVALID_CONTROL = CONTROL_INFO .size();
5657
5758struct Binding {
58- SDL_Keycode key = SDLK_UNKNOWN ;
59- uint8_t mouse_button = 0 ;
60- std::size_t control = INVALID_CONTROL ;
59+ SDL_Keycode key = SDLK_UNKNOWN ;
60+ uint8_t mouse_button = 0 ;
61+ int gamepad_button = -1 ; // SDL_GameControllerButton or -1
62+ std::size_t control = INVALID_CONTROL ;
6163};
6264
6365std::size_t ControlFromName (std::string_view name) {
@@ -95,10 +97,17 @@ uint8_t MouseButtonFromName(std::string_view name) {
9597 return button != buttons.end () ? button->second : 0 ;
9698}
9799
100+ int GamepadButtonFromName (std::string_view name) {
101+ if (!name.starts_with (" Pad:" )) return -1 ;
102+ return static_cast <int >(
103+ SDL_GameControllerGetButtonFromString (std::string (name.substr (4 )).c_str ()));
104+ }
105+
98106bool Conflicts (const Binding& first, const Binding& second) {
99107 return first.control == second.control ||
100108 (first.key != SDLK_UNKNOWN && first.key == second.key ) ||
101- (first.mouse_button != 0 && first.mouse_button == second.mouse_button );
109+ (first.mouse_button != 0 && first.mouse_button == second.mouse_button ) ||
110+ (first.gamepad_button >= 0 && first.gamepad_button == second.gamepad_button );
102111}
103112
104113class InputMap {
@@ -108,23 +117,27 @@ class InputMap {
108117 const std::string_view entry = value;
109118 const auto split = entry.find (' =' );
110119
111- Binding binding;
112- if (split != std::string_view::npos) {
113- binding.control = ControlFromName (entry.substr (0 , split));
114- const auto host_input = entry.substr (split + 1 );
115- binding.mouse_button = MouseButtonFromName (host_input);
116- if (binding.mouse_button == 0 ) {
117- binding.key = NormalizeKey (SDL_GetKeyFromName (std::string (host_input).c_str ()));
118- }
120+ Binding binding;
121+ if (split != std::string_view::npos) {
122+ binding.control = ControlFromName (entry.substr (0 , split));
123+ const auto host_input = entry.substr (split + 1 );
124+ binding.mouse_button = MouseButtonFromName (host_input);
125+ if (binding.mouse_button == 0 ) {
126+ binding.gamepad_button = GamepadButtonFromName (host_input);
119127 }
120-
121- const bool reserved =
122- binding.key == SDLK_ESCAPE || binding.key == SDLK_SPACE || binding.key == SDLK_F1 ;
123- if (binding.control == INVALID_CONTROL || reserved ||
124- (binding.key == SDLK_UNKNOWN && binding.mouse_button == 0 )) {
125- EXIT (" Invalid input mapping: %s\n " , value.c_str ());
128+ if (binding.mouse_button == 0 && binding.gamepad_button < 0 ) {
129+ binding.key = NormalizeKey (SDL_GetKeyFromName (std::string (host_input).c_str ()));
126130 }
127- Add (binding);
131+ }
132+
133+ const bool reserved =
134+ binding.key == SDLK_ESCAPE || binding.key == SDLK_SPACE || binding.key == SDLK_F1 ;
135+ const bool has_binding = binding.key != SDLK_UNKNOWN || binding.mouse_button != 0 ||
136+ binding.gamepad_button >= 0 ;
137+ if (binding.control == INVALID_CONTROL || reserved || !has_binding) {
138+ EXIT (" Invalid input mapping: %s\n " , value.c_str ());
139+ }
140+ Add (binding);
128141 }
129142 }
130143 [[nodiscard]] bool Custom () const { return m_custom; }
@@ -144,6 +157,13 @@ class InputMap {
144157 return binding != m_bindings.begin () + m_size ? binding->control : INVALID_CONTROL ;
145158 }
146159
160+ [[nodiscard]] std::size_t FindGamepadButton (int button) const {
161+ const auto binding = std::find_if (
162+ m_bindings.begin (), m_bindings.begin () + m_size,
163+ [button](const auto & item) { return item.gamepad_button == button; });
164+ return binding != m_bindings.begin () + m_size ? binding->control : INVALID_CONTROL ;
165+ }
166+
147167private:
148168 void Add (const Binding& binding) {
149169 for (std::size_t index = 0 ; index < m_size;) {
@@ -302,4 +322,11 @@ void HostInputMouseButton(uint8_t mouse_button, bool down) {
302322 }
303323}
304324
325+ void HostInputGamepadButton (int gamepad_button, bool down) {
326+ const auto & map = GetInputMap ();
327+ if (map.Custom () && gamepad_button >= 0 ) {
328+ SetControl (map.FindGamepadButton (gamepad_button), down);
329+ }
330+ }
331+
305332} // namespace Libs::Graphics
0 commit comments