eliminada tota la funcionalitat de gamepad_config_manager i la dependencia de json

This commit is contained in:
2025-11-18 09:44:42 +01:00
parent 435358ef1e
commit 4477cc4bbc
6 changed files with 10 additions and 25899 deletions

View File

@@ -1,134 +0,0 @@
#pragma once
#include <fstream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "core/input/input_types.hpp" // Solo incluimos los tipos compartidos
#include "external/json.hpp"
// --- Estructuras ---
struct GamepadConfig {
std::string name; // Nombre del dispositivo
std::string path; // Ruta física del dispositivo
std::unordered_map<InputAction, SDL_GamepadButton> bindings; // Asociación acción-botón
GamepadConfig(std::string name, std::string path)
: name(std::move(name)),
path(std::move(path)),
bindings{
{InputAction::LEFT, SDL_GAMEPAD_BUTTON_DPAD_LEFT},
{InputAction::RIGHT, SDL_GAMEPAD_BUTTON_DPAD_RIGHT},
{InputAction::JUMP, SDL_GAMEPAD_BUTTON_WEST}} {}
// Reasigna un botón a una acción
void rebindAction(InputAction action, SDL_GamepadButton new_button) {
bindings[action] = new_button;
}
};
// --- Tipos ---
using GamepadConfigs = std::vector<GamepadConfig>; // Vector de configuraciones de gamepad
// --- Clase GamepadConfigManager: gestor de configuraciones de gamepad ---
class GamepadConfigManager {
public:
// --- Métodos estáticos ---
static auto writeToJson(const GamepadConfigs& configs, const std::string& filename) -> bool { // Escribir configuraciones a JSON
try {
nlohmann::json j;
j["gamepads"] = nlohmann::json::array();
for (const auto& config : configs) {
nlohmann::json gamepad_json;
gamepad_json["name"] = config.name;
gamepad_json["path"] = config.path;
gamepad_json["bindings"] = nlohmann::json::object();
// Convertir bindings a JSON
for (const auto& [action, button] : config.bindings) {
auto action_it = ACTION_TO_STRING.find(action);
auto button_it = BUTTON_TO_STRING.find(button);
if (action_it != ACTION_TO_STRING.end() && button_it != BUTTON_TO_STRING.end()) {
gamepad_json["bindings"][action_it->second] = button_it->second;
}
}
j["gamepads"].push_back(gamepad_json);
}
// 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 auto readFromJson(GamepadConfigs& configs, const std::string& filename) -> bool {
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& gamepad_json : j["gamepads"]) {
if (!gamepad_json.contains("name") || !gamepad_json.contains("bindings")) {
continue; // Saltar configuraciones malformadas
}
// Leer el campo path si existe, si no dejarlo vacío
std::string path = gamepad_json.contains("path") ? gamepad_json["path"].get<std::string>() : "";
GamepadConfig config(gamepad_json["name"], path);
// Limpiar bindings por defecto para cargar los del archivo
config.bindings.clear();
// Cargar bindings desde JSON
for (const auto& [actionStr, buttonStr] : gamepad_json["bindings"].items()) {
auto action_it = STRING_TO_ACTION.find(actionStr);
auto button_it = STRING_TO_BUTTON.find(buttonStr);
if (action_it != STRING_TO_ACTION.end() && button_it != STRING_TO_BUTTON.end()) {
config.bindings[action_it->second] = button_it->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 auto fileExists(const std::string& filename) -> bool {
std::ifstream file(filename);
return file.good();
}
};

View File

@@ -14,8 +14,8 @@
Input* Input::instance = nullptr; Input* Input::instance = nullptr;
// Inicializa la instancia única del singleton // Inicializa la instancia única del singleton
void Input::init(const std::string& game_controller_db_path, const std::string& gamepad_configs_file) { void Input::init(const std::string& game_controller_db_path) {
Input::instance = new Input(game_controller_db_path, gamepad_configs_file); Input::instance = new Input(game_controller_db_path);
} }
// Libera la instancia // Libera la instancia
@@ -25,9 +25,8 @@ void Input::destroy() { delete Input::instance; }
auto Input::get() -> Input* { return Input::instance; } auto Input::get() -> Input* { return Input::instance; }
// Constructor // Constructor
Input::Input(std::string game_controller_db_path, std::string gamepad_configs_file) Input::Input(std::string game_controller_db_path)
: gamepad_mappings_file_(std::move(game_controller_db_path)), : gamepad_mappings_file_(std::move(game_controller_db_path)) {
gamepad_configs_file_(std::move(gamepad_configs_file)) {
// Inicializar bindings del teclado // Inicializar bindings del teclado
keyboard_.bindings = { keyboard_.bindings = {
// Movimiento del jugador // Movimiento del jugador
@@ -354,7 +353,6 @@ void Input::initSDLGamePad() {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GAMEPAD could not initialize! SDL Error: %s", SDL_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GAMEPAD could not initialize! SDL Error: %s", SDL_GetError());
} else { } else {
addGamepadMappingsFromFile(); addGamepadMappingsFromFile();
loadGamepadConfigs();
discoverGamepads(); discoverGamepads();
std::cout << "Input System initialized successfully\n"; std::cout << "Input System initialized successfully\n";
} }
@@ -421,8 +419,6 @@ auto Input::addGamepad(int device_index) -> std::string {
auto gamepad = std::make_shared<Gamepad>(pad); auto gamepad = std::make_shared<Gamepad>(pad);
auto name = gamepad->name; auto name = gamepad->name;
std::cout << "Gamepad connected (" << name << ")" << '\n'; std::cout << "Gamepad connected (" << name << ")" << '\n';
applyGamepadConfig(gamepad);
saveGamepadConfigFromGamepad(gamepad);
gamepads_.push_back(std::move(gamepad)); gamepads_.push_back(std::move(gamepad));
return name + " CONNECTED"; return name + " CONNECTED";
} }
@@ -456,99 +452,6 @@ void Input::printConnectedGamepads() const {
} }
} }
void Input::loadGamepadConfigs() {
if (GamepadConfigManager::fileExists(gamepad_configs_file_)) {
GamepadConfigManager::readFromJson(gamepad_configs_, gamepad_configs_file_);
}
}
void Input::saveGamepadConfigs() {
GamepadConfigManager::writeToJson(gamepad_configs_, gamepad_configs_file_);
}
void Input::applyGamepadConfig(std::shared_ptr<Gamepad> gamepad) {
if (!gamepad || gamepad->path.empty()) { // No podemos aplicar config sin una ruta
return;
}
// --- Buscar configuración por RUTA (path) ---
auto config_it = std::ranges::find_if(gamepad_configs_, [&gamepad](const GamepadConfig& config) {
return config.path == gamepad->path;
});
if (config_it != gamepad_configs_.end()) {
// Se encontró una configuración específica para este puerto/dispositivo. La aplicamos.
std::cout << "Applying custom config for gamepad at path: " << gamepad->path << '\n';
for (const auto& [action, button] : config_it->bindings) {
if (gamepad->bindings.find(action) != gamepad->bindings.end()) {
gamepad->bindings[action].button = button;
}
}
}
// Opcional: Podrías añadir un fallback para buscar por nombre si no se encuentra por ruta.
}
void Input::saveGamepadConfigFromGamepad(std::shared_ptr<Gamepad> gamepad) {
if (!gamepad || gamepad->path.empty()) { // No podemos guardar una config sin una ruta
return;
}
// --- CAMBIO CLAVE: Buscar si ya existe una configuración por RUTA (path) ---
auto config_it = std::ranges::find_if(gamepad_configs_, [&gamepad](const GamepadConfig& config) {
return config.path == gamepad->path;
});
// Crear nueva configuración desde el gamepad, incluyendo nombre y ruta
GamepadConfig new_config(gamepad->name, gamepad->path); // <--- CAMBIO: Pasamos ambos
new_config.bindings.clear();
// Copiar todos los bindings actuales del gamepad
for (const auto& [action, buttonState] : gamepad->bindings) {
new_config.bindings[action] = static_cast<SDL_GamepadButton>(buttonState.button);
}
if (config_it != gamepad_configs_.end()) {
// Sobreescribir configuración existente para esta ruta
*config_it = new_config;
} else {
// Añadir nueva configuración
gamepad_configs_.push_back(new_config);
}
// Guardar cambios inmediatamente
saveGamepadConfigs();
}
// Método para establecer el archivo de configuración (opcional)
void Input::setGamepadConfigsFile(const std::string& filename) {
gamepad_configs_file_ = filename;
loadGamepadConfigs(); // Recargar con el nuevo archivo
}
// Método para obtener configuración de un gamepad específico (opcional)
auto Input::getGamepadConfig(const std::string& gamepad_name) -> GamepadConfig* {
auto config_it = std::ranges::find_if(gamepad_configs_, [&gamepad_name](const GamepadConfig& config) {
return config.name == gamepad_name;
});
return (config_it != gamepad_configs_.end()) ? &(*config_it) : nullptr;
}
// Método para eliminar configuración de gamepad (opcional)
auto Input::removeGamepadConfig(const std::string& gamepad_name) -> bool {
auto config_it = std::ranges::find_if(gamepad_configs_, [&gamepad_name](const GamepadConfig& config) {
return config.name == gamepad_name;
});
if (config_it != gamepad_configs_.end()) {
gamepad_configs_.erase(config_it);
saveGamepadConfigs();
return true;
}
return false;
}
auto Input::findAvailableGamepadByName(const std::string& gamepad_name) -> std::shared_ptr<Input::Gamepad> { auto Input::findAvailableGamepadByName(const std::string& gamepad_name) -> std::shared_ptr<Input::Gamepad> {
// Si no hay gamepads disponibles, devolver gamepad por defecto // Si no hay gamepads disponibles, devolver gamepad por defecto
if (gamepads_.empty()) { if (gamepads_.empty()) {

View File

@@ -9,7 +9,6 @@
#include <utility> // Para pair #include <utility> // Para pair
#include <vector> // Para vector #include <vector> // Para vector
#include "core/input/gamepad_config_manager.hpp" // for GamepadConfig (ptr only), GamepadConfigs
#include "core/input/input_types.hpp" // for InputAction #include "core/input/input_types.hpp" // for InputAction
// --- Clase Input: gestiona la entrada de teclado y mandos (singleton) --- // --- Clase Input: gestiona la entrada de teclado y mandos (singleton) ---
@@ -79,7 +78,7 @@ class Input {
using Gamepads = std::vector<std::shared_ptr<Gamepad>>; // Vector de gamepads using Gamepads = std::vector<std::shared_ptr<Gamepad>>; // Vector de gamepads
// --- Singleton --- // --- Singleton ---
static void init(const std::string& game_controller_db_path, const std::string& gamepad_configs_file); static void init(const std::string& game_controller_db_path);
static void destroy(); static void destroy();
static auto get() -> Input*; static auto get() -> Input*;
@@ -109,7 +108,6 @@ class Input {
static auto getControllerName(const std::shared_ptr<Gamepad>& gamepad) -> std::string; static auto getControllerName(const std::shared_ptr<Gamepad>& gamepad) -> std::string;
auto getControllerNames() const -> std::vector<std::string>; auto getControllerNames() const -> std::vector<std::string>;
[[nodiscard]] static auto getControllerBinding(const std::shared_ptr<Gamepad>& gamepad, Action action) -> SDL_GamepadButton; [[nodiscard]] static auto getControllerBinding(const std::shared_ptr<Gamepad>& gamepad, Action action) -> SDL_GamepadButton;
void saveGamepadConfigFromGamepad(std::shared_ptr<Gamepad> gamepad);
void printConnectedGamepads() const; void printConnectedGamepads() const;
// --- Eventos --- // --- Eventos ---
@@ -122,7 +120,7 @@ class Input {
static constexpr std::array<Action, 1> BUTTON_INPUTS = {Action::JUMP}; // Inputs que usan botones static constexpr std::array<Action, 1> BUTTON_INPUTS = {Action::JUMP}; // Inputs que usan botones
// --- Métodos --- // --- Métodos ---
explicit Input(std::string game_controller_db_path, std::string gamepad_configs_file); explicit Input(std::string game_controller_db_path);
~Input() = default; ~Input() = default;
void initSDLGamePad(); void initSDLGamePad();
@@ -133,19 +131,10 @@ class Input {
void addGamepadMappingsFromFile(); void addGamepadMappingsFromFile();
void discoverGamepads(); void discoverGamepads();
void loadGamepadConfigs();
void saveGamepadConfigs();
void applyGamepadConfig(std::shared_ptr<Gamepad> gamepad);
void setGamepadConfigsFile(const std::string& filename);
auto getGamepadConfig(const std::string& gamepad_name) -> GamepadConfig*;
auto removeGamepadConfig(const std::string& gamepad_name) -> bool;
// --- Variables miembro --- // --- Variables miembro ---
static Input* instance; // Instancia única del singleton static Input* instance; // Instancia única del singleton
Gamepads gamepads_{}; // Lista de gamepads conectados Gamepads gamepads_{}; // Lista de gamepads conectados
Keyboard keyboard_{}; // Estado del teclado Keyboard keyboard_{}; // Estado del teclado
std::string gamepad_mappings_file_{}; // Ruta al archivo de mappings std::string gamepad_mappings_file_{}; // Ruta al archivo de mappings
std::string gamepad_configs_file_{}; // Ruta al archivo de configuraciones
GamepadConfigs gamepad_configs_{}; // Configuraciones de gamepads guardadas
}; };

View File

@@ -137,14 +137,15 @@ Director::Director(std::vector<std::string> const& args) {
#ifdef RELEASE_BUILD #ifdef RELEASE_BUILD
// In release, construct the path manually (not from Asset which has empty executable_path) // In release, construct the path manually (not from Asset which has empty executable_path)
std::string gamecontroller_db = executable_path_ + PREFIX + "/gamecontrollerdb.txt"; std::string gamecontroller_db = executable_path_ + PREFIX + "/gamecontrollerdb.txt";
Input::init(gamecontroller_db, Resource::List::get()->get("controllers.json")); Input::init(gamecontroller_db);
#else #else
// In development, use Asset as normal // In development, use Asset as normal
Input::init(Resource::List::get()->get("gamecontrollerdb.txt"), Resource::List::get()->get("controllers.json")); // Carga configuración de controles Input::init(Resource::List::get()->get("gamecontrollerdb.txt")); // Carga configuración de controles
#endif #endif
// Aplica las teclas configuradas desde Options // Aplica las teclas y botones del gamepad configurados desde Options
Input::get()->applyKeyboardBindingsFromOptions(); Input::get()->applyKeyboardBindingsFromOptions();
Input::get()->applyGamepadBindingsFromOptions();
#ifdef _DEBUG #ifdef _DEBUG
Debug::init(); Debug::init();

View File

@@ -1,122 +0,0 @@
# External Dependencies
This directory contains third-party libraries used by JailDoctor's Dilemma.
## Current Dependencies
| Library | Version | Type | Purpose |
|---------|---------|------|---------|
| **jail_audio** | Custom | Source (.cpp/.h) | Audio playback engine (OGG/WAV) |
| **stb_image** | v2.x | Header-only | Image loading (PNG, GIF) |
| **stb_vorbis** | v1.x | Header-only | OGG Vorbis audio decoding |
| **json** | nlohmann/json | Header-only | JSON parsing (if needed) |
| **fkYAML** | v3.x | Header-only | YAML parsing for room files |
## Structure
```
external/
├── jail_audio.cpp # Custom audio library implementation
├── jail_audio.h # C interface for jail_audio
├── stb_image.h # STB image loader (header-only)
├── stb_vorbis.h # STB Vorbis decoder (header-only)
├── json.hpp # nlohmann JSON library (header-only)
└── fkyaml_node.hpp # fkYAML parser library (header-only)
```
## Why Dependencies Are Here
All dependencies are kept in `source/external/` for several reasons:
1. **Build System Independence** - Can compile with CMake, Make, or other build systems
2. **Offline Builds** - No internet required during compilation
3. **Version Control** - Exact versions committed to repository
4. **Portability** - Works on any platform without external package managers
5. **Consistency** - All team members use identical library versions
## Using With Different Build Systems
### CMake (Recommended)
```cmake
# Include path for header-only libraries (fkYAML, json, stb)
target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_SOURCE_DIR}/source")
# All external dependencies are header-only except jail_audio
# jail_audio.cpp is compiled as part of the main build
```
### Makefile
See `Makefile.example` in the project root for a complete example.
```makefile
CXXFLAGS = -I./source
# Compile jail_audio.cpp and link with your sources
```
### Manual Compilation
```bash
# Compile jail_audio (only non-header-only library)
g++ -c source/external/jail_audio.cpp -I./source
# Compile your project sources
g++ -c source/game/*.cpp -I./source
# Link everything together
g++ *.o -o game -lSDL3
```
## Adding New Dependencies
### Header-Only Libraries
1. Download the header file(s)
2. Place in `source/external/`
3. Include in code: `#include "external/library.h"`
### Source Libraries
1. Place source files (.cpp) directly in `source/external/`
2. Place header files (.h/.hpp) in `source/external/`
3. Add to CMakeLists.txt if needed:
```cmake
# Most dependencies are header-only
# For source libraries, add to SOURCES list
```
## Updating Dependencies
### fkYAML
To update fkYAML to a newer version:
```bash
cd source/external
# Download the single-header version from the releases page
curl -L -O https://github.com/fktn-k/fkYAML/releases/download/v3.x.x/fkyaml_node.hpp
```
Or download from: https://github.com/fktn-k/fkYAML/releases
### STB Libraries
Download latest from: https://github.com/nothings/stb
```bash
cd source/external
curl -O https://raw.githubusercontent.com/nothings/stb/master/stb_image.h
curl -O https://raw.githubusercontent.com/nothings/stb/master/stb_vorbis.h
```
## License Information
Each library has its own license:
- **jail_audio** - Custom (see source files)
- **stb libraries** - Public Domain / MIT
- **nlohmann/json** - MIT License
- **fkYAML** - MIT License
See individual library files for full license texts.
## Notes
- All dependencies are compatible with C++20
- Most libraries are header-only and require no compilation
- Only jail_audio (source library) is compiled as part of the main build
- Keep dependencies minimal to reduce build times and binary size

25526
source/external/json.hpp vendored

File diff suppressed because it is too large Load Diff