#pragma once #include // Para SDL_GamepadButton, SDL_Gamepad #include // Para SDL_Joystick, SDL_JoystickID #include // Para SDL_Scancode #include // Para Uint8 #include // Para string #include // Para vector /* connectedControllers es un vector donde están todos los mandos encontrados [0 .. n] checkInput requiere de un índice para comprobar las pulsaciones de un controlador en concreto [0 .. n] device contiene el tipo de dispositivo a comprobar: InputDeviceToUse::KEYBOARD solo mirará el teclado InputDeviceToUse::CONTROLLER solo mirará el controlador especificado (Si no se especifica, el primero) InputDeviceToUse::ANY mirará tanto el teclado como el PRIMER controlador */ // Acciones de entrada posibles en el juego enum class InputAction : int { // Inputs de movimiento UP, DOWN, LEFT, RIGHT, // Inputs personalizados FIRE_LEFT, FIRE_CENTER, FIRE_RIGHT, START, // Inputs de control EXIT, PAUSE, SERVICE, WINDOW_FULLSCREEN, WINDOW_INC_SIZE, WINDOW_DEC_SIZE, TOGGLE_VIDEO_SHADERS, TOGGLE_VIDEO_INTEGER_SCALE, TOGGLE_VIDEO_VSYNC, RESET, TOGGLE_AUDIO, CHANGE_LANG, SHOW_INFO, CONFIG, SWAP_CONTROLLERS, TOGGLE_AUTO_FIRE, // Input obligatorio NONE, SIZE, }; constexpr bool INPUT_ALLOW_REPEAT = true; constexpr bool INPUT_DO_NOT_ALLOW_REPEAT = false; // Tipos de dispositivos de entrada enum class InputDeviceToUse : int { KEYBOARD = 0, CONTROLLER = 1, ANY = 2, }; // Clase Input: gestiona la entrada de teclado y mandos (singleton) class Input { public: // --- Métodos de singleton --- static void init(const std::string &game_controller_db_path); // Inicializa el singleton static void destroy(); // Libera el singleton static Input *get(); // Obtiene la instancia // --- Métodos de configuración de controles --- void bindKey(InputAction input, SDL_Scancode code); // Asigna inputs a teclas void bindGameControllerButton(int controller_index, InputAction input, SDL_GamepadButton button); // Asigna inputs a botones del mando void bindGameControllerButton(int controller_index, InputAction inputTarget, InputAction inputSource); // Asigna inputs a otros inputs del mando // --- Métodos de consulta de entrada --- bool checkInput(InputAction input, bool repeat = true, InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0); // Comprueba si un input está activo bool checkAnyInput(InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0); // Comprueba si hay al menos un input activo int checkAnyButtonPressed(bool repeat = INPUT_DO_NOT_ALLOW_REPEAT); // Comprueba si hay algún botón pulsado // --- Métodos de gestión de mandos --- bool discoverGameControllers(); // Busca si hay mandos conectados bool gameControllerFound(); // Comprueba si hay algún mando conectado int getNumControllers() const; // Obtiene el número de mandos conectados std::string getControllerName(int controller_index) const; // Obtiene el nombre de un mando de juego int getJoyIndex(SDL_JoystickID id) const; // Obtiene el índice del controlador a partir de un event.id // --- Métodos de consulta y utilidades --- void printBindings(InputDeviceToUse device = InputDeviceToUse::KEYBOARD, int controller_index = 0) const; // Muestra por consola los controles asignados SDL_GamepadButton getControllerBinding(int controller_index, InputAction input) const; // Obtiene el SDL_GamepadButton asignado a un input std::string to_string(InputAction input) const; // Convierte un InputAction a std::string InputAction to_inputs_e(const std::string &name) const; // Convierte un std::string a InputAction int getIndexByName(const std::string &name) const; // Obtiene el índice a partir del nombre del mando private: // --- Singleton --- static Input *instance_; // --- Estructuras internas --- struct KeyBindings { Uint8 scancode; // Scancode asociado bool active; // Indica si está activo KeyBindings(Uint8 sc = 0, bool act = false) : scancode(sc), active(act) {} }; struct ControllerBindings { SDL_GamepadButton button; // GameControllerButton asociado bool active; // Indica si está activo bool axis_active; // Estado del eje ControllerBindings(SDL_GamepadButton btn = SDL_GAMEPAD_BUTTON_INVALID, bool act = false, bool axis_act = false) : button(btn), active(act), axis_active(axis_act) {} }; // --- Variables internas --- 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 asociados 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 // --- Métodos internos --- void initSDL(); // Inicializa SDL para la gestión de mandos bool checkAxisInput(InputAction input, int controller_index, bool repeat); // Comprueba el eje del mando // --- Constructor y destructor --- explicit Input(const std::string &game_controller_db_path); // Constructor privado ~Input() = default; // Destructor privado };