diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index 01f3848..1ed135b 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -4,10 +4,12 @@ #include // Para max, min, transform #include // Para toupper +#include // Para round, floor #include // Para memcpy #include // Para basic_ostream, operator<<, endl, basic_... #include // Para cerr #include // Para istreambuf_iterator, operator== +#include // Para ostringstream #include // Para char_traits, string, operator+, operator== #include "core/input/mouse.hpp" // Para updateCursorVisibility @@ -49,6 +51,7 @@ Screen::Screen() // Calcular tamaños y hacer .resize() de los buffers de píxeles adjustWindowSize(); adjustRenderLogicalSize(); + updateZoomFactor(); // Ajusta los tamaños game_surface_dstrect_ = {.x = Options::video.border.width, .y = Options::video.border.height, .w = Options::game.width, .h = Options::game.height}; @@ -151,8 +154,10 @@ void Screen::setVideoMode(bool mode) { // Configura el modo de pantalla y ajusta la ventana SDL_SetWindowFullscreen(window_, Options::video.fullscreen); + SDL_SyncWindow(window_); adjustWindowSize(); adjustRenderLogicalSize(); + updateZoomFactor(); } // Camibia entre pantalla completa y ventana @@ -292,6 +297,25 @@ void Screen::adjustRenderLogicalSize() { SDL_SetRenderLogicalPresentation(renderer_, window_width_, window_height_, Options::video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX); } +// Recalcula y almacena el factor de zoom. Llamar solo cuando SDL ya ha estabilizado el estado de la ventana. +// En ventana: Options::window.zoom (siempre entero). +// En fullscreen: mínimo de las escalas en ambos ejes; floor si integer scale está activo. +void Screen::updateZoomFactor() { + if (!Options::video.fullscreen) { + zoom_factor_ = static_cast(Options::window.zoom); + return; + } + if (window_width_ == 0 || window_height_ == 0) { + zoom_factor_ = 1.0F; + return; + } + int pw{0}, ph{0}; + SDL_GetRenderOutputSize(renderer_, &pw, &ph); + const float SCALE = std::min(static_cast(pw) / static_cast(window_width_), + static_cast(ph) / static_cast(window_height_)); + zoom_factor_ = Options::video.integer_scale ? std::floor(SCALE) : SCALE; +} + // Establece el renderizador para las surfaces void Screen::setRendererSurface(const std::shared_ptr& surface) { (surface) ? renderer_surface_ = std::make_shared>(surface) : renderer_surface_ = std::make_shared>(game_surface_); @@ -456,28 +480,30 @@ void Screen::renderInfo() const { text_->write(X, y, gpu_driver_.empty() ? "sdl" : gpu_driver_); y += LINE_HEIGHT; - // Zoom de la ventana - const std::string ZOOM_TEXT = "zoom x" + std::to_string(Options::window.zoom); - text_->write(X, y, ZOOM_TEXT); - y += LINE_HEIGHT; - - // PostFX enabled - const std::string POSTFX_TEXT = std::string("postfx ") + (Options::video.postfx ? "on" : "off"); - text_->write(X, y, POSTFX_TEXT); - y += LINE_HEIGHT; - - // PostFX preset - std::string preset_name = "-"; - if (!Options::postfx_presets.empty()) { - preset_name = Options::postfx_presets[static_cast(Options::current_postfx_preset)].name; + // Zoom calculado (alto físico / alto lógico), con coma decimal y sin ceros innecesarios + const float ROUNDED = std::round(zoom_factor_ * 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::replace(zoom_str.begin(), zoom_str.end(), '.', ','); } - const std::string PRESET_TEXT = "preset " + preset_name; - text_->write(X, y, PRESET_TEXT); + text_->write(X, y, zoom_str + "x"); y += LINE_HEIGHT; - // Supersampling enabled - const std::string SS_TEXT = std::string("ss ") + (Options::video.supersampling ? "on" : "off"); - text_->write(X, y, SS_TEXT); + // PostFX: muestra preset y supersampling en una sola línea, o nada si está desactivado + if (Options::video.postfx) { + std::string preset_name = "-"; + if (!Options::postfx_presets.empty()) { + preset_name = Options::postfx_presets[static_cast(Options::current_postfx_preset)].name; + } + const std::string POSTFX_LINE = preset_name + (Options::video.supersampling ? " (SS)" : ""); + text_->write(X, y, POSTFX_LINE); + } } // Limpia la game_surface_ @@ -511,6 +537,7 @@ void Screen::toggleIntegerScale() { if (shader_backend_) { shader_backend_->setScaleMode(Options::video.integer_scale); } + updateZoomFactor(); } // Alterna entre activar y desactivar el V-Sync diff --git a/source/core/rendering/screen.hpp b/source/core/rendering/screen.hpp index 6c388b7..b281e6f 100644 --- a/source/core/rendering/screen.hpp +++ b/source/core/rendering/screen.hpp @@ -114,6 +114,7 @@ class Screen { void renderNotifications() const; // Dibuja las notificaciones void adjustWindowSize(); // Calcula el tamaño de la ventana void adjustRenderLogicalSize(); // Ajusta el tamaño lógico del renderizador + void updateZoomFactor(); // Recalcula y almacena el factor de zoom real void processPaletteList(); // Extrae los nombres de las paletas void surfaceToTexture(); // Copia la surface a la textura void textureToRenderer(); // Copia la textura al renderizador @@ -154,6 +155,7 @@ class Screen { // Configuración de ventana y pantalla int window_width_{0}; // Ancho de la pantalla o ventana int window_height_{0}; // Alto de la pantalla o ventana + float zoom_factor_{1.0f}; // Factor de zoom calculado (alto físico / alto lógico) SDL_FRect game_surface_dstrect_; // Coordenadas donde se dibuja la textura del juego // Paletas y colores