refactor(#28): SDLManager rep Config::EngineConfig + on_persist callback
Pas 4/N del hallazgo #28. SDLManager deixa d'incloure game/options.hpp. El ctor accepta ara una Config::EngineConfig& (per llegir/mutar window i rendering) i un opcional std::function<void()> on_persist callback. Canvis funcionals: - Es mantenen les mutacions de window.{width,height,zoom_factor,fullscreen} però ara sobre cfg_->window en lloc d'Options::window. Comportament idèntic perquè Options::window és un alias a engine_config.window. - toggleVSync deixa de cridar Options::saveToFile() directament i invoca on_persist_ si està connectat. El Director li passa una lambda que fa la persistència (mantenint sdl_manager agnòstic). - initWindowAndGpu (free function) rep el vsync inicial per paràmetre. - Eliminat el ctor per defecte (SDLManager()) que no era cridat des de cap call-site del projecte. Cleanup preexistent surfat per clang-tidy en treure el ctor default: - finestra_, max_width_, max_height_, max_zoom_ passen a tindre default member initializers; eliminat el seu ctor mem-init redundant. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,95 +13,65 @@
|
||||
#include "core/defaults.hpp"
|
||||
#include "core/input/mouse.hpp"
|
||||
#include "core/rendering/coordinate_transform.hpp"
|
||||
#include "game/options.hpp"
|
||||
#include "project.h"
|
||||
|
||||
namespace {
|
||||
auto initWindowAndGpu(SDL_Window** out_window,
|
||||
Rendering::Renderer& gpu_renderer,
|
||||
int width, int height, bool fullscreen) -> bool {
|
||||
// Título estático estilo CCAE. El FPS y el estado de VSync los muestra
|
||||
// el DebugOverlay (toggle F11), no la barra de título.
|
||||
const std::string TITLE = std::format("© 2026 {} — JailDesigner",
|
||||
Project::LONG_NAME);
|
||||
auto initWindowAndGpu(SDL_Window** out_window,
|
||||
Rendering::Renderer& gpu_renderer,
|
||||
int width,
|
||||
int height,
|
||||
bool fullscreen,
|
||||
int initial_vsync) -> bool {
|
||||
// Título estático estilo CCAE. El FPS y el estado de VSync los muestra
|
||||
// el DebugOverlay (toggle F11), no la barra de título.
|
||||
const std::string TITLE = std::format("© 2026 {} — JailDesigner",
|
||||
Project::LONG_NAME);
|
||||
|
||||
SDL_WindowFlags flags = SDL_WINDOW_RESIZABLE;
|
||||
if (fullscreen) {
|
||||
flags = static_cast<SDL_WindowFlags>(flags | SDL_WINDOW_FULLSCREEN);
|
||||
SDL_WindowFlags flags = SDL_WINDOW_RESIZABLE;
|
||||
if (fullscreen) {
|
||||
flags = static_cast<SDL_WindowFlags>(flags | SDL_WINDOW_FULLSCREEN);
|
||||
}
|
||||
|
||||
SDL_Window* window = SDL_CreateWindow(TITLE.c_str(), width, height, flags);
|
||||
if (window == nullptr) {
|
||||
std::cerr << "Error creant finestra: " << SDL_GetError() << '\n';
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fullscreen) {
|
||||
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
}
|
||||
|
||||
// Inicializar el FrameRenderer (claim del window + pipeline de líneas).
|
||||
if (!gpu_renderer.init(window,
|
||||
static_cast<float>(Defaults::Game::WIDTH),
|
||||
static_cast<float>(Defaults::Game::HEIGHT))) {
|
||||
std::cerr << "Error inicialitzant GpuFrameRenderer\n";
|
||||
SDL_DestroyWindow(window);
|
||||
return false;
|
||||
}
|
||||
|
||||
gpu_renderer.setVSync(initial_vsync != 0);
|
||||
|
||||
// Cargar parámetros del postpro desde el resource pack. Si el YAML falta
|
||||
// o falla, el loader devuelve los defaults built-in (bloom suave + flicker
|
||||
// sutil + background verde tenue).
|
||||
gpu_renderer.setPostFx(Config::PostFx::load("config/postfx.yaml"));
|
||||
|
||||
*out_window = window;
|
||||
return true;
|
||||
}
|
||||
|
||||
SDL_Window* window = SDL_CreateWindow(TITLE.c_str(), width, height, flags);
|
||||
if (window == nullptr) {
|
||||
std::cerr << "Error creant finestra: " << SDL_GetError() << '\n';
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fullscreen) {
|
||||
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
}
|
||||
|
||||
// Inicializar el FrameRenderer (claim del window + pipeline de líneas).
|
||||
if (!gpu_renderer.init(window,
|
||||
static_cast<float>(Defaults::Game::WIDTH),
|
||||
static_cast<float>(Defaults::Game::HEIGHT))) {
|
||||
std::cerr << "Error inicialitzant GpuFrameRenderer\n";
|
||||
SDL_DestroyWindow(window);
|
||||
return false;
|
||||
}
|
||||
|
||||
gpu_renderer.setVSync(Options::rendering.vsync != 0);
|
||||
|
||||
// Cargar parámetros del postpro desde el resource pack. Si el YAML falta
|
||||
// o falla, el loader devuelve los defaults built-in (bloom suave + flicker
|
||||
// sutil + background verde tenue).
|
||||
gpu_renderer.setPostFx(Config::PostFx::load("config/postfx.yaml"));
|
||||
|
||||
*out_window = window;
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SDLManager::SDLManager()
|
||||
: finestra_(nullptr),
|
||||
current_width_(Defaults::Window::WIDTH),
|
||||
current_height_(Defaults::Window::HEIGHT),
|
||||
is_fullscreen_(false),
|
||||
max_width_(1920),
|
||||
max_height_(1080),
|
||||
zoom_factor_(Defaults::Window::BASE_ZOOM),
|
||||
windowed_width_(Defaults::Window::WIDTH),
|
||||
windowed_height_(Defaults::Window::HEIGHT),
|
||||
max_zoom_(1.0F) {
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << '\n';
|
||||
return;
|
||||
}
|
||||
|
||||
calculateMaxWindowSize();
|
||||
|
||||
if (!initWindowAndGpu(&finestra_, gpu_renderer_, current_width_, current_height_, false)) {
|
||||
SDL_Quit();
|
||||
return;
|
||||
}
|
||||
|
||||
updateViewport();
|
||||
|
||||
std::cout << "SDL3 inicialitzat: " << current_width_ << "x" << current_height_
|
||||
<< " (logic: " << Defaults::Game::WIDTH << "x"
|
||||
<< Defaults::Game::HEIGHT << ")" << '\n';
|
||||
}
|
||||
|
||||
SDLManager::SDLManager(int width, int height, bool fullscreen)
|
||||
: finestra_(nullptr),
|
||||
SDLManager::SDLManager(int width, int height, bool fullscreen, Config::EngineConfig& cfg, std::function<void()> on_persist)
|
||||
: cfg_(&cfg),
|
||||
on_persist_(std::move(on_persist)),
|
||||
current_width_(width),
|
||||
current_height_(height),
|
||||
is_fullscreen_(fullscreen),
|
||||
max_width_(1920),
|
||||
max_height_(1080),
|
||||
zoom_factor_(static_cast<float>(width) / Defaults::Window::WIDTH),
|
||||
windowed_width_(width),
|
||||
windowed_height_(height),
|
||||
max_zoom_(1.0F) {
|
||||
windowed_height_(height) {
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << '\n';
|
||||
return;
|
||||
@@ -109,7 +79,7 @@ SDLManager::SDLManager(int width, int height, bool fullscreen)
|
||||
|
||||
calculateMaxWindowSize();
|
||||
|
||||
if (!initWindowAndGpu(&finestra_, gpu_renderer_, current_width_, current_height_, is_fullscreen_)) {
|
||||
if (!initWindowAndGpu(&finestra_, gpu_renderer_, current_width_, current_height_, is_fullscreen_, cfg_->rendering.vsync)) {
|
||||
SDL_Quit();
|
||||
return;
|
||||
}
|
||||
@@ -194,9 +164,9 @@ void SDLManager::applyZoom(float new_zoom) {
|
||||
windowed_width_ = new_width;
|
||||
windowed_height_ = new_height;
|
||||
|
||||
Options::window.width = new_width;
|
||||
Options::window.height = new_height;
|
||||
Options::window.zoom_factor = zoom_factor_;
|
||||
cfg_->window.width = new_width;
|
||||
cfg_->window.height = new_height;
|
||||
cfg_->window.zoom_factor = zoom_factor_;
|
||||
|
||||
std::cout << "Zoom: " << zoom_factor_ << "x ("
|
||||
<< new_width << "x" << new_height << ")" << '\n';
|
||||
@@ -216,9 +186,9 @@ void SDLManager::updateViewport() {
|
||||
offset_y = std::max(offset_y, 0);
|
||||
|
||||
gpu_renderer_.setViewport(static_cast<float>(offset_x),
|
||||
static_cast<float>(offset_y),
|
||||
static_cast<float>(scaled_width),
|
||||
static_cast<float>(scaled_height));
|
||||
static_cast<float>(offset_y),
|
||||
static_cast<float>(scaled_width),
|
||||
static_cast<float>(scaled_height));
|
||||
|
||||
std::cout << "Viewport: " << scaled_width << "x" << scaled_height
|
||||
<< " @ (" << offset_x << "," << offset_y << ") [scale=" << scale << "]"
|
||||
@@ -288,7 +258,7 @@ void SDLManager::toggleFullscreen() {
|
||||
<< windowed_width_ << "x" << windowed_height_ << ")" << '\n';
|
||||
}
|
||||
|
||||
Options::window.fullscreen = is_fullscreen_;
|
||||
cfg_->window.fullscreen = is_fullscreen_;
|
||||
Mouse::setForceHidden(is_fullscreen_);
|
||||
}
|
||||
|
||||
@@ -334,7 +304,9 @@ void SDLManager::present() {
|
||||
}
|
||||
|
||||
void SDLManager::toggleVSync() {
|
||||
Options::rendering.vsync = (Options::rendering.vsync == 1) ? 0 : 1;
|
||||
gpu_renderer_.setVSync(Options::rendering.vsync != 0);
|
||||
Options::saveToFile();
|
||||
cfg_->rendering.vsync = (cfg_->rendering.vsync == 1) ? 0 : 1;
|
||||
gpu_renderer_.setVSync(cfg_->rendering.vsync != 0);
|
||||
if (on_persist_) {
|
||||
on_persist_();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,61 +11,67 @@
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
#include "core/config/engine_config.hpp"
|
||||
#include "core/rendering/render_context.hpp"
|
||||
|
||||
class SDLManager {
|
||||
public:
|
||||
SDLManager(); // Constructor per defecte (usa Defaults::)
|
||||
SDLManager(int width, int height, bool fullscreen); // Constructor con configuración
|
||||
~SDLManager();
|
||||
public:
|
||||
// `cfg` ha de viure tant com el manager (el posseeix el Director).
|
||||
// `on_persist` es crida després de mutar la config (per exemple a
|
||||
// toggleVSync) per delegar la persistència en una capa externa
|
||||
// (game/Options::saveToFile), mantenint sdl_manager agnòstic.
|
||||
SDLManager(int width, int height, bool fullscreen, Config::EngineConfig& cfg, std::function<void()> on_persist = {});
|
||||
~SDLManager();
|
||||
|
||||
// No permetre còpia ni assignació
|
||||
SDLManager(const SDLManager&) = delete;
|
||||
auto operator=(const SDLManager&) -> SDLManager& = delete;
|
||||
// No permetre còpia ni assignació
|
||||
SDLManager(const SDLManager&) = delete;
|
||||
auto operator=(const SDLManager&) -> SDLManager& = delete;
|
||||
|
||||
// [NUEVO] Gestió de finestra dinàmica
|
||||
void increaseWindowSize(); // F2: +100px
|
||||
void decreaseWindowSize(); // F1: -100px
|
||||
void toggleFullscreen(); // F3
|
||||
void toggleVSync(); // F4
|
||||
auto handleWindowEvent(const SDL_Event& event) -> bool; // Per a SDL_EVENT_WINDOW_RESIZED
|
||||
// [NUEVO] Gestió de finestra dinàmica
|
||||
void increaseWindowSize(); // F2: +100px
|
||||
void decreaseWindowSize(); // F1: -100px
|
||||
void toggleFullscreen(); // F3
|
||||
void toggleVSync(); // F4
|
||||
auto handleWindowEvent(const SDL_Event& event) -> bool; // Per a SDL_EVENT_WINDOW_RESIZED
|
||||
|
||||
// Funciones principals (renderizado).
|
||||
// clear() devuelve false si la swapchain no está disponible (p.ej.
|
||||
// ventana minimizada). El caller debe saltarse draw+present ese frame.
|
||||
[[nodiscard]] auto clear(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0) -> bool;
|
||||
void present();
|
||||
// Funciones principals (renderizado).
|
||||
// clear() devuelve false si la swapchain no está disponible (p.ej.
|
||||
// ventana minimizada). El caller debe saltarse draw+present ese frame.
|
||||
[[nodiscard]] auto clear(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0) -> bool;
|
||||
void present();
|
||||
|
||||
// Getters
|
||||
auto getRenderer() -> Rendering::Renderer* { return &gpu_renderer_; }
|
||||
[[nodiscard]] auto getScaleFactor() const -> float { return zoom_factor_; }
|
||||
// Getters
|
||||
auto getRenderer() -> Rendering::Renderer* { return &gpu_renderer_; }
|
||||
[[nodiscard]] auto getScaleFactor() const -> float { return zoom_factor_; }
|
||||
|
||||
// [NUEVO] Actualitzar context de renderizado (factor de scale global)
|
||||
void updateRenderingContext() const;
|
||||
// [NUEVO] Actualitzar context de renderizado (factor de scale global)
|
||||
void updateRenderingContext() const;
|
||||
|
||||
private:
|
||||
SDL_Window* finestra_;
|
||||
Rendering::Renderer gpu_renderer_; // GpuFrameRenderer (SDL3 GPU)
|
||||
private:
|
||||
SDL_Window* finestra_{nullptr};
|
||||
Rendering::Renderer gpu_renderer_; // GpuFrameRenderer (SDL3 GPU)
|
||||
Config::EngineConfig* cfg_; // Propietat del Director, sobreviu al manager
|
||||
std::function<void()> on_persist_; // Opcional: persistència delegada
|
||||
|
||||
// [NUEVO] Estat de la finestra
|
||||
int current_width_; // Mida física actual
|
||||
int current_height_;
|
||||
bool is_fullscreen_;
|
||||
int max_width_; // Calculat des del display
|
||||
int max_height_;
|
||||
// [NUEVO] Estat de la finestra
|
||||
int current_width_; // Mida física actual
|
||||
int current_height_;
|
||||
bool is_fullscreen_;
|
||||
int max_width_{1920}; // Fallback si no es pot llegir del display
|
||||
int max_height_{1080};
|
||||
|
||||
// [ZOOM SYSTEM]
|
||||
float zoom_factor_; // Current zoom (0.5x to max_zoom_)
|
||||
int windowed_width_; // Saved size before fullscreen
|
||||
int windowed_height_; // Saved size before fullscreen
|
||||
float max_zoom_; // Maximum zoom (calculated from display)
|
||||
|
||||
// [NUEVO] Funciones internes
|
||||
void calculateMaxWindowSize(); // Llegir resolució del display
|
||||
void calculateMaxZoom(); // Calculate max zoom from display
|
||||
void applyZoom(float new_zoom); // Apply zoom and resize window
|
||||
void applyWindowSize(int width, int height); // Canviar mida + centrar
|
||||
void updateViewport(); // Configurar viewport con letterbox
|
||||
// [ZOOM SYSTEM]
|
||||
float zoom_factor_; // Current zoom (0.5x to max_zoom_)
|
||||
int windowed_width_; // Saved size before fullscreen
|
||||
int windowed_height_; // Saved size before fullscreen
|
||||
float max_zoom_{1.0F}; // Maximum zoom (calculated from display)
|
||||
|
||||
// [NUEVO] Funciones internes
|
||||
void calculateMaxWindowSize(); // Llegir resolució del display
|
||||
void calculateMaxZoom(); // Calculate max zoom from display
|
||||
void applyZoom(float new_zoom); // Apply zoom and resize window
|
||||
void applyWindowSize(int width, int height); // Canviar mida + centrar
|
||||
void updateViewport(); // Configurar viewport con letterbox
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user