diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index d475e9c..387b07c 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -508,14 +508,16 @@ void Screen::clearNotification() { notification_message_.clear(); } -// Dibuja la notificación activa (si la hay) sobre el gameCanvas +// Dibuja la notificación activa (si la hay) sobre el gameCanvas. La Y es +// el `notification_y_` configurat, desplacat cap avall si en overscan part +// de la franja superior queda fora de pantalla. void Screen::renderNotification() { if (notification_text_ == nullptr || SDL_GetTicks() >= notification_end_time_) { return; } notification_text_->writeDX(Text::FLAG_CENTER | Text::FLAG_COLOR | Text::FLAG_STROKE, game_canvas_width_ / 2, - notification_y_, + notification_y_ + safeNotificationY(), notification_message_, 1, notification_text_color_, @@ -523,6 +525,21 @@ void Screen::renderNotification() { notification_outline_color_); } +// Y minima del canvas visible. Solo no zero quan estem en overscan i l'aspect +// de finestra obliga a escalar mes ample que alt (el canvas vertical desborda +// i la franja superior es retalla). En cas contrari (qualsevol altre mode, o +// overscan amb retall horitzontal nomes), retorna 0. +auto Screen::safeNotificationY() const -> int { + if (Options::video.presentation_mode != Options::PresentationMode::OVERSCAN) { return 0; } + if (window_width_ <= 0 || window_height_ <= 0 || game_canvas_height_ <= 0) { return 0; } + const float CANVAS_RATIO = static_cast(game_canvas_width_) / static_cast(game_canvas_height_); + const float WINDOW_RATIO = static_cast(window_width_) / static_cast(window_height_); + if (WINDOW_RATIO < CANVAS_RATIO) { return 0; } // retall horitzontal nomes + const float OVERSCAN_SCALE = static_cast(window_width_) / static_cast(game_canvas_width_); + const float VH = static_cast(game_canvas_height_) * OVERSCAN_SCALE; + return static_cast(std::ceil((VH - static_cast(window_height_)) / (2.0F * OVERSCAN_SCALE))); +} + // ============================================================================ // Emscripten — fix per a fullscreen/resize (veure el bloc de comentaris al // principi del fitxer i l'anonymous namespace amb els callbacks natius). diff --git a/source/core/rendering/screen.h b/source/core/rendering/screen.h index 8afe954..c90dfa4 100644 --- a/source/core/rendering/screen.h +++ b/source/core/rendering/screen.h @@ -112,7 +112,8 @@ class Screen { void registerEmscriptenEventCallbacks(); // Registra los callbacks nativos de Emscripten para fullscreenchange y orientationchange. No-op fuera de Emscripten // Notificaciones - void renderNotification(); // Dibuja la notificación activa (si la hay) sobre el gameCanvas + void renderNotification(); // Dibuja la notificación activa (si la hay) sobre el gameCanvas + [[nodiscard]] auto safeNotificationY() const -> int; // Y minima dins del canvas que segueix sent visible en overscan (segons aspect ratio finestra/canvas) #ifndef NO_SHADERS // Aplica els paràmetres actuals del shader al backend segons options