diff --git a/source/director.cpp b/source/director.cpp index bc3fab48..7d48218b 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -203,11 +203,8 @@ void Director::createSystemFolder(const std::string &folder) // Inicia las variables necesarias para arrancar el programa void Director::initInput() { - // Establece si ha de mostrar mensajes - Input::get()->setVerbose(options.console); - // Busca si hay un mando conectado - Input::get()->discoverGameController(); + Input::get()->discoverGameControllers(); // Teclado - Movimiento if (options.keys == ControlScheme::CURSOR) @@ -250,24 +247,29 @@ void Director::initInput() Input::get()->bindKey(InputAction::TOGGLE_MUSIC, SDL_SCANCODE_M); Input::get()->bindKey(InputAction::TOGGLE_BORDER, SDL_SCANCODE_B); - // Mando - Movimiento - Input::get()->bindGameControllerButton(InputAction::JUMP, SDL_CONTROLLER_BUTTON_B); - Input::get()->bindGameControllerButton(InputAction::LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT); - Input::get()->bindGameControllerButton(InputAction::RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); + // MANDO + const int NUM_GAMEPADS = Input::get()->getNumControllers(); + for (int i = 0; i < NUM_GAMEPADS; ++i) + { + // Movimiento + Input::get()->bindGameControllerButton(i, InputAction::JUMP, SDL_CONTROLLER_BUTTON_B); + Input::get()->bindGameControllerButton(i, InputAction::LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT); + Input::get()->bindGameControllerButton(i, InputAction::RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); - // Mando - Otros - Input::get()->bindGameControllerButton(InputAction::ACCEPT, SDL_CONTROLLER_BUTTON_B); - Input::get()->bindGameControllerButton(InputAction::CANCEL, SDL_CONTROLLER_BUTTON_A); + // Otros + Input::get()->bindGameControllerButton(i, InputAction::ACCEPT, SDL_CONTROLLER_BUTTON_B); + Input::get()->bindGameControllerButton(i, InputAction::CANCEL, SDL_CONTROLLER_BUTTON_A); #ifdef GAME_CONSOLE - Input::get()->bindGameControllerButton(InputAction::input_pause, SDL_CONTROLLER_BUTTON_BACK); - Input::get()->bindGameControllerButton(InputAction::input_exit, SDL_CONTROLLER_BUTTON_START); + Input::get()->bindGameControllerButton(i, InputAction::input_pause, SDL_CONTROLLER_BUTTON_BACK); + Input::get()->bindGameControllerButton(i, InputAction::input_exit, SDL_CONTROLLER_BUTTON_START); #else - Input::get()->bindGameControllerButton(InputAction::PAUSE, SDL_CONTROLLER_BUTTON_START); - Input::get()->bindGameControllerButton(InputAction::EXIT, SDL_CONTROLLER_BUTTON_BACK); + Input::get()->bindGameControllerButton(i, InputAction::PAUSE, SDL_CONTROLLER_BUTTON_START); + Input::get()->bindGameControllerButton(i, InputAction::EXIT, SDL_CONTROLLER_BUTTON_BACK); #endif - Input::get()->bindGameControllerButton(InputAction::NEXT_PALETTE, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); - Input::get()->bindGameControllerButton(InputAction::TOGGLE_MUSIC, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); - Input::get()->bindGameControllerButton(InputAction::TOGGLE_BORDER, SDL_CONTROLLER_BUTTON_X); + Input::get()->bindGameControllerButton(i, InputAction::NEXT_PALETTE, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); + Input::get()->bindGameControllerButton(i, InputAction::TOGGLE_MUSIC, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); + Input::get()->bindGameControllerButton(i, InputAction::TOGGLE_BORDER, SDL_CONTROLLER_BUTTON_X); + } } // Inicializa JailAudio diff --git a/source/game.cpp b/source/game.cpp index 90c07840..c4b9d781 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -9,7 +9,7 @@ #include "defines.h" // Para BLOCK, PLAY_AREA_HEIGHT, BORDER_BOTTOM #include "global_events.h" // Para check #include "global_inputs.h" // Para check -#include "input.h" // Para Input, InputAction, REPEAT_FALSE +#include "input.h" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT #include "item_tracker.h" // Para ItemTracker #include "jail_audio.h" // Para JA_PauseMusic, JA_GetMusicState, JA_P... #include "notifier.h" // Para Notifier, NotificationText, CHEEVO_NO... @@ -82,14 +82,14 @@ void Game::checkEvents() // Comprueba el teclado void Game::checkInput() { - if (Input::get()->checkInput(InputAction::TOGGLE_MUSIC, REPEAT_FALSE)) + if (Input::get()->checkInput(InputAction::TOGGLE_MUSIC, INPUT_DO_NOT_ALLOW_REPEAT)) { board_->music = !board_->music; board_->music ? JA_ResumeMusic() : JA_PauseMusic(); Notifier::get()->show({"MUSIC " + std::string(board_->music ? "ENABLED" : "DISABLED")}, NotificationText::CENTER); } - else if (Input::get()->checkInput(InputAction::PAUSE, REPEAT_FALSE)) + else if (Input::get()->checkInput(InputAction::PAUSE, INPUT_DO_NOT_ALLOW_REPEAT)) { togglePause(); Notifier::get()->show({std::string(paused_ ? "GAME PAUSED" : "GAME RUNNING")}, NotificationText::CENTER); diff --git a/source/global_inputs.cpp b/source/global_inputs.cpp index e302e42f..bd33e157 100644 --- a/source/global_inputs.cpp +++ b/source/global_inputs.cpp @@ -3,7 +3,7 @@ #include // Para SDL_FALSE, SDL_TRUE #include // Para allocator, operator+, char_traits, string #include // Para vector -#include "input.h" // Para Input, InputAction, REPEAT_FALSE +#include "input.h" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT #include "notifier.h" // Para Notifier, NotificationText #include "options.h" // Para Options, options, OptionsVideo, Section #include "screen.h" // Para Screen @@ -51,29 +51,29 @@ namespace globalInputs // Comprueba los inputs que se pueden introducir en cualquier sección del juego void check() { - if (Input::get()->checkInput(InputAction::EXIT, REPEAT_FALSE)) + if (Input::get()->checkInput(InputAction::EXIT, INPUT_DO_NOT_ALLOW_REPEAT)) { quit(); } - else if (Input::get()->checkInput(InputAction::ACCEPT, REPEAT_FALSE)) + else if (Input::get()->checkInput(InputAction::ACCEPT, INPUT_DO_NOT_ALLOW_REPEAT)) { skip_section(); } - else if (Input::get()->checkInput(InputAction::TOGGLE_BORDER, REPEAT_FALSE)) + else if (Input::get()->checkInput(InputAction::TOGGLE_BORDER, INPUT_DO_NOT_ALLOW_REPEAT)) { Screen::get()->toggleBorder(); Notifier::get()->show({"BORDER " + std::string(options.video.border.enabled ? "ENABLED" : "DISABLED")}, NotificationText::CENTER); } - else if (Input::get()->checkInput(InputAction::TOGGLE_VIDEOMODE, REPEAT_FALSE)) + else if (Input::get()->checkInput(InputAction::TOGGLE_VIDEOMODE, INPUT_DO_NOT_ALLOW_REPEAT)) { Screen::get()->toggleVideoMode(); Notifier::get()->show({"FULLSCREEN " + std::string(options.video.mode == 0 ? "DISABLED" : "ENABLED")}, NotificationText::CENTER); } - else if (Input::get()->checkInput(InputAction::WINDOW_DEC_ZOOM, REPEAT_FALSE)) + else if (Input::get()->checkInput(InputAction::WINDOW_DEC_ZOOM, INPUT_DO_NOT_ALLOW_REPEAT)) { if (Screen::get()->decWindowZoom()) { @@ -81,7 +81,7 @@ namespace globalInputs } } - else if (Input::get()->checkInput(InputAction::WINDOW_INC_ZOOM, REPEAT_FALSE)) + else if (Input::get()->checkInput(InputAction::WINDOW_INC_ZOOM, INPUT_DO_NOT_ALLOW_REPEAT)) { if (Screen::get()->incWindowZoom()) { @@ -89,25 +89,25 @@ namespace globalInputs } } - else if (Input::get()->checkInput(InputAction::TOGGLE_SHADERS, REPEAT_FALSE)) + else if (Input::get()->checkInput(InputAction::TOGGLE_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT)) { Screen::get()->toggleShaders(); Notifier::get()->show({"SHADERS " + std::string(options.video.shaders ? "ENABLED" : "DISABLED")}, NotificationText::CENTER); } - else if (Input::get()->checkInput(InputAction::NEXT_PALETTE, REPEAT_FALSE)) + else if (Input::get()->checkInput(InputAction::NEXT_PALETTE, INPUT_DO_NOT_ALLOW_REPEAT)) { Screen::get()->nextPalette(); Notifier::get()->show({"PALETTE " + options.video.palette}, NotificationText::CENTER); } - else if (Input::get()->checkInput(InputAction::PREVIOUS_PALETTE, REPEAT_FALSE)) + else if (Input::get()->checkInput(InputAction::PREVIOUS_PALETTE, INPUT_DO_NOT_ALLOW_REPEAT)) { Screen::get()->previousPalette(); Notifier::get()->show({"PALETTE " + options.video.palette}, NotificationText::CENTER); } - else if (Input::get()->checkInput(InputAction::TOGGLE_INTEGER_SCALE, REPEAT_FALSE)) + else if (Input::get()->checkInput(InputAction::TOGGLE_INTEGER_SCALE, INPUT_DO_NOT_ALLOW_REPEAT)) { options.video.integer_scale = !options.video.integer_scale; SDL_RenderSetIntegerScale(Screen::get()->getRenderer(), options.video.integer_scale ? SDL_TRUE : SDL_FALSE); diff --git a/source/input.cpp b/source/input.cpp index 4e901e73..c4eb2a2f 100644 --- a/source/input.cpp +++ b/source/input.cpp @@ -2,9 +2,12 @@ #include // Para SDL_INIT_GAMECONTROLLER, SDL_InitSubS... #include // Para SDL_GetError #include // Para SDL_ENABLE -#include // Para SDL_NumJoysticks #include // Para SDL_GetKeyboardState -#include // Para basic_ostream, operator<<, cout, basi... +#include // Para find +#include // Para basic_ostream, operator<<, cout, endl +#include // Para distance +#include // Para unordered_map, operator==, _Node_cons... +#include // Para pair // [SINGLETON] Input *Input::input_ = nullptr; @@ -29,18 +32,17 @@ Input *Input::get() // Constructor Input::Input(const std::string &game_controller_db_path) - : db_path_(game_controller_db_path) + : game_controller_db_path_(game_controller_db_path) { - // Inicializa las variables - KeyBindings kb; - kb.scancode = 0; - kb.active = false; - key_bindings_.resize(static_cast(InputAction::SIZE), kb); + // Busca si hay mandos conectados + discoverGameControllers(); - GameControllerBindings gcb; - gcb.button = SDL_CONTROLLER_BUTTON_INVALID; - gcb.active = false; - game_controller_bindings_.resize(static_cast(InputAction::SIZE), gcb); + // Inicializa los vectores + key_bindings_.resize(static_cast(InputAction::SIZE), KeyBindings()); + controller_bindings_.resize(num_gamepads_, std::vector(static_cast(InputAction::SIZE), ControllerBindings())); + + // Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas + button_inputs_ = {InputAction::JUMP}; } // Asigna inputs a teclas @@ -50,133 +52,117 @@ void Input::bindKey(InputAction input, SDL_Scancode code) } // Asigna inputs a botones del mando -void Input::bindGameControllerButton(InputAction input, SDL_GameControllerButton button) +void Input::bindGameControllerButton(int controller_index, InputAction input, SDL_GameControllerButton button) { - game_controller_bindings_.at(static_cast(input)).button = button; + if (controller_index < num_gamepads_) + { + controller_bindings_.at(controller_index).at(static_cast(input)).button = button; + } +} + +// Asigna inputs a botones del mando +void Input::bindGameControllerButton(int controller_index, InputAction input_target, InputAction input_source) +{ + if (controller_index < num_gamepads_) + { + controller_bindings_.at(controller_index).at(static_cast(input_target)).button = controller_bindings_.at(controller_index).at(static_cast(input_source)).button; + } } // Comprueba si un input esta activo -bool Input::checkInput(InputAction input, bool repeat, int device, int index) +bool Input::checkInput(InputAction input, bool repeat, InputDeviceToUse device, int controller_index) { - if (!enabled_) - { - return false; - } + bool success_keyboard = false; + bool success_controller = false; + const int input_index = static_cast(input); - bool successKeyboard = false; - bool successGameController = false; - - if (device == INPUT_USE_ANY) - { - index = 0; - } - - if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY) + if (device == InputDeviceToUse::KEYBOARD || device == InputDeviceToUse::ANY) { const Uint8 *keyStates = SDL_GetKeyboardState(nullptr); if (repeat) { - if (keyStates[key_bindings_.at(static_cast(input)).scancode] != 0) - { - successKeyboard = true; - } - else - { - successKeyboard = false; - } + success_keyboard = keyStates[key_bindings_[input_index].scancode] != 0; } else { - if (!key_bindings_.at(static_cast(input)).active) + if (!key_bindings_[input_index].active) { - if (keyStates[key_bindings_.at(static_cast(input)).scancode] != 0) + if (keyStates[key_bindings_[input_index].scancode] != 0) { - key_bindings_.at(static_cast(input)).active = true; - successKeyboard = true; + key_bindings_[input_index].active = true; + success_keyboard = true; } else { - successKeyboard = false; + success_keyboard = false; } } else { - if (keyStates[key_bindings_.at(static_cast(input)).scancode] == 0) + if (keyStates[key_bindings_[input_index].scancode] == 0) { - key_bindings_.at(static_cast(input)).active = false; - successKeyboard = false; + key_bindings_[input_index].active = false; + } + success_keyboard = false; + } + } + } + + if (gameControllerFound() && controller_index >= 0 && controller_index < num_gamepads_) + { + if ((device == InputDeviceToUse::CONTROLLER) || (device == InputDeviceToUse::ANY)) + { + success_controller = checkAxisInput(input, controller_index, repeat); + + if (!success_controller) + { + if (repeat) + { + success_controller = SDL_GameControllerGetButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) != 0; } else { - successKeyboard = false; + if (!controller_bindings_.at(controller_index).at(input_index).active) + { + if (SDL_GameControllerGetButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) != 0) + { + controller_bindings_.at(controller_index).at(input_index).active = true; + success_controller = true; + } + else + { + success_controller = false; + } + } + else + { + if (SDL_GameControllerGetButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) == 0) + { + controller_bindings_.at(controller_index).at(input_index).active = false; + } + success_controller = false; + } } } } } - if (gameControllerFound()) - if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY)) - { - if (repeat) - { - if (SDL_GameControllerGetButton(connected_controllers_.at(index), game_controller_bindings_.at(static_cast(input)).button) != 0) - { - successGameController = true; - } - else - { - successGameController = false; - } - } - else - { - if (!game_controller_bindings_.at(static_cast(input)).active) - { - if (SDL_GameControllerGetButton(connected_controllers_.at(index), game_controller_bindings_.at(static_cast(input)).button) != 0) - { - game_controller_bindings_.at(static_cast(input)).active = true; - successGameController = true; - } - else - { - successGameController = false; - } - } - else - { - if (SDL_GameControllerGetButton(connected_controllers_.at(index), game_controller_bindings_.at(static_cast(input)).button) == 0) - { - game_controller_bindings_.at(static_cast(input)).active = false; - successGameController = false; - } - else - { - successGameController = false; - } - } - } - } - - return (successKeyboard || successGameController); + return (success_keyboard || success_controller); } // Comprueba si hay almenos un input activo -bool Input::checkAnyInput(int device, int index) +bool Input::checkAnyInput(InputDeviceToUse device, int controller_index) { - if (device == INPUT_USE_ANY) - { - index = 0; - } - - if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY) + if (device == InputDeviceToUse::KEYBOARD || device == InputDeviceToUse::ANY) { const Uint8 *mKeystates = SDL_GetKeyboardState(nullptr); for (int i = 0; i < (int)key_bindings_.size(); ++i) { - if (mKeystates[key_bindings_[i].scancode] != 0) + if (mKeystates[key_bindings_[i].scancode] != 0 && !key_bindings_[i].active) { + key_bindings_[i].active = true; return true; } } @@ -184,12 +170,13 @@ bool Input::checkAnyInput(int device, int index) if (gameControllerFound()) { - if (device == INPUT_USE_GAMECONTROLLER || device == INPUT_USE_ANY) + if (device == InputDeviceToUse::CONTROLLER || device == InputDeviceToUse::ANY) { - for (int i = 0; i < (int)game_controller_bindings_.size(); ++i) + for (int i = 0; i < (int)controller_bindings_.size(); ++i) { - if (SDL_GameControllerGetButton(connected_controllers_.at(index), game_controller_bindings_[i].button) != 0) + if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][i].button) != 0 && !controller_bindings_[controller_index][i].active) { + controller_bindings_[controller_index][i].active = true; return true; } } @@ -199,8 +186,8 @@ bool Input::checkAnyInput(int device, int index) return false; } -// Busca si hay un mando conectado -bool Input::discoverGameController() +// Busca si hay mandos conectados +bool Input::discoverGameControllers() { bool found = false; @@ -209,30 +196,35 @@ bool Input::discoverGameController() SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); } - if (SDL_GameControllerAddMappingsFromFile(db_path_.c_str()) < 0) + if (SDL_GameControllerAddMappingsFromFile(game_controller_db_path_.c_str()) < 0) { - if (verbose_) - { - std::cout << "Error, could not load " << db_path_.c_str() << " file: " << SDL_GetError() << std::endl; - } + std::cout << "Error, could not load " << game_controller_db_path_.c_str() << " file: " << SDL_GetError() << std::endl; } - const int nJoysticks = SDL_NumJoysticks(); + num_joysticks_ = SDL_NumJoysticks(); num_gamepads_ = 0; - // Cuenta el numero de mandos - for (int i = 0; i < nJoysticks; ++i) + // Cuenta el número de mandos + joysticks_.clear(); + for (int i = 0; i < num_joysticks_; ++i) { + auto joy = SDL_JoystickOpen(i); + joysticks_.push_back(joy); if (SDL_IsGameController(i)) { num_gamepads_++; } } - if (verbose_) + std::cout << "\n** LOOKING FOR GAME CONTROLLERS" << std::endl; + if (num_joysticks_ != num_gamepads_) { - std::cout << "\nChecking for game controllers...\n"; - std::cout << nJoysticks << " joysticks found, " << num_gamepads_ << " are gamepads\n"; + std::cout << "Joysticks found: " << num_joysticks_ << std::endl; + std::cout << "Gamepads found : " << num_gamepads_ << std::endl; + } + else + { + std::cout << "Gamepads found: " << num_gamepads_ << std::endl; } if (num_gamepads_ > 0) @@ -242,69 +234,110 @@ bool Input::discoverGameController() for (int i = 0; i < num_gamepads_; i++) { // Abre el mando y lo añade a la lista - SDL_GameController *pad = SDL_GameControllerOpen(i); + auto pad = SDL_GameControllerOpen(i); if (SDL_GameControllerGetAttached(pad) == 1) { connected_controllers_.push_back(pad); - const std::string separator(" #"); - std::string name = SDL_GameControllerNameForIndex(i); - name.resize(25); - name = name + separator + std::to_string(i); - if (verbose_) - { - std::cout << name << std::endl; - } + const std::string name = SDL_GameControllerNameForIndex(i); + std::cout << "#" << i << ": " << name << std::endl; controller_names_.push_back(name); } else { - if (verbose_) - { - std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl; - } + std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl; } } SDL_GameControllerEventState(SDL_ENABLE); } + std::cout << "\n** FINISHED LOOKING FOR GAME CONTROLLERS" << std::endl; return found; } // Comprueba si hay algun mando conectado -bool Input::gameControllerFound() -{ - if (num_gamepads_ > 0) - { - return true; - } - else - { - return false; - } -} +bool Input::gameControllerFound() { return num_gamepads_ > 0 ? true : false; } // Obten el nombre de un mando de juego -std::string Input::getControllerName(int index) +std::string Input::getControllerName(int controller_index) const { return num_gamepads_ > 0 ? controller_names_.at(controller_index) : std::string(); } + +// Obten el número de mandos conectados +int Input::getNumControllers() const { return num_gamepads_; } + +// Obtiene el indice del controlador a partir de un event.id +int Input::getJoyIndex(int id) const { - if (num_gamepads_ > 0) + for (int i = 0; i < num_joysticks_; ++i) { - return controller_names_[index]; + if (SDL_JoystickInstanceID(joysticks_[i]) == id) + { + return i; + } + } + return -1; +} + +// Obtiene el SDL_GameControllerButton asignado a un input +SDL_GameControllerButton Input::getControllerBinding(int controller_index, InputAction input) const +{ + return controller_bindings_[controller_index][static_cast(input)].button; +} + +// Obtiene el indice a partir del nombre del mando +int Input::getIndexByName(const std::string &name) const +{ + auto it = std::find(controller_names_.begin(), controller_names_.end(), name); + return it != controller_names_.end() ? std::distance(controller_names_.begin(), it) : -1; +} + +// Comprueba el eje del mando +bool Input::checkAxisInput(InputAction input, int controller_index, bool repeat) +{ + // Umbral para considerar el eje como activo + const Sint16 threshold = 30000; + bool axis_active_now = false; + + switch (input) + { + case InputAction::LEFT: + axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) < -threshold; + break; + case InputAction::RIGHT: + axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) > threshold; + break; + case InputAction::UP: + axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) < -threshold; + break; + case InputAction::DOWN: + axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) > threshold; + break; + default: + return false; + } + + // Referencia al binding correspondiente + auto &binding = controller_bindings_.at(controller_index).at(static_cast(input)); + + if (repeat) + { + // Si se permite repetir, simplemente devolvemos el estado actual + return axis_active_now; } else { - return ""; + // Si no se permite repetir, aplicamos la lógica de transición + if (axis_active_now && !binding.axis_active) + { + // Transición de inactivo a activo + binding.axis_active = true; + return true; + } + else if (!axis_active_now && binding.axis_active) + { + // Transición de activo a inactivo + binding.axis_active = false; + } + // Mantener el estado actual + return false; } -} - -// Obten el numero de mandos conectados -int Input::getNumControllers() -{ - return num_gamepads_; -} - -// Establece si ha de mostrar mensajes -void Input::setVerbose(bool value) -{ - verbose_ = value; } \ No newline at end of file diff --git a/source/input.h b/source/input.h index 963aaaf2..deffc537 100644 --- a/source/input.h +++ b/source/input.h @@ -7,18 +7,20 @@ #include // Para vector // Definiciones de repetición -constexpr bool REPEAT_TRUE = true; -constexpr bool REPEAT_FALSE = false; +constexpr bool INPUT_ALLOW_REPEAT = true; +constexpr bool INPUT_DO_NOT_ALLOW_REPEAT = false; // Tipos de entrada -constexpr int INPUT_USE_KEYBOARD = 0; -constexpr int INPUT_USE_GAMECONTROLLER = 1; -constexpr int INPUT_USE_ANY = 2; +enum class InputDeviceToUse : int +{ + KEYBOARD = 0, + CONTROLLER = 1, + ANY = 2, +}; enum class InputAction { // Inputs obligatorios - NONE, UP, DOWN, LEFT, @@ -41,6 +43,7 @@ enum class InputAction TOGGLE_SHADERS, // Input obligatorio + NONE, SIZE }; @@ -54,25 +57,36 @@ private: { Uint8 scancode; // Scancode asociado bool active; // Indica si está activo + + // Constructor + explicit KeyBindings(Uint8 sc = 0, bool act = false) + : scancode(sc), active(act) {} }; - struct GameControllerBindings + struct ControllerBindings { SDL_GameControllerButton button; // GameControllerButton asociado bool active; // Indica si está activo + bool axis_active; // Estado del eje + + // Constructor + explicit ControllerBindings(SDL_GameControllerButton btn = SDL_CONTROLLER_BUTTON_INVALID, bool act = false, bool axis_act = false) + : button(btn), active(act), axis_active(axis_act) {} }; - // Objetos y punteros - std::vector connected_controllers_; // Vector con todos los mandos conectados - // Variables - std::vector key_bindings_; // Vector con las teclas asociadas a los inputs predefinidos - std::vector game_controller_bindings_; // Vector con las teclas asociadas a los inputs predefinidos - std::vector controller_names_; // Vector con los nombres de los mandos - int num_gamepads_ = 0; // Numero de mandos conectados - std::string db_path_; // Ruta al archivo gamecontrollerdb.txt - bool verbose_ = true; // Indica si ha de mostrar mensajes - bool enabled_ = true; // Indica si está habilitado + std::vector connected_controllers_; // Vector con todos los mandos conectados + std::vector joysticks_; // Vector con todos los joysticks conectados + std::vector key_bindings_; // Vector con las teclas asociadas a los inputs predefinidos + std::vector> controller_bindings_; // Vector con los botones asociadas a los inputs predefinidos para cada mando + std::vector controller_names_; // Vector con los nombres de los mandos + std::vector button_inputs_; // Inputs asignados al jugador y a botones, excluyendo direcciones + int num_joysticks_ = 0; // Número de joysticks conectados + int num_gamepads_ = 0; // Número de mandos conectados + std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt + + // Comprueba el eje del mando + bool checkAxisInput(InputAction input, int controller_index, bool repeat); // Constructor explicit Input(const std::string &game_controller_db_path); @@ -94,26 +108,33 @@ public: void bindKey(InputAction input, SDL_Scancode code); // Asigna inputs a botones del mando - void bindGameControllerButton(InputAction input, SDL_GameControllerButton button); + void bindGameControllerButton(int controller_index, InputAction input, SDL_GameControllerButton button); + void bindGameControllerButton(int controller_index, InputAction inputTarget, InputAction inputSource); // Comprueba si un input esta activo - bool checkInput(InputAction input, bool repeat = true, int device = INPUT_USE_ANY, int index = 0); + bool checkInput(InputAction input, bool repeat = true, InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0); // Comprueba si hay almenos un input activo - bool checkAnyInput(int device = INPUT_USE_ANY, int index = 0); + bool checkAnyInput(InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0); - // Busca si hay un mando conectado - bool discoverGameController(); + // Busca si hay mandos conectados + bool discoverGameControllers(); // Comprueba si hay algun mando conectado bool gameControllerFound(); - // Obten el numero de mandos conectados - int getNumControllers(); + // Obten el número de mandos conectados + int getNumControllers() const; // Obten el nombre de un mando de juego - std::string getControllerName(int index); + std::string getControllerName(int controller_index) const; - // Establece si ha de mostrar mensajes - void setVerbose(bool value); + // Obtiene el indice del controlador a partir de un event.id + int getJoyIndex(int id) const; + + // Obtiene el SDL_GameControllerButton asignado a un input + SDL_GameControllerButton getControllerBinding(int controller_index, InputAction input) const; + + // Obtiene el indice a partir del nombre del mando + int getIndexByName(const std::string &name) const; }; \ No newline at end of file diff --git a/source/title.cpp b/source/title.cpp index dd15dbc5..b053ab52 100644 --- a/source/title.cpp +++ b/source/title.cpp @@ -7,7 +7,7 @@ #include "defines.h" // Para PLAY_AREA_CENTER_X, GAMECANVAS_WIDTH #include "global_events.h" // Para check #include "global_inputs.h" // Para check -#include "input.h" // Para Input, InputAction, REPEAT_FALSE, REP... +#include "input.h" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT, REP... #include "options.h" // Para Options, options, SectionState, Section #include "resource.h" // Para Resource #include "s_sprite.h" // Para SSprite @@ -96,22 +96,22 @@ void Title::checkInput() { if (show_cheevos_) { - if (Input::get()->checkInput(InputAction::DOWN, REPEAT_TRUE)) + if (Input::get()->checkInput(InputAction::DOWN, INPUT_ALLOW_REPEAT)) { moveCheevosList(1); } - else if (Input::get()->checkInput(InputAction::UP, REPEAT_TRUE)) + else if (Input::get()->checkInput(InputAction::UP, INPUT_ALLOW_REPEAT)) { moveCheevosList(0); } - else if (Input::get()->checkInput(InputAction::ACCEPT, REPEAT_FALSE)) + else if (Input::get()->checkInput(InputAction::ACCEPT, INPUT_DO_NOT_ALLOW_REPEAT)) { hideCheevosList(); counter_ = 0; } } - if (Input::get()->checkInput(InputAction::ACCEPT, REPEAT_FALSE)) + if (Input::get()->checkInput(InputAction::ACCEPT, INPUT_DO_NOT_ALLOW_REPEAT)) { if (state_ == TitleState::SHOW_LOADING_SCREEN) {