Config.yaml + Screen::Config desacoblat via Options (v0.3.0)

This commit is contained in:
JailDesigner committed 2026-04-18 21:38:40 +02:00
1 parent de5a670fdb
commit 0348acb0eb
8 files changed
+335 -16

No files matched your search

+35 -14
View File
@@ -8,7 +8,6 @@
#include <cstdlib>
#include <ranges>
#include "utils/defaults.hpp"
#include "utils/defines.hpp"
namespace {
@@ -48,12 +47,41 @@ Screen::Screen()
std::fprintf(stderr, "SDL_InitSubSystem(VIDEO) failed: %s\n", SDL_GetError());
std::exit(EXIT_FAILURE);
}
// Els recursos SDL (finestra, renderer, textura) es creen a configure().
}
const int WIN_W = GameCanvas::WIDTH * Defaults::Window::ZOOM;
const int WIN_H = GameCanvas::HEIGHT * Defaults::Window::ZOOM;
Screen::~Screen() {
destroySdl();
SDL_QuitSubSystem(SDL_INIT_VIDEO);
}
void Screen::configure(const Config& config) {
destroySdl();
config_ = config;
createSdl();
}
void Screen::destroySdl() {
if (game_texture_ != nullptr) {
SDL_DestroyTexture(game_texture_);
game_texture_ = nullptr;
}
if (renderer_ != nullptr) {
SDL_DestroyRenderer(renderer_);
renderer_ = nullptr;
}
if (window_ != nullptr) {
SDL_DestroyWindow(window_);
window_ = nullptr;
}
}
void Screen::createSdl() {
const int WIN_W = GameCanvas::WIDTH * config_.zoom;
const int WIN_H = GameCanvas::HEIGHT * config_.zoom;
Uint32 win_flags = SDL_WINDOW_RESIZABLE;
if (Defaults::Window::FULLSCREEN) { win_flags |= SDL_WINDOW_FULLSCREEN; }
if (config_.fullscreen) { win_flags |= SDL_WINDOW_FULLSCREEN; }
window_ = SDL_CreateWindow(Texts::WINDOW_TITLE, WIN_W, WIN_H, win_flags);
if (window_ == nullptr) {
@@ -67,8 +95,8 @@ Screen::Screen()
std::exit(EXIT_FAILURE);
}
SDL_SetRenderVSync(renderer_, Defaults::Video::VSYNC ? 1 : 0);
SDL_SetRenderLogicalPresentation(renderer_, GameCanvas::WIDTH, GameCanvas::HEIGHT, toSdlPresentation(Defaults::Video::SCALING_MODE));
SDL_SetRenderVSync(renderer_, config_.vsync ? 1 : 0);
SDL_SetRenderLogicalPresentation(renderer_, GameCanvas::WIDTH, GameCanvas::HEIGHT, toSdlPresentation(config_.scaling_mode));
// STREAMING: el framebuffer ARGB del joc s'actualitza per CPU cada frame
// i s'envia a la GPU via SDL_UpdateTexture en present().
@@ -77,14 +105,7 @@ Screen::Screen()
std::fprintf(stderr, "SDL_CreateTexture failed: %s\n", SDL_GetError());
std::exit(EXIT_FAILURE);
}
SDL_SetTextureScaleMode(game_texture_, toSdlScaleMode(Defaults::Video::TEXTURE_FILTER));
}
Screen::~Screen() {
if (game_texture_ != nullptr) { SDL_DestroyTexture(game_texture_); }
if (renderer_ != nullptr) { SDL_DestroyRenderer(renderer_); }
if (window_ != nullptr) { SDL_DestroyWindow(window_); }
SDL_QuitSubSystem(SDL_INIT_VIDEO);
SDL_SetTextureScaleMode(game_texture_, toSdlScaleMode(config_.texture_filter));
}
void Screen::clear(std::uint8_t r, std::uint8_t g, std::uint8_t b) {
+21
View File
@@ -5,8 +5,20 @@
#include <cstdint>
#include <vector>
#include "utils/defaults.hpp"
class Screen {
public:
// Configuració typada de Screen. L'omple el Director des d'Options,
// de manera que Screen no coneix YAML ni la capa Options directament.
struct Config {
int zoom{Defaults::Window::ZOOM};
bool fullscreen{Defaults::Window::FULLSCREEN};
bool vsync{Defaults::Video::VSYNC};
Defaults::ScalingMode scaling_mode{Defaults::Video::SCALING_MODE};
Defaults::TextureFilter texture_filter{Defaults::Video::TEXTURE_FILTER};
};
// Meyers singleton: la destrucció ocorre durant la termianció estàtica
// (LIFO respecte a Resource::Cache). El SDL_Quit s'ha de registrar via
// std::atexit ABANS de la primera crida a get(); així Screen::~Screen
@@ -18,6 +30,10 @@ class Screen {
auto operator=(const Screen&) -> Screen& = delete;
auto operator=(Screen&&) -> Screen& = delete;
// Crea (o recrea) finestra, renderer i textura a partir de la config.
// Imprescindible cridar-lo abans de qualsevol clear()/present().
void configure(const Config& config);
void clear(std::uint8_t r = 0, std::uint8_t g = 0, std::uint8_t b = 0);
void present();
@@ -30,6 +46,11 @@ class Screen {
Screen();
~Screen();
void destroySdl();
void createSdl();
Config config_{};
SDL_Window* window_{nullptr};
SDL_Renderer* renderer_{nullptr};
SDL_Texture* game_texture_{nullptr};
+33 -1
View File
@@ -5,6 +5,8 @@
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <filesystem>
#include <iostream>
#include <memory>
#include <utility>
@@ -12,6 +14,7 @@
#include "core/resources/resource_cache.hpp"
#include "core/scene/scene.hpp"
#include "core/system/event_buffer.hpp"
#include "game/options.hpp"
#include "game/scenes/game_scene.hpp"
Director::Director() {
@@ -26,10 +29,18 @@ Director::Director() {
// amb SDL ja apagat → caos de destrucció clàssic.
std::atexit(+[] { SDL_Quit(); });
// Prepara la carpeta de sistema (~/.config/jailgames/aee_2026/) i carrega
// les opcions; si no existeix config.yaml el crea amb els defaults.
createSystemFolder();
Options::setConfigFile(system_folder_ + "config.yaml");
if (!Options::loadFromFile()) {
std::cerr << "Director: no s'ha pogut carregar ni desar config.yaml a " << system_folder_ << '\n';
}
// Forcem la construcció dels singletons en l'ordre desitjat: primer
// Screen (necessari per a renderitzar), després Cache. La destrucció
// estàtica anirà LIFO: Cache primer, Screen últim.
(void)Screen::get();
Screen::get().configure(Options::buildScreenConfig());
(void)Resource::Cache::get();
current_scene_ = std::make_unique<GameScene>();
@@ -41,6 +52,27 @@ Director::~Director() {
// SDL_Quit corre via atexit; els singletons via destrucció estàtica.
}
void Director::createSystemFolder() {
// Volem la config a $XDG_CONFIG_HOME/jailgames/aee_2026/ (defecte
// ~/.config/jailgames/aee_2026/). SDL_GetPrefPath apunta a XDG_DATA_HOME
// (.local/share), que és el lloc per a dades, no per a configuració.
const char* xdg = std::getenv("XDG_CONFIG_HOME");
std::string base;
if (xdg != nullptr && *xdg != '\0') {
base = xdg;
} else {
const char* home = std::getenv("HOME");
base = (home != nullptr) ? std::string(home) + "/.config" : ".";
}
system_folder_ = base + "/jailgames/aee_2026/";
std::error_code error;
std::filesystem::create_directories(system_folder_, error);
if (error) {
std::cerr << "Director: no s'ha pogut crear " << system_folder_ << ": " << error.message() << '\n';
}
}
void Director::processEvents() {
const bool QUIT_REQUESTED = std::ranges::any_of(
EventBuffer::events,
+3
View File
@@ -4,6 +4,7 @@
#include <cstdint>
#include <memory>
#include <string>
class Scene;
@@ -15,9 +16,11 @@ class Director {
auto iterate() -> SDL_AppResult;
private:
std::string system_folder_;
std::unique_ptr<Scene> current_scene_;
std::uint64_t last_ticks_ms_{0};
void createSystemFolder();
void processEvents();
void switchSceneIfRequested();
};