#include "core/system/debug.hpp" #ifdef _DEBUG #include // Para max #include // Para ifstream, ofstream #include // Para __shared_ptr_access, shared_ptr #include "core/rendering/text.hpp" // Para Text #include "core/resources/resource_cache.hpp" // Para Resource #include "external/fkyaml_node.hpp" // Para fkyaml::node #include "game/defaults.hpp" // Para Defaults::Game::* #include "utils/defines.hpp" // Para Tile::SIZE #include "utils/utils.hpp" // Para Color, Flip:: // [SINGLETON] Debug* Debug::debug = nullptr; // [SINGLETON] Crearemos el objeto con esta función estática void Debug::init() { Debug::debug = new Debug(); } // [SINGLETON] Destruiremos el objeto con esta función estática void Debug::destroy() { delete Debug::debug; } // [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él auto Debug::get() -> Debug* { return Debug::debug; } // Dibuja en pantalla void Debug::render() { // NOLINT(readability-make-member-function-const) auto text = Resource::Cache::get()->getText("aseprite"); int y = y_; int w = 0; constexpr int DESP_Y = 7; const int CHAR_SIZE = text->getCharacterSize(); // Watch window: valores persistentes (key: value) for (const auto& [key, value] : watches_) { const std::string LINE = key + ": " + value; text->write(x_, y, LINE); w = std::max(w, text->length(LINE)); y += DESP_Y; if (y > 192 - CHAR_SIZE) { y = y_; x_ += w + 2; w = 0; } } // Slot one-shot: mensajes de un solo frame for (const auto& s : slot_) { text->write(x_, y, s); w = std::max(w, text->length(s)); y += DESP_Y; if (y > 192 - CHAR_SIZE) { y = y_; x_ += w + 2; w = 0; } } y = 0; for (const auto& l : log_) { text->writeColored(x_ + 10, y, l, static_cast(PaletteColor::WHITE)); y += CHAR_SIZE + 1; } } // Establece/actualiza un valor persistente en el watch window void Debug::set(const std::string& key, const std::string& value) { watches_[key] = value; } // Elimina un valor del watch window void Debug::unset(const std::string& key) { watches_.erase(key); } // Establece la posición donde se colocará la información de debug void Debug::setPos(SDL_FPoint p) { x_ = p.x; y_ = p.y; } // Establece la ruta del archivo debug.yaml void Debug::setDebugFile(const std::string& path) { debug_file_path_ = path; } // Convierte string a SceneManager::Scene (para debug.yaml) static auto sceneFromString(const std::string& s) -> SceneManager::Scene { if (s == "LOGO") { return SceneManager::Scene::LOGO; } if (s == "LOADING") { return SceneManager::Scene::LOADING_SCREEN; } if (s == "TITLE") { return SceneManager::Scene::TITLE; } if (s == "CREDITS") { return SceneManager::Scene::CREDITS; } if (s == "DEMO") { return SceneManager::Scene::DEMO; } if (s == "ENDING") { return SceneManager::Scene::ENDING; } if (s == "ENDING2") { return SceneManager::Scene::ENDING2; } return SceneManager::Scene::GAME; // Fallback seguro } // Convierte SceneManager::Scene a string (para debug.yaml) static auto sceneToString(SceneManager::Scene scene) -> std::string { switch (scene) { case SceneManager::Scene::LOGO: return "LOGO"; case SceneManager::Scene::LOADING_SCREEN: return "LOADING"; case SceneManager::Scene::TITLE: return "TITLE"; case SceneManager::Scene::CREDITS: return "CREDITS"; case SceneManager::Scene::DEMO: return "DEMO"; case SceneManager::Scene::ENDING: return "ENDING"; case SceneManager::Scene::ENDING2: return "ENDING2"; default: return "GAME"; } } // Carga la configuración de debug desde debug.yaml void Debug::loadFromFile() { // Inicializar con valores de release por defecto spawn_settings_.room = Defaults::Game::Room::INITIAL; spawn_settings_.spawn_x = Defaults::Game::Player::SPAWN_X; spawn_settings_.spawn_y = Defaults::Game::Player::SPAWN_Y; spawn_settings_.flip = Defaults::Game::Player::SPAWN_FLIP; initial_scene_ = SceneManager::Scene::GAME; std::ifstream file(debug_file_path_); if (!file.good()) { saveToFile(); // No existe: crear con valores por defecto return; } std::string content((std::istreambuf_iterator(file)), std::istreambuf_iterator()); file.close(); try { auto yaml = fkyaml::node::deserialize(content); if (yaml.contains("room")) { spawn_settings_.room = yaml["room"].get_value(); } if (yaml.contains("spawn_x")) { spawn_settings_.spawn_x = yaml["spawn_x"].get_value() * Tile::SIZE; } if (yaml.contains("spawn_y")) { spawn_settings_.spawn_y = yaml["spawn_y"].get_value() * Tile::SIZE; } if (yaml.contains("spawn_flip")) { auto s = yaml["spawn_flip"].get_value(); spawn_settings_.flip = (s == "right") ? Flip::RIGHT : Flip::LEFT; } if (yaml.contains("initial_scene")) { initial_scene_ = sceneFromString(yaml["initial_scene"].get_value()); } } catch (...) { // YAML inválido: resetear a defaults y sobreescribir spawn_settings_.room = Defaults::Game::Room::INITIAL; spawn_settings_.spawn_x = Defaults::Game::Player::SPAWN_X; spawn_settings_.spawn_y = Defaults::Game::Player::SPAWN_Y; spawn_settings_.flip = Defaults::Game::Player::SPAWN_FLIP; initial_scene_ = SceneManager::Scene::GAME; saveToFile(); } } // Guarda la configuración de debug en debug.yaml void Debug::saveToFile() const { std::ofstream file(debug_file_path_); if (!file.is_open()) { return; } file << "# JailDoctor's Dilemma - Debug Configuration\n"; file << "# Edita para cambiar la habitacion y spawn del jugador en builds debug.\n\n"; file << "room: \"" << spawn_settings_.room << "\"\n"; file << "spawn_x: " << (spawn_settings_.spawn_x / Tile::SIZE) << " # en tiles\n"; file << "spawn_y: " << (spawn_settings_.spawn_y / Tile::SIZE) << " # en tiles\n"; file << "spawn_flip: " << ((spawn_settings_.flip == Flip::RIGHT) ? "right" : "left") << "\n"; file << "initial_scene: " << sceneToString(initial_scene_) << "\n"; } #endif // _DEBUG