From 5c0d0479ad3e1ea228b646f08d9535e75d49b00f Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Fri, 20 Mar 2026 09:18:11 +0100 Subject: [PATCH] fix(engine): implementar viewport/scissor F6 i eliminar early return toggleIntegerScaling - Eliminar guarda !fullscreen_enabled_ de toggleIntegerScaling(): F6 ara cicla i notifica en mode ventana i fullscreen per igual - Pass 2: afegir viewport+scissor SDL_GPU condicionat a fullscreen_enabled_ per als tres modes (INTEGER pixel-perfect centrat, LETTERBOX aspect-ratio, STRETCH pantalla completa) Co-Authored-By: Claude Sonnet 4.6 --- source/engine.cpp | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/source/engine.cpp b/source/engine.cpp index 7f0d082..b9e5932 100644 --- a/source/engine.cpp +++ b/source/engine.cpp @@ -857,6 +857,36 @@ void Engine::render() { SDL_GPURenderPass* pass2 = SDL_BeginGPURenderPass(cmd, &ct, 1, nullptr); + // Viewport/scissor per integer scaling (only F3 fullscreen) + if (fullscreen_enabled_) { + float vp_x, vp_y, vp_w, vp_h; + if (current_scaling_mode_ == ScalingMode::STRETCH) { + vp_x = 0.0f; vp_y = 0.0f; + vp_w = static_cast(sw_w); + vp_h = static_cast(sw_h); + } else if (current_scaling_mode_ == ScalingMode::INTEGER) { + int scale = static_cast(std::min(sw_w / static_cast(base_screen_width_), + sw_h / static_cast(base_screen_height_))); + if (scale < 1) scale = 1; + vp_w = static_cast(base_screen_width_ * scale); + vp_h = static_cast(base_screen_height_ * scale); + vp_x = (static_cast(sw_w) - vp_w) * 0.5f; + vp_y = (static_cast(sw_h) - vp_h) * 0.5f; + } else { // LETTERBOX + float scale = std::min(static_cast(sw_w) / base_screen_width_, + static_cast(sw_h) / base_screen_height_); + vp_w = base_screen_width_ * scale; + vp_h = base_screen_height_ * scale; + vp_x = (static_cast(sw_w) - vp_w) * 0.5f; + vp_y = (static_cast(sw_h) - vp_h) * 0.5f; + } + SDL_GPUViewport vp = {vp_x, vp_y, vp_w, vp_h, 0.0f, 1.0f}; + SDL_SetGPUViewport(pass2, &vp); + SDL_Rect scissor = {static_cast(vp_x), static_cast(vp_y), + static_cast(vp_w), static_cast(vp_h)}; + SDL_SetGPUScissor(pass2, &scissor); + } + // PostFX: full-screen triangle via vertex_id (no vertex buffer needed) SDL_BindGPUGraphicsPipeline(pass2, gpu_pipeline_->postfxPipeline()); SDL_GPUTextureSamplerBinding scene_tsb = {offscreen_tex_->texture(), offscreen_tex_->sampler()}; @@ -1060,11 +1090,6 @@ void Engine::setInitialPostFX(int mode) { } void Engine::toggleIntegerScaling() { - // Solo permitir cambio si estamos en modo fullscreen normal (F3) - if (!fullscreen_enabled_) { - return; // No hacer nada si no estamos en fullscreen - } - // Ciclar entre los 3 modos: INTEGER → LETTERBOX → STRETCH → INTEGER switch (current_scaling_mode_) { case ScalingMode::INTEGER: @@ -1078,16 +1103,13 @@ void Engine::toggleIntegerScaling() { break; } - // SDL_GPU stretches to fill swapchain by default; just show notification const char* mode_name = "INTEGER"; switch (current_scaling_mode_) { - case ScalingMode::INTEGER: mode_name = "INTEGER"; break; + case ScalingMode::INTEGER: mode_name = "INTEGER"; break; case ScalingMode::LETTERBOX: mode_name = "LETTERBOX"; break; - case ScalingMode::STRETCH: mode_name = "STRETCH"; break; + case ScalingMode::STRETCH: mode_name = "STRETCH"; break; } - - std::string notification = std::string("Escalado: ") + mode_name; - ui_manager_->showNotification(notification); + showNotificationForAction(std::string("Escalado: ") + mode_name); } void Engine::addSpriteToBatch(float x, float y, float w, float h, int r, int g, int b, float scale) {