#include "core/rendering/render_info.hpp" #include #include // Para transform #include // Para round, floor #include // Para setprecision #include // Para ostringstream #include // Para string #include "core/rendering/screen.hpp" // Para Screen #include "core/rendering/surface.hpp" // Para Surface #include "core/rendering/text.hpp" // Para Text #include "game/options.hpp" // Para Options #include "game/ui/console.hpp" // Para Console #include "game/ui/notifier.hpp" // Para Notifier #include "utils/utils.hpp" // Para prettyName // [SINGLETON] RenderInfo* RenderInfo::render_info = nullptr; // [SINGLETON] Crearemos el objeto con esta función estática void RenderInfo::init() { RenderInfo::render_info = new RenderInfo(); } // [SINGLETON] Destruiremos el objeto con esta función estática void RenderInfo::destroy() { delete RenderInfo::render_info; RenderInfo::render_info = nullptr; } // [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él auto RenderInfo::get() -> RenderInfo* { return RenderInfo::render_info; } // Constructor: arranca oculto; quien quiera activarlo debe llamar a toggle() RenderInfo::RenderInfo() = default; // Actualiza la animación de entrada/salida del overlay void RenderInfo::update(float delta_time) { switch (status_) { case Status::RISING: y_ += SLIDE_SPEED * delta_time; if (y_ >= 0.0F) { y_ = 0.0F; status_ = Status::ACTIVE; } break; case Status::VANISHING: y_ -= SLIDE_SPEED * delta_time; if (y_ <= static_cast(-HEIGHT)) { y_ = static_cast(-HEIGHT); status_ = Status::HIDDEN; } break; default: break; } } // Renderiza el overlay de información por pantalla void RenderInfo::render() const { if (status_ == Status::HIDDEN) { return; } // FPS std::string line = std::to_string(Screen::get()->getLastFPS()) + " fps"; // Driver GPU const auto& driver = Screen::get()->getGPUDriver(); line += " | " + (driver.empty() ? std::string("sdl") : driver); // Zoom calculado (alto físico / alto lógico), con coma decimal y sin ceros innecesarios const float ROUNDED = std::round(Screen::get()->getZoomFactor() * 100.0F) / 100.0F; std::string zoom_str; if (ROUNDED == std::floor(ROUNDED)) { zoom_str = std::to_string(static_cast(ROUNDED)); } else { std::ostringstream oss; oss << std::fixed << std::setprecision(2) << ROUNDED; zoom_str = oss.str(); if (zoom_str.back() == '0') { zoom_str.pop_back(); } std::ranges::replace(zoom_str, '.', ','); } line += " | " + zoom_str + "x"; // PostFX: muestra shader + preset y supersampling, o nada si está desactivado if (Options::video.shader.enabled) { const bool IS_CRTPI = (Options::video.shader.current_shader == Rendering::ShaderType::CRTPI); const std::string SHADER_NAME = IS_CRTPI ? "crtpi" : "postfx"; std::string preset_name = "-"; if (IS_CRTPI) { if (!Options::crtpi_presets.empty()) { preset_name = prettyName(Options::crtpi_presets[static_cast(Options::video.shader.current_crtpi_preset)].name); } } else { if (!Options::postfx_presets.empty()) { preset_name = prettyName(Options::postfx_presets[static_cast(Options::video.shader.current_postfx_preset)].name); } } const bool SHOW_SS = Options::video.supersampling.enabled && !IS_CRTPI; line += " | " + SHADER_NAME + " " + preset_name + (SHOW_SS ? " (ss)" : ""); } // Todo en lowercase std::ranges::transform(line, line.begin(), [](unsigned char c) { return std::tolower(c); }); // Constantes visuales static constexpr Uint8 MSG_COLOR = 9; // PaletteColor::BRIGHT_GREEN static constexpr int TEXT_SIZE = Console::TEXT_SIZE; static constexpr int PADDING_V = (TEXT_SIZE / 2) - 1; // Fuente: preferir la de la consola si está disponible auto text_obj = (Console::get() != nullptr) ? Console::get()->getText() : Screen::get()->getText(); // Posición Y: debajo de la consola + notificaciones + offset animado propio const int CONSOLE_Y = (Console::get() != nullptr) ? Console::get()->getVisibleHeight() : 0; const int NOTIFIER_Y = (Notifier::get() != nullptr) ? Notifier::get()->getVisibleHeight() : 0; const int Y = CONSOLE_Y + NOTIFIER_Y + static_cast(y_); text_obj->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, static_cast(Options::game.width / 2), Y + PADDING_V, line, 1, MSG_COLOR); } // Activa o desactiva el overlay void RenderInfo::toggle() { switch (status_) { case Status::HIDDEN: status_ = Status::RISING; Screen::get()->updateZoomFactor(); break; case Status::ACTIVE: status_ = Status::VANISHING; break; default: break; } }