#pragma once #include #include // for uint8_t #include // for string, basic_string #include // for vector enum InputDisable : std::uint8_t { NOT_DISABLED, FOREVER, KEY_PRESSED }; class Input { public: enum class Repeat : std::uint8_t { OFF, ON }; enum class Device : std::uint8_t { KEYBOARD, GAMECONTROLLER, ANY }; enum class Action : std::uint8_t { // Inputs obligatorios INVALID, UP, DOWN, LEFT, RIGHT, PAUSE, EXIT, ACCEPT, CANCEL, // Inputs personalizados FIRE_LEFT, FIRE_CENTER, FIRE_RIGHT, WINDOW_FULLSCREEN, WINDOW_INC_ZOOM, WINDOW_DEC_ZOOM, // GPU / shaders (hotkeys provisionales hasta que haya menú de opciones) NEXT_SHADER_PRESET, TOGGLE_SHADER, TOGGLE_SHADER_TYPE, // Centinela final (usar para sizing) NUMBER_OF_INPUTS }; // Singleton API static void init(const std::string &game_controller_db_path); // Crea la instancia static void destroy(); // Libera la instancia static auto get() -> Input *; // Obtiene el puntero a la instancia ~Input(); // Destructor void update(); // Actualiza el estado del objeto void bindKey(Action input, SDL_Scancode code); // Asigna inputs a teclas void bindGameControllerButton(Action input, SDL_GamepadButton button); // Asigna inputs a botones del mando auto checkInput(Action input, Repeat repeat = Repeat::ON, Device device = Device::ANY, int index = 0) -> bool; // Comprueba si un input esta activo auto checkAnyInput(Device device = Device::ANY, int index = 0) -> bool; // Comprueba si hay almenos un input activo auto discoverGameController() -> bool; // Busca si hay un mando conectado // Procesa un evento SDL_EVENT_GAMEPAD_ADDED. Devuelve true si el mando se ha añadido // (no estaba ya registrado) y escribe el nombre visible en outName. auto handleGamepadAdded(SDL_JoystickID jid, std::string &out_name) -> bool; // Procesa un evento SDL_EVENT_GAMEPAD_REMOVED. Devuelve true si se ha encontrado y // eliminado, y escribe el nombre visible en outName. auto handleGamepadRemoved(SDL_JoystickID jid, std::string &out_name) -> bool; [[nodiscard]] auto gameControllerFound() const -> bool; // Comprueba si hay algun mando conectado [[nodiscard]] auto getNumControllers() const -> int; // Obten el numero de mandos conectados auto getControllerName(int index) -> std::string; // Obten el nombre de un mando de juego void setVerbose(bool value); // Establece si ha de mostrar mensajes void disableUntil(InputDisable value); // Deshabilita las entradas durante un periodo de tiempo void enable(); // Hablita las entradas private: struct KeyBindings { Uint8 scancode; // Scancode asociado bool active; // Indica si está activo }; struct GameControllerBindings { SDL_GamepadButton button; // GameControllerButton asociado bool active; // Indica si está activo }; // Objetos y punteros std::vector connected_controllers_; // Vector con todos los mandos conectados std::vector connected_controller_ids_; // Instance IDs paralelos para mapear eventos // 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 InputDisable disabled_until_{NOT_DISABLED}; // Tiempo que esta deshabilitado bool enabled_{true}; // Indica si está habilitado static Input *instance; // Instancia única explicit Input(std::string file); // Constructor privado (usar Input::init) // Construye el nombre visible de un mando (name truncado + sufijo #N) static auto buildControllerName(SDL_Gamepad *pad, int pad_index) -> std::string; // Helpers de checkInput auto checkKeyboardInput(Action input, Repeat repeat) -> bool; auto checkGameControllerInput(Action input, Repeat repeat, int index) -> bool; // Helpers de discoverGameController void resetGameControllerState(); void ensureGamepadSubsystem(); auto openGamepad(SDL_JoystickID joystick_id, int pad_index) -> bool; };