#pragma once #include #include #include #include #include #include "input.h" // Para Input // Mapas para convertir entre enums y strings std::unordered_map actionToString = { {Input::Action::FIRE_LEFT, "FIRE_LEFT"}, {Input::Action::FIRE_CENTER, "FIRE_CENTER"}, {Input::Action::FIRE_RIGHT, "FIRE_RIGHT"}, {Input::Action::START, "START"}, {Input::Action::SERVICE, "SERVICE"}}; std::unordered_map stringToAction = { {"FIRE_LEFT", Input::Action::FIRE_LEFT}, {"FIRE_CENTER", Input::Action::FIRE_CENTER}, {"FIRE_RIGHT", Input::Action::FIRE_RIGHT}, {"START", Input::Action::START}, {"SERVICE", Input::Action::SERVICE}}; std::unordered_map buttonToString = { {SDL_GAMEPAD_BUTTON_WEST, "WEST"}, {SDL_GAMEPAD_BUTTON_NORTH, "NORTH"}, {SDL_GAMEPAD_BUTTON_EAST, "EAST"}, {SDL_GAMEPAD_BUTTON_SOUTH, "SOUTH"}, {SDL_GAMEPAD_BUTTON_START, "START"}, {SDL_GAMEPAD_BUTTON_BACK, "BACK"}, {SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, "LEFT_SHOULDER"}, {SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, "RIGHT_SHOULDER"} // Añade todos los botones que necesites }; std::unordered_map stringToButton = { {"WEST", SDL_GAMEPAD_BUTTON_WEST}, {"NORTH", SDL_GAMEPAD_BUTTON_NORTH}, {"EAST", SDL_GAMEPAD_BUTTON_EAST}, {"SOUTH", SDL_GAMEPAD_BUTTON_SOUTH}, {"START", SDL_GAMEPAD_BUTTON_START}, {"BACK", SDL_GAMEPAD_BUTTON_BACK}, {"LEFT_SHOULDER", SDL_GAMEPAD_BUTTON_LEFT_SHOULDER}, {"RIGHT_SHOULDER", SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER} // Añade todos los botones que necesites }; struct GamepadConfig { std::string name; // Nombre del dispositivo std::unordered_map bindings; // Asociación acción-botón GamepadConfig(std::string name = "") : name(name), bindings{ {Input::Action::FIRE_LEFT, SDL_GAMEPAD_BUTTON_WEST}, {Input::Action::FIRE_CENTER, SDL_GAMEPAD_BUTTON_NORTH}, {Input::Action::FIRE_RIGHT, SDL_GAMEPAD_BUTTON_EAST}, {Input::Action::START, SDL_GAMEPAD_BUTTON_START}, {Input::Action::SERVICE, SDL_GAMEPAD_BUTTON_BACK}} {} // Reasigna un botón a una acción void rebindAction(Input::Action action, SDL_GamepadButton new_button) { bindings[action] = new_button; } }; class GamepadConfigManager { public: // Escribir vector de GamepadConfig a archivo JSON static bool writeToJson(const std::vector& configs, const std::string& filename) { try { nlohmann::json j; j["gamepads"] = nlohmann::json::array(); for (const auto& config : configs) { nlohmann::json gamepadJson; gamepadJson["name"] = config.name; gamepadJson["bindings"] = nlohmann::json::object(); // Convertir bindings a JSON for (const auto& [action, button] : config.bindings) { std::string actionStr = actionToString[action]; std::string buttonStr = buttonToString[button]; gamepadJson["bindings"][actionStr] = buttonStr; } j["gamepads"].push_back(gamepadJson); } // Escribir al archivo std::ofstream file(filename); if (!file.is_open()) { return false; } file << j.dump(4); // Formato con indentación de 4 espacios file.close(); return true; } catch (const std::exception& e) { // Log del error si tienes sistema de logging return false; } } // Leer vector de GamepadConfig desde archivo JSON static bool readFromJson(std::vector& configs, const std::string& filename) { try { std::ifstream file(filename); if (!file.is_open()) { return false; } nlohmann::json j; file >> j; file.close(); configs.clear(); if (!j.contains("gamepads") || !j["gamepads"].is_array()) { return false; } for (const auto& gamepadJson : j["gamepads"]) { if (!gamepadJson.contains("name") || !gamepadJson.contains("bindings")) { continue; // Saltar configuraciones malformadas } GamepadConfig config(gamepadJson["name"]); // Limpiar bindings por defecto para cargar los del archivo config.bindings.clear(); // Cargar bindings desde JSON for (const auto& [actionStr, buttonStr] : gamepadJson["bindings"].items()) { auto actionIt = stringToAction.find(actionStr); auto buttonIt = stringToButton.find(buttonStr); if (actionIt != stringToAction.end() && buttonIt != stringToButton.end()) { config.bindings[actionIt->second] = buttonIt->second; } } configs.push_back(config); } return true; } catch (const std::exception& e) { // Log del error si tienes sistema de logging return false; } } // Método auxiliar para verificar si un archivo existe static bool fileExists(const std::string& filename) { std::ifstream file(filename); return file.good(); } }; /* // Ejemplo de uso void ejemploUso() { std::vector configs; // Crear algunas configuraciones de ejemplo GamepadConfig config1("Xbox Controller"); config1.rebindAction(Input::Action::FIRE_LEFT, SDL_GAMEPAD_BUTTON_SOUTH); GamepadConfig config2("PS4 Controller"); config2.rebindAction(Input::Action::START, SDL_GAMEPAD_BUTTON_OPTIONS); configs.push_back(config1); configs.push_back(config2); // Escribir a archivo if (GamepadConfigManager::writeToJson(configs, "gamepad_config.json")) { std::cout << "Configuración guardada exitosamente" << std::endl; } // Leer desde archivo std::vector loadedConfigs; if (GamepadConfigManager::readFromJson(loadedConfigs, "gamepad_config.json")) { std::cout << "Configuración cargada exitosamente" << std::endl; std::cout << "Número de configuraciones: " << loadedConfigs.size() << std::endl; } } */