arreglos en screen
This commit is contained in:
@@ -135,7 +135,7 @@ if(EMSCRIPTEN)
|
|||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
SDL3
|
SDL3
|
||||||
GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
|
GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
|
||||||
GIT_TAG release-3.2.12
|
GIT_TAG release-3.4.4
|
||||||
GIT_SHALLOW TRUE
|
GIT_SHALLOW TRUE
|
||||||
)
|
)
|
||||||
set(SDL_SHARED OFF CACHE BOOL "" FORCE)
|
set(SDL_SHARED OFF CACHE BOOL "" FORCE)
|
||||||
|
|||||||
1
Makefile
1
Makefile
@@ -424,6 +424,7 @@ raspi_release:
|
|||||||
wasm:
|
wasm:
|
||||||
@echo "Compilando para WebAssembly - Version: $(VERSION) ($(GIT_HASH))"
|
@echo "Compilando para WebAssembly - Version: $(VERSION) ($(GIT_HASH))"
|
||||||
docker run --rm \
|
docker run --rm \
|
||||||
|
--user $(shell id -u):$(shell id -g) \
|
||||||
-v $(DIR_ROOT):/src \
|
-v $(DIR_ROOT):/src \
|
||||||
-w /src \
|
-w /src \
|
||||||
emscripten/emsdk:latest \
|
emscripten/emsdk:latest \
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
#include "core/rendering/screen.hpp"
|
#include "core/rendering/screen.hpp"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_SetRenderTarget, SDL_RenderTexture, SDL_SetRenderDrawColor, SDL_SetRenderVSync, SDL_LogCategory, SDL_GetError, SDL_LogError, SDL_LogInfo, SDL_RendererLogicalPresentation, SDL_SetRenderLogicalPresentation, SDL_CreateTexture, SDL_DestroyTexture, SDL_DestroyWindow, SDL_GetDisplayName, SDL_GetTicks, SDL_Quit, SDL_RENDERER_VSYNC_DISABLED, SDL_RenderClear, SDL_CreateRenderer, SDL_CreateWindow, SDL_DestroyRenderer, SDL_DisplayID, SDL_FRect, SDL_GetCurrentDisplayMode, SDL_GetDisplays, SDL_GetRenderTarget, SDL_GetWindowPosition, SDL_GetWindowSize, SDL_Init, SDL_LogWarn, SDL_PixelFormat, SDL_RenderFillRect, SDL_RenderPresent, SDL_SetHint, SDL_SetRenderDrawBlendMode, SDL_SetTextureScaleMode, SDL_SetWindowFullscreen, SDL_SetWindowPosition, SDL_SetWindowSize, SDL_TextureAccess, SDL_free, SDL_BLENDMODE_BLEND, SDL_HINT_RENDER_DRIVER, SDL_INIT_VIDEO, SDL_ScaleMode, SDL_WINDOW_FULLSCREEN, SDL_WindowFlags
|
#include <SDL3/SDL.h> // Para SDL_SetRenderTarget, SDL_RenderTexture, SDL_SetRenderDrawColor, SDL_SetRenderVSync, SDL_LogCategory, SDL_GetError, SDL_LogError, SDL_LogInfo, SDL_RendererLogicalPresentation, SDL_SetRenderLogicalPresentation, SDL_CreateTexture, SDL_DestroyTexture, SDL_DestroyWindow, SDL_GetDisplayName, SDL_GetTicks, SDL_Quit, SDL_RENDERER_VSYNC_DISABLED, SDL_RenderClear, SDL_CreateRenderer, SDL_CreateWindow, SDL_DestroyRenderer, SDL_DisplayID, SDL_FRect, SDL_GetCurrentDisplayMode, SDL_GetDisplays, SDL_GetRenderTarget, SDL_GetWindowPosition, SDL_GetWindowSize, SDL_Init, SDL_LogWarn, SDL_PixelFormat, SDL_RenderFillRect, SDL_RenderPresent, SDL_SetHint, SDL_SetRenderDrawBlendMode, SDL_SetTextureScaleMode, SDL_SetWindowFullscreen, SDL_SetWindowPosition, SDL_SetWindowSize, SDL_SyncWindow, SDL_TextureAccess, SDL_free, SDL_BLENDMODE_BLEND, SDL_HINT_RENDER_DRIVER, SDL_INIT_VIDEO, SDL_ScaleMode, SDL_WINDOW_FULLSCREEN, SDL_WindowFlags
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
#include <emscripten.h>
|
||||||
|
#include <emscripten/html5.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <algorithm> // Para min, max
|
#include <algorithm> // Para min, max
|
||||||
#include <cstring> // Para memcpy
|
#include <cstring> // Para memcpy
|
||||||
@@ -27,6 +31,43 @@
|
|||||||
// Singleton
|
// Singleton
|
||||||
Screen* Screen::instance = nullptr;
|
Screen* Screen::instance = nullptr;
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
// ============================================================================
|
||||||
|
// Restauración del canvas en wasm/Emscripten
|
||||||
|
// ============================================================================
|
||||||
|
// SDL3 + Emscripten no notifica de forma fiable los cambios de estado del
|
||||||
|
// canvas HTML (fullscreen exit vía Esc, rotación del dispositivo, etc.).
|
||||||
|
// Registramos callbacks nativos de Emscripten que delegan en
|
||||||
|
// Screen::handleCanvasResized(), el cual re-aplica el modo de fullscreen y
|
||||||
|
// reajusta la ventana para que SDL salga de su estado interno de fullscreen.
|
||||||
|
//
|
||||||
|
// Los callbacks difieren el trabajo con emscripten_async_call(0ms) porque el
|
||||||
|
// navegador todavía no ha acabado de redimensionar el canvas cuando el evento
|
||||||
|
// se dispara; posponer al siguiente tick garantiza valores estables.
|
||||||
|
//
|
||||||
|
// Referencias: libsdl-org/SDL#13300, libsdl-org/SDL#11389.
|
||||||
|
// ============================================================================
|
||||||
|
namespace {
|
||||||
|
void deferredCanvasResize(void* /*user_data*/) {
|
||||||
|
if (Screen::get() != nullptr) { Screen::get()->handleCanvasResized(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
auto onEmFullscreenChange(int /*event_type*/, const EmscriptenFullscreenChangeEvent* event, void* /*user_data*/) -> EM_BOOL {
|
||||||
|
// Sincronizamos Options::video.fullscreen con el estado real del navegador
|
||||||
|
// antes de diferir la restauración: cuando el usuario sale con Esc no pasa
|
||||||
|
// por toggleFullscreen() y el estado interno quedaría desincronizado.
|
||||||
|
Options::video.fullscreen = (event != nullptr && event->isFullscreen != 0);
|
||||||
|
emscripten_async_call(deferredCanvasResize, nullptr, 0);
|
||||||
|
return EM_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto onEmOrientationChange(int /*event_type*/, const EmscriptenOrientationChangeEvent* /*event*/, void* /*user_data*/) -> EM_BOOL {
|
||||||
|
emscripten_async_call(deferredCanvasResize, nullptr, 0);
|
||||||
|
return EM_FALSE;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
#endif
|
||||||
|
|
||||||
// Inicializa la instancia única del singleton
|
// Inicializa la instancia única del singleton
|
||||||
void Screen::init() {
|
void Screen::init() {
|
||||||
Screen::instance = new Screen();
|
Screen::instance = new Screen();
|
||||||
@@ -69,6 +110,14 @@ Screen::Screen()
|
|||||||
// Renderizar una vez la textura vacía para que tenga contenido válido antes de inicializar los shaders (evita pantalla negra)
|
// Renderizar una vez la textura vacía para que tenga contenido válido antes de inicializar los shaders (evita pantalla negra)
|
||||||
SDL_RenderTexture(renderer_, game_canvas_, nullptr, nullptr);
|
SDL_RenderTexture(renderer_, game_canvas_, nullptr, nullptr);
|
||||||
|
|
||||||
|
// Aplicar la configuración inicial completa (vsync + logical presentation +
|
||||||
|
// fullscreen + tamaño de ventana). En Emscripten es necesario porque el
|
||||||
|
// canvas HTML tiene un tamaño propio y SDL_CreateWindow solo no basta para
|
||||||
|
// que SDL sincronice su viewport interno con el canvas real: sin este
|
||||||
|
// applySettings el canvas inicial sale descolocado con barras negras a los
|
||||||
|
// lados y el juego pequeño en el centro hasta el primer toggle de fullscreen.
|
||||||
|
applySettings();
|
||||||
|
|
||||||
// Limpiar renderer
|
// Limpiar renderer
|
||||||
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255);
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255);
|
||||||
SDL_RenderClear(renderer_);
|
SDL_RenderClear(renderer_);
|
||||||
@@ -145,10 +194,39 @@ void Screen::setFullscreenMode() {
|
|||||||
SDL_SetWindowFullscreen(window_, Options::video.fullscreen);
|
SDL_SetWindowFullscreen(window_, Options::video.fullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Camibia entre pantalla completa y ventana
|
// Cambia entre pantalla completa y ventana. Usamos applySettings en vez de
|
||||||
|
// setFullscreenMode porque applySettings también re-aplica la logical
|
||||||
|
// presentation — sin eso, al entrar en fullscreen SDL no recalcula el viewport
|
||||||
|
// y el juego se ve pequeño (especialmente en Android).
|
||||||
void Screen::toggleFullscreen() {
|
void Screen::toggleFullscreen() {
|
||||||
Options::video.fullscreen = !Options::video.fullscreen;
|
Options::video.fullscreen = !Options::video.fullscreen;
|
||||||
setFullscreenMode();
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-sincroniza SDL con el estado real del canvas del navegador. Lo invocan los
|
||||||
|
// callbacks nativos de Emscripten (vegeu el bloc al principi del fitxer) cuando
|
||||||
|
// se detecta un fullscreenchange o un orientationchange. Re-aplica fullscreen y
|
||||||
|
// reajusta la ventana porque SDL no emite SDL_EVENT_WINDOW_LEAVE_FULLSCREEN en
|
||||||
|
// Emscripten y su estado interno queda desincronizado al salir con Esc.
|
||||||
|
// Fuera de Emscripten es un no-op (desktop sí emite los events correctamente).
|
||||||
|
void Screen::handleCanvasResized() {
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
// SDL_SetWindowFullscreen es imprescindible para sacar a SDL de su estado
|
||||||
|
// interno de fullscreen cuando el usuario ha salido sin pasar por
|
||||||
|
// toggleFullscreen (onEmFullscreenChange ya ha actualizado Options).
|
||||||
|
SDL_SetWindowFullscreen(window_, Options::video.fullscreen);
|
||||||
|
SDL_SyncWindow(window_);
|
||||||
|
adjustWindowSize();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registra los callbacks nativos de Emscripten que restauran el canvas cuando
|
||||||
|
// SDL3 no emite los events equivalentes. Fuera de Emscripten es un no-op.
|
||||||
|
void Screen::registerEmscriptenEventCallbacks() { // NOLINT(readability-convert-member-functions-to-static)
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, EM_TRUE, onEmFullscreenChange);
|
||||||
|
emscripten_set_orientationchange_callback(nullptr, EM_TRUE, onEmOrientationChange);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cambia el tamaño de la ventana
|
// Cambia el tamaño de la ventana
|
||||||
@@ -424,6 +502,8 @@ auto Screen::initSDLVideo() -> bool {
|
|||||||
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
|
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
|
||||||
SDL_SetRenderVSync(renderer_, Options::video.vsync ? 1 : SDL_RENDERER_VSYNC_DISABLED);
|
SDL_SetRenderVSync(renderer_, Options::video.vsync ? 1 : SDL_RENDERER_VSYNC_DISABLED);
|
||||||
|
|
||||||
|
registerEmscriptenEventCallbacks();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,12 +691,17 @@ void Screen::getSingletons() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aplica los valores de las opciones
|
// Aplica los valores de las opciones.
|
||||||
|
// IMPORTANTE: el orden importa. SDL_SetRenderLogicalPresentation calcula el
|
||||||
|
// viewport en función del tamaño actual de la ventana SDL, así que DEBE llamarse
|
||||||
|
// DESPUÉS de setFullscreenMode/adjustWindowSize — si no, al entrar en fullscreen
|
||||||
|
// el viewport queda cacheado al tamaño de la ventana pequeña previa y el juego
|
||||||
|
// se ve pequeño y centrado con barras negras alrededor.
|
||||||
void Screen::applySettings() {
|
void Screen::applySettings() {
|
||||||
SDL_SetRenderVSync(renderer_, Options::video.vsync ? 1 : SDL_RENDERER_VSYNC_DISABLED);
|
SDL_SetRenderVSync(renderer_, Options::video.vsync ? 1 : SDL_RENDERER_VSYNC_DISABLED);
|
||||||
SDL_SetRenderLogicalPresentation(Screen::get()->getRenderer(), param.game.width, param.game.height, Options::video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX);
|
|
||||||
setFullscreenMode();
|
setFullscreenMode();
|
||||||
adjustWindowSize();
|
adjustWindowSize();
|
||||||
|
SDL_SetRenderLogicalPresentation(renderer_, param.game.width, param.game.height, Options::video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea el objeto de texto
|
// Crea el objeto de texto
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ class Screen {
|
|||||||
// --- Configuración de ventana y render ---
|
// --- Configuración de ventana y render ---
|
||||||
void setFullscreenMode(); // Establece el modo de pantalla completa
|
void setFullscreenMode(); // Establece el modo de pantalla completa
|
||||||
void toggleFullscreen(); // Cambia entre pantalla completa y ventana
|
void toggleFullscreen(); // Cambia entre pantalla completa y ventana
|
||||||
|
void handleCanvasResized(); // Restaura el canvas cuando SDL3 no reporta el cambio (emscripten only: salida de fullscreen con Esc, rotación); no-op fuera de emscripten
|
||||||
void setWindowZoom(int zoom); // Cambia el tamaño de la ventana
|
void setWindowZoom(int zoom); // Cambia el tamaño de la ventana
|
||||||
auto decWindowSize() -> bool; // Reduce el tamaño de la ventana
|
auto decWindowSize() -> bool; // Reduce el tamaño de la ventana
|
||||||
auto incWindowSize() -> bool; // Aumenta el tamaño de la ventana
|
auto incWindowSize() -> bool; // Aumenta el tamaño de la ventana
|
||||||
@@ -233,6 +234,7 @@ class Screen {
|
|||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana
|
auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana
|
||||||
|
void registerEmscriptenEventCallbacks(); // Registra callbacks nativos para restaurar el canvas en wasm (no-op fuera de emscripten)
|
||||||
void renderFlash(); // Dibuja el efecto de flash en la pantalla
|
void renderFlash(); // Dibuja el efecto de flash en la pantalla
|
||||||
void renderShake(); // Aplica el efecto de agitar la pantalla
|
void renderShake(); // Aplica el efecto de agitar la pantalla
|
||||||
void renderInfo() const; // Muestra información por pantalla
|
void renderInfo() const; // Muestra información por pantalla
|
||||||
|
|||||||
Reference in New Issue
Block a user