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/defaults.hpp"
|
||||||
#include "core/input/mouse.hpp"
|
#include "core/input/mouse.hpp"
|
||||||
#include "core/rendering/coordinate_transform.hpp"
|
#include "core/rendering/coordinate_transform.hpp"
|
||||||
#include "game/options.hpp"
|
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
auto initWindowAndGpu(SDL_Window** out_window,
|
auto initWindowAndGpu(SDL_Window** out_window,
|
||||||
Rendering::Renderer& gpu_renderer,
|
Rendering::Renderer& gpu_renderer,
|
||||||
int width, int height, bool fullscreen) -> bool {
|
int width,
|
||||||
// Título estático estilo CCAE. El FPS y el estado de VSync los muestra
|
int height,
|
||||||
// el DebugOverlay (toggle F11), no la barra de título.
|
bool fullscreen,
|
||||||
const std::string TITLE = std::format("© 2026 {} — JailDesigner",
|
int initial_vsync) -> bool {
|
||||||
Project::LONG_NAME);
|
// 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;
|
SDL_WindowFlags flags = SDL_WINDOW_RESIZABLE;
|
||||||
if (fullscreen) {
|
if (fullscreen) {
|
||||||
flags = static_cast<SDL_WindowFlags>(flags | SDL_WINDOW_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
|
} // namespace
|
||||||
|
|
||||||
SDLManager::SDLManager()
|
SDLManager::SDLManager(int width, int height, bool fullscreen, Config::EngineConfig& cfg, std::function<void()> on_persist)
|
||||||
: finestra_(nullptr),
|
: cfg_(&cfg),
|
||||||
current_width_(Defaults::Window::WIDTH),
|
on_persist_(std::move(on_persist)),
|
||||||
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),
|
|
||||||
current_width_(width),
|
current_width_(width),
|
||||||
current_height_(height),
|
current_height_(height),
|
||||||
is_fullscreen_(fullscreen),
|
is_fullscreen_(fullscreen),
|
||||||
max_width_(1920),
|
|
||||||
max_height_(1080),
|
|
||||||
zoom_factor_(static_cast<float>(width) / Defaults::Window::WIDTH),
|
zoom_factor_(static_cast<float>(width) / Defaults::Window::WIDTH),
|
||||||
windowed_width_(width),
|
windowed_width_(width),
|
||||||
windowed_height_(height),
|
windowed_height_(height) {
|
||||||
max_zoom_(1.0F) {
|
|
||||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||||
std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << '\n';
|
std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << '\n';
|
||||||
return;
|
return;
|
||||||
@@ -109,7 +79,7 @@ SDLManager::SDLManager(int width, int height, bool fullscreen)
|
|||||||
|
|
||||||
calculateMaxWindowSize();
|
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();
|
SDL_Quit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -194,9 +164,9 @@ void SDLManager::applyZoom(float new_zoom) {
|
|||||||
windowed_width_ = new_width;
|
windowed_width_ = new_width;
|
||||||
windowed_height_ = new_height;
|
windowed_height_ = new_height;
|
||||||
|
|
||||||
Options::window.width = new_width;
|
cfg_->window.width = new_width;
|
||||||
Options::window.height = new_height;
|
cfg_->window.height = new_height;
|
||||||
Options::window.zoom_factor = zoom_factor_;
|
cfg_->window.zoom_factor = zoom_factor_;
|
||||||
|
|
||||||
std::cout << "Zoom: " << zoom_factor_ << "x ("
|
std::cout << "Zoom: " << zoom_factor_ << "x ("
|
||||||
<< new_width << "x" << new_height << ")" << '\n';
|
<< new_width << "x" << new_height << ")" << '\n';
|
||||||
@@ -216,9 +186,9 @@ void SDLManager::updateViewport() {
|
|||||||
offset_y = std::max(offset_y, 0);
|
offset_y = std::max(offset_y, 0);
|
||||||
|
|
||||||
gpu_renderer_.setViewport(static_cast<float>(offset_x),
|
gpu_renderer_.setViewport(static_cast<float>(offset_x),
|
||||||
static_cast<float>(offset_y),
|
static_cast<float>(offset_y),
|
||||||
static_cast<float>(scaled_width),
|
static_cast<float>(scaled_width),
|
||||||
static_cast<float>(scaled_height));
|
static_cast<float>(scaled_height));
|
||||||
|
|
||||||
std::cout << "Viewport: " << scaled_width << "x" << scaled_height
|
std::cout << "Viewport: " << scaled_width << "x" << scaled_height
|
||||||
<< " @ (" << offset_x << "," << offset_y << ") [scale=" << scale << "]"
|
<< " @ (" << offset_x << "," << offset_y << ") [scale=" << scale << "]"
|
||||||
@@ -288,7 +258,7 @@ void SDLManager::toggleFullscreen() {
|
|||||||
<< windowed_width_ << "x" << windowed_height_ << ")" << '\n';
|
<< windowed_width_ << "x" << windowed_height_ << ")" << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
Options::window.fullscreen = is_fullscreen_;
|
cfg_->window.fullscreen = is_fullscreen_;
|
||||||
Mouse::setForceHidden(is_fullscreen_);
|
Mouse::setForceHidden(is_fullscreen_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,7 +304,9 @@ void SDLManager::present() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SDLManager::toggleVSync() {
|
void SDLManager::toggleVSync() {
|
||||||
Options::rendering.vsync = (Options::rendering.vsync == 1) ? 0 : 1;
|
cfg_->rendering.vsync = (cfg_->rendering.vsync == 1) ? 0 : 1;
|
||||||
gpu_renderer_.setVSync(Options::rendering.vsync != 0);
|
gpu_renderer_.setVSync(cfg_->rendering.vsync != 0);
|
||||||
Options::saveToFile();
|
if (on_persist_) {
|
||||||
|
on_persist_();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,61 +11,67 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "core/config/engine_config.hpp"
|
||||||
#include "core/rendering/render_context.hpp"
|
#include "core/rendering/render_context.hpp"
|
||||||
|
|
||||||
class SDLManager {
|
class SDLManager {
|
||||||
public:
|
public:
|
||||||
SDLManager(); // Constructor per defecte (usa Defaults::)
|
// `cfg` ha de viure tant com el manager (el posseeix el Director).
|
||||||
SDLManager(int width, int height, bool fullscreen); // Constructor con configuración
|
// `on_persist` es crida després de mutar la config (per exemple a
|
||||||
~SDLManager();
|
// 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ó
|
// No permetre còpia ni assignació
|
||||||
SDLManager(const SDLManager&) = delete;
|
SDLManager(const SDLManager&) = delete;
|
||||||
auto operator=(const SDLManager&) -> SDLManager& = delete;
|
auto operator=(const SDLManager&) -> SDLManager& = delete;
|
||||||
|
|
||||||
// [NUEVO] Gestió de finestra dinàmica
|
// [NUEVO] Gestió de finestra dinàmica
|
||||||
void increaseWindowSize(); // F2: +100px
|
void increaseWindowSize(); // F2: +100px
|
||||||
void decreaseWindowSize(); // F1: -100px
|
void decreaseWindowSize(); // F1: -100px
|
||||||
void toggleFullscreen(); // F3
|
void toggleFullscreen(); // F3
|
||||||
void toggleVSync(); // F4
|
void toggleVSync(); // F4
|
||||||
auto handleWindowEvent(const SDL_Event& event) -> bool; // Per a SDL_EVENT_WINDOW_RESIZED
|
auto handleWindowEvent(const SDL_Event& event) -> bool; // Per a SDL_EVENT_WINDOW_RESIZED
|
||||||
|
|
||||||
// Funciones principals (renderizado).
|
// Funciones principals (renderizado).
|
||||||
// clear() devuelve false si la swapchain no está disponible (p.ej.
|
// clear() devuelve false si la swapchain no está disponible (p.ej.
|
||||||
// ventana minimizada). El caller debe saltarse draw+present ese frame.
|
// 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;
|
[[nodiscard]] auto clear(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0) -> bool;
|
||||||
void present();
|
void present();
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
auto getRenderer() -> Rendering::Renderer* { return &gpu_renderer_; }
|
auto getRenderer() -> Rendering::Renderer* { return &gpu_renderer_; }
|
||||||
[[nodiscard]] auto getScaleFactor() const -> float { return zoom_factor_; }
|
[[nodiscard]] auto getScaleFactor() const -> float { return zoom_factor_; }
|
||||||
|
|
||||||
// [NUEVO] Actualitzar context de renderizado (factor de scale global)
|
// [NUEVO] Actualitzar context de renderizado (factor de scale global)
|
||||||
void updateRenderingContext() const;
|
void updateRenderingContext() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SDL_Window* finestra_;
|
SDL_Window* finestra_{nullptr};
|
||||||
Rendering::Renderer gpu_renderer_; // GpuFrameRenderer (SDL3 GPU)
|
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
|
// [NUEVO] Estat de la finestra
|
||||||
int current_width_; // Mida física actual
|
int current_width_; // Mida física actual
|
||||||
int current_height_;
|
int current_height_;
|
||||||
bool is_fullscreen_;
|
bool is_fullscreen_;
|
||||||
int max_width_; // Calculat des del display
|
int max_width_{1920}; // Fallback si no es pot llegir del display
|
||||||
int max_height_;
|
int max_height_{1080};
|
||||||
|
|
||||||
// [ZOOM SYSTEM]
|
// [ZOOM SYSTEM]
|
||||||
float zoom_factor_; // Current zoom (0.5x to max_zoom_)
|
float zoom_factor_; // Current zoom (0.5x to max_zoom_)
|
||||||
int windowed_width_; // Saved size before fullscreen
|
int windowed_width_; // Saved size before fullscreen
|
||||||
int windowed_height_; // Saved size before fullscreen
|
int windowed_height_; // Saved size before fullscreen
|
||||||
float max_zoom_; // Maximum zoom (calculated from display)
|
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
|
|
||||||
|
|
||||||
|
// [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
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -220,8 +220,10 @@ auto Director::run() -> int {
|
|||||||
int initial_height = static_cast<int>(std::round(
|
int initial_height = static_cast<int>(std::round(
|
||||||
Defaults::Window::HEIGHT * Options::window.zoom_factor));
|
Defaults::Window::HEIGHT * Options::window.zoom_factor));
|
||||||
|
|
||||||
// Crear gestor SDL con configuración de Options
|
// Crear gestor SDL con configuración de Options.
|
||||||
SDLManager sdl(initial_width, initial_height, Options::window.fullscreen);
|
// Inyectamos la engine_config + un callback per persistir-la quan
|
||||||
|
// toggleVSync (F4) muti vsync, sense que sdl_manager conegui Options.
|
||||||
|
SDLManager sdl(initial_width, initial_height, Options::window.fullscreen, Options::engine_config, [] { Options::saveToFile(); });
|
||||||
|
|
||||||
// CRÍTIC: Forçar ocultació del cursor DESPRÉS de toda la inicialización SDL
|
// CRÍTIC: Forçar ocultació del cursor DESPRÉS de toda la inicialización SDL
|
||||||
// Això evita que SDL mostre el cursor automàticament durante la creació de la finestra
|
// Això evita que SDL mostre el cursor automàticament durante la creació de la finestra
|
||||||
|
|||||||
Reference in New Issue
Block a user