tone a commitar pa provar el canvi de pantalla en emscripten

This commit is contained in:
2026-04-13 20:09:18 +02:00
parent 9b8820ffa3
commit 9047bd7d1f
3 changed files with 56 additions and 19 deletions

View File

@@ -1,6 +1,10 @@
#include "core/rendering/screen.hpp" #include "core/rendering/screen.hpp"
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/html5.h>
#endif
#include <algorithm> // Para max, min, transform #include <algorithm> // Para max, min, transform
#include <cctype> // Para toupper #include <cctype> // Para toupper
@@ -28,6 +32,28 @@
// [SINGLETON] // [SINGLETON]
Screen* Screen::screen = nullptr; Screen* Screen::screen = nullptr;
#ifdef __EMSCRIPTEN__
// Callbacks d'Emscripten per detectar canvis de mida que SDL3 no reporta
// de manera fiable al wasm: sortida de fullscreen (Esc/F11), rotació del
// dispositiu i resize de la finestra del navegador. Tots reenvien al mètode
// Screen::handleCanvasResized() que re-sincronitza la finestra SDL amb la
// mida real del canvas. Veure issues libsdl-org/SDL #13300 i #11389.
namespace {
auto onEmFullscreenChange(int /*event_type*/, const EmscriptenFullscreenChangeEvent* /*event*/, void* /*user_data*/) -> EM_BOOL {
if (Screen::get() != nullptr) { Screen::get()->handleCanvasResized(); }
return EM_FALSE;
}
auto onEmResize(int /*event_type*/, const EmscriptenUiEvent* /*event*/, void* /*user_data*/) -> EM_BOOL {
if (Screen::get() != nullptr) { Screen::get()->handleCanvasResized(); }
return EM_FALSE;
}
auto onEmOrientationChange(int /*event_type*/, const EmscriptenOrientationChangeEvent* /*event*/, void* /*user_data*/) -> EM_BOOL {
if (Screen::get() != nullptr) { Screen::get()->handleCanvasResized(); }
return EM_FALSE;
}
} // namespace
#endif
// [SINGLETON] Crearemos el objeto con esta función estática // [SINGLETON] Crearemos el objeto con esta función estática
void Screen::init() { void Screen::init() {
Screen::screen = new Screen(); Screen::screen = new Screen();
@@ -168,11 +194,21 @@ void Screen::toggleVideoMode() {
setVideoMode(Options::video.fullscreen); setVideoMode(Options::video.fullscreen);
} }
// Re-sincronitza el logical size i el factor de zoom quan la mida de la finestra canvia // Re-sincronitza la finestra SDL amb la mida real del canvas HTML. Només cal en
// per una causa externa al joc: navegador sortint de fullscreen (Esc), rotació del dispositiu, // emscripten: quan l'usuari surt de fullscreen amb Esc, rota el dispositiu o
// redimensionat de la finestra, etc. No toca SDL_SetWindowFullscreen ni SDL_SetWindowSize // canvia la mida del canvas, SDL3 no emet SDL_EVENT_WINDOW_LEAVE_FULLSCREEN ni
// per no interferir amb el que estigui fent el sistema/navegador. // SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED de manera fiable (issues libsdl-org/SDL
void Screen::handleWindowResized() { // #13300 i #11389), així que els callbacks d'Emscripten criden aquest mètode
// directament. Llegim la mida real del canvas per CSS i l'apliquem a la finestra
// SDL perquè el logical presentation s'escali al nou viewport.
void Screen::handleCanvasResized() {
#ifdef __EMSCRIPTEN__
double css_w = 0.0;
double css_h = 0.0;
if (emscripten_get_element_css_size("#canvas", &css_w, &css_h) == EMSCRIPTEN_RESULT_SUCCESS && css_w > 0.0 && css_h > 0.0) {
SDL_SetWindowSize(window_, static_cast<int>(css_w), static_cast<int>(css_h));
}
#endif
adjustRenderLogicalSize(); adjustRenderLogicalSize();
updateZoomFactor(); updateZoomFactor();
} }
@@ -752,6 +788,15 @@ auto Screen::initSDLVideo() -> bool {
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
SDL_SetRenderVSync(renderer_, Options::video.vertical_sync ? 1 : SDL_RENDERER_VSYNC_DISABLED); SDL_SetRenderVSync(renderer_, Options::video.vertical_sync ? 1 : SDL_RENDERER_VSYNC_DISABLED);
#ifdef __EMSCRIPTEN__
// Registrem callbacks d'Emscripten per reaccionar a canvis de mida del
// canvas que SDL3 no notifica: sortida de fullscreen amb Esc, rotació
// del dispositiu i resize de la finestra del navegador.
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, EM_TRUE, onEmFullscreenChange);
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, EM_TRUE, onEmResize);
emscripten_set_orientationchange_callback(nullptr, EM_TRUE, onEmOrientationChange);
#endif
std::cout << "Video system initialized successfully\n"; std::cout << "Video system initialized successfully\n";
return true; return true;
} }

View File

@@ -38,7 +38,7 @@ class Screen {
// Video y ventana // Video y ventana
void setVideoMode(bool mode); // Establece el modo de video void setVideoMode(bool mode); // Establece el modo de video
void toggleVideoMode(); // Cambia entre pantalla completa y ventana void toggleVideoMode(); // Cambia entre pantalla completa y ventana
void handleWindowResized(); // Re-sincronitza logical size i zoom en canvis de mida externs (fullscreen, rotació, resize) void handleCanvasResized(); // Re-sincronitza SDL amb la mida real del canvas (emscripten: sortida de fullscreen, rotació, resize)
void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero
void toggleVSync(); // Alterna entre activar y desactivar el V-Sync void toggleVSync(); // Alterna entre activar y desactivar el V-Sync
auto decWindowZoom() -> bool; // Reduce el tamaño de la ventana auto decWindowZoom() -> bool; // Reduce el tamaño de la ventana

View File

@@ -2,12 +2,11 @@
#include "core/input/input.hpp" // Para Input (gamepad add/remove) #include "core/input/input.hpp" // Para Input (gamepad add/remove)
#include "core/input/mouse.hpp" #include "core/input/mouse.hpp"
#include "core/locale/locale.hpp" // Para Locale #include "core/locale/locale.hpp" // Para Locale
#include "core/rendering/screen.hpp" // Para Screen::handleWindowResized #include "game/options.hpp" // Para Options, options, OptionsGame, OptionsAudio
#include "game/options.hpp" // Para Options, options, OptionsGame, OptionsAudio #include "game/scene_manager.hpp" // Para SceneManager::current (filtrar BACK a GAME)
#include "game/scene_manager.hpp" // Para SceneManager::current (filtrar BACK a GAME) #include "game/ui/console.hpp" // Para Console
#include "game/ui/console.hpp" // Para Console #include "game/ui/notifier.hpp" // Para Notifier
#include "game/ui/notifier.hpp" // Para Notifier
namespace GlobalEvents { namespace GlobalEvents {
@@ -24,13 +23,6 @@ namespace GlobalEvents {
// reLoadTextures(); // reLoadTextures();
} }
// Canvi de mida de la finestra (fullscreen toggle extern, rotació del dispositiu,
// resize manual...). Re-sincronitzem el logical size del renderer i el zoom factor
// per evitar que la textura quedi estirada o desalineada amb el nou viewport.
if (event.type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED && Screen::get() != nullptr) {
Screen::get()->handleWindowResized();
}
// Connexió/desconnexió de gamepads: cal enrutar-los a Input perquè // Connexió/desconnexió de gamepads: cal enrutar-los a Input perquè
// afegisca el dispositiu a gamepads_. Sense això, en wasm els gamepads // afegisca el dispositiu a gamepads_. Sense això, en wasm els gamepads
// mai es detecten (la Gamepad API del navegador només els exposa // mai es detecten (la Gamepad API del navegador només els exposa