ja guarda la configuracio
This commit is contained in:
@@ -3,210 +3,287 @@
|
||||
|
||||
#include "sdl_manager.hpp"
|
||||
#include "core/defaults.hpp"
|
||||
#include "game/options.hpp"
|
||||
#include "project.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <format>
|
||||
#include <iostream>
|
||||
|
||||
SDLManager::SDLManager()
|
||||
: finestra_(nullptr)
|
||||
, renderer_(nullptr)
|
||||
, current_width_(Defaults::Window::WIDTH)
|
||||
, current_height_(Defaults::Window::HEIGHT)
|
||||
, is_fullscreen_(false)
|
||||
, max_width_(1920)
|
||||
, max_height_(1080)
|
||||
{
|
||||
// Inicialitzar SDL3
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << std::endl;
|
||||
return;
|
||||
}
|
||||
: finestra_(nullptr), renderer_(nullptr),
|
||||
current_width_(Defaults::Window::WIDTH),
|
||||
current_height_(Defaults::Window::HEIGHT), is_fullscreen_(false),
|
||||
max_width_(1920), max_height_(1080) {
|
||||
// Inicialitzar SDL3
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Calcular mida màxima des del display
|
||||
calculateMaxWindowSize();
|
||||
// Calcular mida màxima des del display
|
||||
calculateMaxWindowSize();
|
||||
|
||||
// Construir títol dinàmic igual que en pollo
|
||||
std::string window_title = std::format("{} v{} ({})",
|
||||
Project::LONG_NAME,
|
||||
Project::VERSION,
|
||||
Project::COPYRIGHT
|
||||
);
|
||||
// Construir títol dinàmic igual que en pollo
|
||||
std::string window_title = std::format("{} v{} ({})", Project::LONG_NAME,
|
||||
Project::VERSION, Project::COPYRIGHT);
|
||||
|
||||
// Crear finestra CENTRADA (SDL ho fa automàticament amb CENTERED)
|
||||
finestra_ = SDL_CreateWindow(
|
||||
window_title.c_str(),
|
||||
current_width_,
|
||||
current_height_,
|
||||
SDL_WINDOW_RESIZABLE // Permetre resize manual també
|
||||
);
|
||||
// Crear finestra CENTRADA (SDL ho fa automàticament amb CENTERED)
|
||||
finestra_ =
|
||||
SDL_CreateWindow(window_title.c_str(), current_width_, current_height_,
|
||||
SDL_WINDOW_RESIZABLE // Permetre resize manual també
|
||||
);
|
||||
|
||||
if (!finestra_) {
|
||||
std::cerr << "Error creant finestra: " << SDL_GetError() << std::endl;
|
||||
SDL_Quit();
|
||||
return;
|
||||
}
|
||||
if (!finestra_) {
|
||||
std::cerr << "Error creant finestra: " << SDL_GetError() << std::endl;
|
||||
SDL_Quit();
|
||||
return;
|
||||
}
|
||||
|
||||
// IMPORTANT: Centrar explícitament la finestra
|
||||
SDL_SetWindowPosition(finestra_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
// IMPORTANT: Centrar explícitament la finestra
|
||||
SDL_SetWindowPosition(finestra_, SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED);
|
||||
|
||||
// Crear renderer amb acceleració
|
||||
renderer_ = SDL_CreateRenderer(finestra_, nullptr);
|
||||
// Crear renderer amb acceleració
|
||||
renderer_ = SDL_CreateRenderer(finestra_, nullptr);
|
||||
|
||||
if (!renderer_) {
|
||||
std::cerr << "Error creant renderer: " << SDL_GetError() << std::endl;
|
||||
SDL_DestroyWindow(finestra_);
|
||||
SDL_Quit();
|
||||
return;
|
||||
}
|
||||
if (!renderer_) {
|
||||
std::cerr << "Error creant renderer: " << SDL_GetError() << std::endl;
|
||||
SDL_DestroyWindow(finestra_);
|
||||
SDL_Quit();
|
||||
return;
|
||||
}
|
||||
|
||||
// CRÍTIC: Configurar viewport scaling
|
||||
updateLogicalPresentation();
|
||||
// CRÍTIC: Configurar viewport scaling
|
||||
updateLogicalPresentation();
|
||||
|
||||
std::cout << "SDL3 inicialitzat: " << current_width_ << "x" << current_height_
|
||||
<< " (logic: " << Defaults::Game::WIDTH << "x" << Defaults::Game::HEIGHT << ")" << std::endl;
|
||||
std::cout << "SDL3 inicialitzat: " << current_width_ << "x" << current_height_
|
||||
<< " (logic: " << Defaults::Game::WIDTH << "x"
|
||||
<< Defaults::Game::HEIGHT << ")" << std::endl;
|
||||
}
|
||||
|
||||
// Constructor amb configuració
|
||||
SDLManager::SDLManager(int width, int height, bool fullscreen)
|
||||
: finestra_(nullptr), renderer_(nullptr), current_width_(width),
|
||||
current_height_(height), is_fullscreen_(fullscreen), max_width_(1920),
|
||||
max_height_(1080) {
|
||||
// Inicialitzar SDL3
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Calcular mida màxima des del display
|
||||
calculateMaxWindowSize();
|
||||
|
||||
// Construir títol dinàmic
|
||||
std::string window_title = std::format("{} v{} ({})", Project::LONG_NAME,
|
||||
Project::VERSION, Project::COPYRIGHT);
|
||||
|
||||
// Configurar flags de la finestra
|
||||
SDL_WindowFlags flags = SDL_WINDOW_RESIZABLE;
|
||||
if (is_fullscreen_) {
|
||||
flags = static_cast<SDL_WindowFlags>(flags | SDL_WINDOW_FULLSCREEN);
|
||||
}
|
||||
|
||||
// Crear finestra
|
||||
finestra_ = SDL_CreateWindow(window_title.c_str(), current_width_,
|
||||
current_height_, flags);
|
||||
|
||||
if (!finestra_) {
|
||||
std::cerr << "Error creant finestra: " << SDL_GetError() << std::endl;
|
||||
SDL_Quit();
|
||||
return;
|
||||
}
|
||||
|
||||
// Centrar explícitament la finestra (si no és fullscreen)
|
||||
if (!is_fullscreen_) {
|
||||
SDL_SetWindowPosition(finestra_, SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED);
|
||||
}
|
||||
|
||||
// Crear renderer amb acceleració
|
||||
renderer_ = SDL_CreateRenderer(finestra_, nullptr);
|
||||
|
||||
if (!renderer_) {
|
||||
std::cerr << "Error creant renderer: " << SDL_GetError() << std::endl;
|
||||
SDL_DestroyWindow(finestra_);
|
||||
SDL_Quit();
|
||||
return;
|
||||
}
|
||||
|
||||
// Configurar viewport scaling
|
||||
updateLogicalPresentation();
|
||||
|
||||
std::cout << "SDL3 inicialitzat: " << current_width_ << "x" << current_height_
|
||||
<< " (logic: " << Defaults::Game::WIDTH << "x"
|
||||
<< Defaults::Game::HEIGHT << ")";
|
||||
if (is_fullscreen_) {
|
||||
std::cout << " [FULLSCREEN]";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
SDLManager::~SDLManager() {
|
||||
if (renderer_) {
|
||||
SDL_DestroyRenderer(renderer_);
|
||||
renderer_ = nullptr;
|
||||
}
|
||||
if (renderer_) {
|
||||
SDL_DestroyRenderer(renderer_);
|
||||
renderer_ = nullptr;
|
||||
}
|
||||
|
||||
if (finestra_) {
|
||||
SDL_DestroyWindow(finestra_);
|
||||
finestra_ = nullptr;
|
||||
}
|
||||
if (finestra_) {
|
||||
SDL_DestroyWindow(finestra_);
|
||||
finestra_ = nullptr;
|
||||
}
|
||||
|
||||
SDL_Quit();
|
||||
std::cout << "SDL3 netejat correctament" << std::endl;
|
||||
SDL_Quit();
|
||||
std::cout << "SDL3 netejat correctament" << std::endl;
|
||||
}
|
||||
|
||||
void SDLManager::calculateMaxWindowSize() {
|
||||
SDL_DisplayID display = SDL_GetPrimaryDisplay();
|
||||
const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(display);
|
||||
SDL_DisplayID display = SDL_GetPrimaryDisplay();
|
||||
const SDL_DisplayMode *mode = SDL_GetCurrentDisplayMode(display);
|
||||
|
||||
if (mode) {
|
||||
// Deixar marge de 100px per a decoracions de l'OS
|
||||
max_width_ = mode->w - 100;
|
||||
max_height_ = mode->h - 100;
|
||||
std::cout << "Display detectat: " << mode->w << "x" << mode->h
|
||||
<< " (max finestra: " << max_width_ << "x" << max_height_ << ")" << std::endl;
|
||||
} else {
|
||||
// Fallback conservador
|
||||
max_width_ = 1920;
|
||||
max_height_ = 1080;
|
||||
std::cerr << "No s'ha pogut detectar el display, usant fallback: "
|
||||
<< max_width_ << "x" << max_height_ << std::endl;
|
||||
}
|
||||
if (mode) {
|
||||
// Deixar marge de 100px per a decoracions de l'OS
|
||||
max_width_ = mode->w - 100;
|
||||
max_height_ = mode->h - 100;
|
||||
std::cout << "Display detectat: " << mode->w << "x" << mode->h
|
||||
<< " (max finestra: " << max_width_ << "x" << max_height_ << ")"
|
||||
<< std::endl;
|
||||
} else {
|
||||
// Fallback conservador
|
||||
max_width_ = 1920;
|
||||
max_height_ = 1080;
|
||||
std::cerr << "No s'ha pogut detectar el display, usant fallback: "
|
||||
<< max_width_ << "x" << max_height_ << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void SDLManager::updateLogicalPresentation() {
|
||||
// AIXÒ ÉS LA MÀGIA: El joc SEMPRE dibuixa en 640x480,
|
||||
// SDL escala automàticament a la mida física de la finestra
|
||||
SDL_SetRenderLogicalPresentation(
|
||||
renderer_,
|
||||
Defaults::Game::WIDTH, // 640 (lògic)
|
||||
Defaults::Game::HEIGHT, // 480 (lògic)
|
||||
SDL_LOGICAL_PRESENTATION_LETTERBOX // Mantenir aspect ratio 4:3
|
||||
);
|
||||
// AIXÒ ÉS LA MÀGIA: El joc SEMPRE dibuixa en 640x480,
|
||||
// SDL escala automàticament a la mida física de la finestra
|
||||
SDL_SetRenderLogicalPresentation(
|
||||
renderer_,
|
||||
Defaults::Game::WIDTH, // 640 (lògic)
|
||||
Defaults::Game::HEIGHT, // 480 (lògic)
|
||||
SDL_LOGICAL_PRESENTATION_LETTERBOX // Mantenir aspect ratio 4:3
|
||||
);
|
||||
}
|
||||
|
||||
void SDLManager::increaseWindowSize() {
|
||||
if (is_fullscreen_) return; // No operar en fullscreen
|
||||
if (is_fullscreen_)
|
||||
return; // No operar en fullscreen
|
||||
|
||||
int new_width = current_width_ + Defaults::Window::SIZE_INCREMENT;
|
||||
int new_height = current_height_ + Defaults::Window::SIZE_INCREMENT;
|
||||
int new_width = current_width_ + Defaults::Window::SIZE_INCREMENT;
|
||||
int new_height = current_height_ + Defaults::Window::SIZE_INCREMENT;
|
||||
|
||||
// Clamp a màxim
|
||||
new_width = std::min(new_width, max_width_);
|
||||
new_height = std::min(new_height, max_height_);
|
||||
// Clamp a màxim
|
||||
new_width = std::min(new_width, max_width_);
|
||||
new_height = std::min(new_height, max_height_);
|
||||
|
||||
if (new_width != current_width_ || new_height != current_height_) {
|
||||
applyWindowSize(new_width, new_height);
|
||||
std::cout << "F2: Finestra augmentada a " << new_width << "x" << new_height << std::endl;
|
||||
}
|
||||
if (new_width != current_width_ || new_height != current_height_) {
|
||||
applyWindowSize(new_width, new_height);
|
||||
|
||||
// Persistir canvis a Options (es guardarà a config.yaml al tancar)
|
||||
Options::window.width = current_width_;
|
||||
Options::window.height = current_height_;
|
||||
|
||||
std::cout << "F2: Finestra augmentada a " << new_width << "x" << new_height
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void SDLManager::decreaseWindowSize() {
|
||||
if (is_fullscreen_) return;
|
||||
if (is_fullscreen_)
|
||||
return;
|
||||
|
||||
int new_width = current_width_ - Defaults::Window::SIZE_INCREMENT;
|
||||
int new_height = current_height_ - Defaults::Window::SIZE_INCREMENT;
|
||||
int new_width = current_width_ - Defaults::Window::SIZE_INCREMENT;
|
||||
int new_height = current_height_ - Defaults::Window::SIZE_INCREMENT;
|
||||
|
||||
// Clamp a mínim
|
||||
new_width = std::max(new_width, Defaults::Window::MIN_WIDTH);
|
||||
new_height = std::max(new_height, Defaults::Window::MIN_HEIGHT);
|
||||
// Clamp a mínim
|
||||
new_width = std::max(new_width, Defaults::Window::MIN_WIDTH);
|
||||
new_height = std::max(new_height, Defaults::Window::MIN_HEIGHT);
|
||||
|
||||
if (new_width != current_width_ || new_height != current_height_) {
|
||||
applyWindowSize(new_width, new_height);
|
||||
std::cout << "F1: Finestra reduïda a " << new_width << "x" << new_height << std::endl;
|
||||
}
|
||||
if (new_width != current_width_ || new_height != current_height_) {
|
||||
applyWindowSize(new_width, new_height);
|
||||
|
||||
// Persistir canvis a Options (es guardarà a config.yaml al tancar)
|
||||
Options::window.width = current_width_;
|
||||
Options::window.height = current_height_;
|
||||
|
||||
std::cout << "F1: Finestra reduïda a " << new_width << "x" << new_height
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void SDLManager::applyWindowSize(int new_width, int new_height) {
|
||||
// Obtenir posició actual ABANS del resize
|
||||
int old_x, old_y;
|
||||
SDL_GetWindowPosition(finestra_, &old_x, &old_y);
|
||||
// Obtenir posició actual ABANS del resize
|
||||
int old_x, old_y;
|
||||
SDL_GetWindowPosition(finestra_, &old_x, &old_y);
|
||||
|
||||
int old_width = current_width_;
|
||||
int old_height = current_height_;
|
||||
int old_width = current_width_;
|
||||
int old_height = current_height_;
|
||||
|
||||
// Actualitzar mida
|
||||
SDL_SetWindowSize(finestra_, new_width, new_height);
|
||||
current_width_ = new_width;
|
||||
current_height_ = new_height;
|
||||
// Actualitzar mida
|
||||
SDL_SetWindowSize(finestra_, new_width, new_height);
|
||||
current_width_ = new_width;
|
||||
current_height_ = new_height;
|
||||
|
||||
// CENTRADO INTEL·LIGENT (algoritme de pollo)
|
||||
// Calcular nova posició per mantenir la finestra centrada sobre si mateixa
|
||||
int delta_width = old_width - new_width;
|
||||
int delta_height = old_height - new_height;
|
||||
// CENTRADO INTEL·LIGENT (algoritme de pollo)
|
||||
// Calcular nova posició per mantenir la finestra centrada sobre si mateixa
|
||||
int delta_width = old_width - new_width;
|
||||
int delta_height = old_height - new_height;
|
||||
|
||||
int new_x = old_x + (delta_width / 2);
|
||||
int new_y = old_y + (delta_height / 2);
|
||||
int new_x = old_x + (delta_width / 2);
|
||||
int new_y = old_y + (delta_height / 2);
|
||||
|
||||
// Evitar que la finestra surti de la pantalla
|
||||
constexpr int TITLEBAR_HEIGHT = 35; // Alçada aproximada de la barra de títol
|
||||
new_x = std::max(new_x, 0);
|
||||
new_y = std::max(new_y, TITLEBAR_HEIGHT);
|
||||
// Evitar que la finestra surti de la pantalla
|
||||
constexpr int TITLEBAR_HEIGHT = 35; // Alçada aproximada de la barra de títol
|
||||
new_x = std::max(new_x, 0);
|
||||
new_y = std::max(new_y, TITLEBAR_HEIGHT);
|
||||
|
||||
SDL_SetWindowPosition(finestra_, new_x, new_y);
|
||||
SDL_SetWindowPosition(finestra_, new_x, new_y);
|
||||
|
||||
// NO cal actualitzar el logical presentation aquí,
|
||||
// SDL ho maneja automàticament
|
||||
// NO cal actualitzar el logical presentation aquí,
|
||||
// SDL ho maneja automàticament
|
||||
}
|
||||
|
||||
void SDLManager::toggleFullscreen() {
|
||||
is_fullscreen_ = !is_fullscreen_;
|
||||
SDL_SetWindowFullscreen(finestra_, is_fullscreen_);
|
||||
is_fullscreen_ = !is_fullscreen_;
|
||||
SDL_SetWindowFullscreen(finestra_, is_fullscreen_);
|
||||
|
||||
std::cout << "F3: Fullscreen " << (is_fullscreen_ ? "activat" : "desactivat") << std::endl;
|
||||
// Persistir canvis a Options (es guardarà a config.yaml al tancar)
|
||||
Options::window.fullscreen = is_fullscreen_;
|
||||
|
||||
// En fullscreen, SDL gestiona tot automàticament
|
||||
// En sortir, restaura la mida anterior
|
||||
std::cout << "F3: Fullscreen " << (is_fullscreen_ ? "activat" : "desactivat")
|
||||
<< std::endl;
|
||||
|
||||
// En fullscreen, SDL gestiona tot automàticament
|
||||
// En sortir, restaura la mida anterior
|
||||
}
|
||||
|
||||
bool SDLManager::handleWindowEvent(const SDL_Event& event) {
|
||||
if (event.type == SDL_EVENT_WINDOW_RESIZED) {
|
||||
// Usuari ha redimensionat manualment (arrossegar vora)
|
||||
// Actualitzar el nostre tracking
|
||||
SDL_GetWindowSize(finestra_, ¤t_width_, ¤t_height_);
|
||||
std::cout << "Finestra redimensionada manualment a "
|
||||
<< current_width_ << "x" << current_height_ << std::endl;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool SDLManager::handleWindowEvent(const SDL_Event &event) {
|
||||
if (event.type == SDL_EVENT_WINDOW_RESIZED) {
|
||||
// Usuari ha redimensionat manualment (arrossegar vora)
|
||||
// Actualitzar el nostre tracking
|
||||
SDL_GetWindowSize(finestra_, ¤t_width_, ¤t_height_);
|
||||
std::cout << "Finestra redimensionada manualment a " << current_width_
|
||||
<< "x" << current_height_ << std::endl;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SDLManager::neteja(uint8_t r, uint8_t g, uint8_t b) {
|
||||
if (!renderer_) return;
|
||||
if (!renderer_)
|
||||
return;
|
||||
|
||||
SDL_SetRenderDrawColor(renderer_, r, g, b, 255);
|
||||
SDL_RenderClear(renderer_);
|
||||
SDL_SetRenderDrawColor(renderer_, r, g, b, 255);
|
||||
SDL_RenderClear(renderer_);
|
||||
}
|
||||
|
||||
void SDLManager::presenta() {
|
||||
if (!renderer_) return;
|
||||
if (!renderer_)
|
||||
return;
|
||||
|
||||
SDL_RenderPresent(renderer_);
|
||||
SDL_RenderPresent(renderer_);
|
||||
}
|
||||
|
||||
@@ -9,41 +9,44 @@
|
||||
|
||||
class SDLManager {
|
||||
public:
|
||||
SDLManager();
|
||||
~SDLManager();
|
||||
SDLManager(); // Constructor per defecte (usa Defaults::)
|
||||
SDLManager(int width, int height,
|
||||
bool fullscreen); // Constructor amb configuració
|
||||
~SDLManager();
|
||||
|
||||
// No permetre còpia ni assignació
|
||||
SDLManager(const SDLManager&) = delete;
|
||||
SDLManager& operator=(const SDLManager&) = delete;
|
||||
// No permetre còpia ni assignació
|
||||
SDLManager(const SDLManager &) = delete;
|
||||
SDLManager &operator=(const SDLManager &) = delete;
|
||||
|
||||
// [NUEVO] Gestió de finestra dinàmica
|
||||
void increaseWindowSize(); // F2: +100px
|
||||
void decreaseWindowSize(); // F1: -100px
|
||||
void toggleFullscreen(); // F3
|
||||
bool handleWindowEvent(const SDL_Event& event); // Per a SDL_EVENT_WINDOW_RESIZED
|
||||
// [NUEVO] Gestió de finestra dinàmica
|
||||
void increaseWindowSize(); // F2: +100px
|
||||
void decreaseWindowSize(); // F1: -100px
|
||||
void toggleFullscreen(); // F3
|
||||
bool
|
||||
handleWindowEvent(const SDL_Event &event); // Per a SDL_EVENT_WINDOW_RESIZED
|
||||
|
||||
// Funcions principals (renderitzat)
|
||||
void neteja(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0);
|
||||
void presenta();
|
||||
// Funcions principals (renderitzat)
|
||||
void neteja(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0);
|
||||
void presenta();
|
||||
|
||||
// Getters
|
||||
SDL_Renderer* obte_renderer() { return renderer_; }
|
||||
// Getters
|
||||
SDL_Renderer *obte_renderer() { return renderer_; }
|
||||
|
||||
private:
|
||||
SDL_Window* finestra_;
|
||||
SDL_Renderer* renderer_;
|
||||
SDL_Window *finestra_;
|
||||
SDL_Renderer *renderer_;
|
||||
|
||||
// [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_; // Calculat des del display
|
||||
int max_height_;
|
||||
|
||||
// [NUEVO] Funcions internes
|
||||
void calculateMaxWindowSize(); // Llegir resolució del display
|
||||
void applyWindowSize(int width, int height); // Canviar mida + centrar
|
||||
void updateLogicalPresentation(); // Actualitzar viewport
|
||||
// [NUEVO] Funcions internes
|
||||
void calculateMaxWindowSize(); // Llegir resolució del display
|
||||
void applyWindowSize(int width, int height); // Canviar mida + centrar
|
||||
void updateLogicalPresentation(); // Actualitzar viewport
|
||||
};
|
||||
|
||||
#endif // SDL_MANAGER_HPP
|
||||
|
||||
Reference in New Issue
Block a user