From 659e37e5a1ced776d22376c7088fb9122e57e990 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Sun, 17 May 2026 17:46:49 +0200 Subject: [PATCH] window: max_zoom derivat del display via Screen::detectMaxZoom() --- source/core/rendering/screen.cpp | 32 ++++++++++++++++++++++++++++++-- source/core/rendering/screen.h | 10 +++++++++- source/core/system/director.cpp | 4 ++++ source/game/options.cpp | 9 ++++++--- 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index 7afc77a..9c426a4 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -282,7 +282,7 @@ auto Screen::decWindowZoom() -> bool { auto Screen::incWindowZoom() -> bool { if (Options::video.fullscreen) { return false; } const int PREV = Options::window.zoom; - Options::window.zoom = std::min(Options::window.zoom + 1, WINDOW_ZOOM_MAX); + Options::window.zoom = std::min(Options::window.zoom + 1, Options::window.max_zoom); if (Options::window.zoom == PREV) { return false; } setVideoMode(false); return true; @@ -291,13 +291,41 @@ auto Screen::incWindowZoom() -> bool { // Establece el zoom de la ventana directamente auto Screen::setWindowZoom(int zoom) -> bool { if (Options::video.fullscreen) { return false; } - if (zoom < WINDOW_ZOOM_MIN || zoom > WINDOW_ZOOM_MAX) { return false; } + if (zoom < WINDOW_ZOOM_MIN || zoom > Options::window.max_zoom) { return false; } if (zoom == Options::window.zoom) { return false; } Options::window.zoom = zoom; setVideoMode(false); return true; } +// Detecta el zoom màxim windowed segons la resolució del display actual. +void Screen::detectMaxZoom() { +#ifdef __EMSCRIPTEN__ + // En WASM el tamany del canvas el fixa el browser; el zoom no aplica. + return; +#else + int num_displays = 0; + SDL_DisplayID *displays = SDL_GetDisplays(&num_displays); + if (displays == nullptr || num_displays == 0) { + if (displays != nullptr) { SDL_free(displays); } + return; + } + const auto *dm = SDL_GetCurrentDisplayMode(displays[0]); + if (dm != nullptr) { + const int MAX_W = dm->w / GAMECANVAS_WIDTH; + const int MAX_H = (dm->h - WINDOWS_DECORATIONS) / GAMECANVAS_HEIGHT; + const int DETECTED = std::max(WINDOW_ZOOM_MIN, std::min(MAX_W, MAX_H)); + Options::window.max_zoom = DETECTED; + Options::window.zoom = std::clamp(Options::window.zoom, WINDOW_ZOOM_MIN, DETECTED); + if (Options::settings.console) { + std::cout << "Display " << dm->w << "x" << dm->h + << " → max windowed zoom = " << DETECTED << "x\n"; + } + } + SDL_free(displays); +#endif +} + // Establece el escalado entero void Screen::setIntegerScale(bool enabled) { if (Options::video.integer_scale == enabled) { return; } diff --git a/source/core/rendering/screen.h b/source/core/rendering/screen.h index 5efc0cb..52540df 100644 --- a/source/core/rendering/screen.h +++ b/source/core/rendering/screen.h @@ -21,7 +21,9 @@ class Screen { public: // Constantes static constexpr int WINDOW_ZOOM_MIN = 1; - static constexpr int WINDOW_ZOOM_MAX = 4; + // Pixels reservats per a la barra de títol/decoracions a l'hora de + // calcular el zoom màxim windowed (mateix valor que CCAE/jaildoctors). + static constexpr int WINDOWS_DECORATIONS = 35; #ifdef __EMSCRIPTEN__ // En WASM el tamaño de ventana está fijado a 1x, así que escalamos el // renderizado por 3 aprovechando el modo NEAREST de la textura del juego @@ -34,6 +36,12 @@ class Screen { static void destroy(); // Libera la instancia static auto get() -> Screen *; // Obtiene el puntero a la instancia + // Detecta el zoom màxim windowed segons la resolució del display actual. + // Cal cridar-la després de SDL_Init(VIDEO) i abans de crear la finestra. + // Escriu a `Options::window.max_zoom` i clampa `Options::window.zoom`. + // En Emscripten és no-op (el tamany del canvas el controla el browser). + static void detectMaxZoom(); + // Destructor (público por requisitos de `delete` desde destroy()) ~Screen(); diff --git a/source/core/system/director.cpp b/source/core/system/director.cpp index b438e4f..59064ed 100644 --- a/source/core/system/director.cpp +++ b/source/core/system/director.cpp @@ -269,6 +269,10 @@ auto Director::initSDL() -> bool { // Inicia el generador de numeros aleatorios std::srand(static_cast(SDL_GetTicks())); + // Calcula el zoom màxim windowed segons el display actual i clampa + // `Options::window.zoom` abans de crear la finestra. + Screen::detectMaxZoom(); + // Crea la ventana window_ = SDL_CreateWindow( Options::window.caption.c_str(), diff --git a/source/game/options.cpp b/source/game/options.cpp index 6058f31..16cc1d2 100644 --- a/source/game/options.cpp +++ b/source/game/options.cpp @@ -69,7 +69,9 @@ namespace Options { if (!yaml.contains("window")) { return; } const auto &win = yaml["window"]; parseIntField(win, "zoom", window.zoom); - if (window.zoom < 1 || window.zoom > window.max_zoom) { + // El bound superior s'aplica més tard a `Screen::detectMaxZoom()` + // un cop sabem la resolució real del display. + if (window.zoom < 1) { window.zoom = Defaults::Window::ZOOM; } } @@ -270,10 +272,11 @@ namespace Options { file << "config_version: " << settings.config_version << "\n\n"; // WINDOW + // `max_zoom` no es guarda — es deriva del display a cada arranc via + // `Screen::detectMaxZoom()`. file << "# WINDOW\n"; file << "window:\n"; - file << " zoom: " << window.zoom << "\n"; - file << " max_zoom: " << window.max_zoom << "\n\n"; + file << " zoom: " << window.zoom << "\n\n"; // VIDEO file << "# VIDEO\n";