presets en yaml

This commit is contained in:
2026-04-17 19:56:43 +02:00
parent 7f703390f9
commit 5889df2a47
13 changed files with 519 additions and 161 deletions

View File

@@ -0,0 +1,42 @@
#include "core/input/global_inputs.hpp"
#include "core/input/input.h"
#include "core/rendering/screen.h"
namespace GlobalInputs {
auto handle(Screen *screen, Input *input) -> bool {
if (screen == nullptr || input == nullptr) { return false; }
if (input->checkInput(input_window_fullscreen, REPEAT_FALSE)) {
screen->toggleVideoMode();
return true;
}
if (input->checkInput(input_window_dec_size, REPEAT_FALSE)) {
screen->decWindowZoom();
return true;
}
if (input->checkInput(input_window_inc_size, REPEAT_FALSE)) {
screen->incWindowZoom();
return true;
}
if (input->checkInput(input_prev_preset, REPEAT_FALSE)) {
screen->prevPreset();
return true;
}
if (input->checkInput(input_next_preset, REPEAT_FALSE)) {
screen->nextPreset();
return true;
}
if (input->checkInput(input_toggle_shader, REPEAT_FALSE)) {
screen->toggleShaderEnabled();
return true;
}
if (input->checkInput(input_toggle_shader_type, REPEAT_FALSE)) {
screen->toggleActiveShader();
return true;
}
return false;
}
} // namespace GlobalInputs

View File

@@ -0,0 +1,13 @@
#pragma once
class Input;
class Screen;
namespace GlobalInputs {
// Gestiona els atalls globals disponibles en qualsevol escena: zoom de
// finestra (F1/F2), fullscreen (F3), presets de shader (F8/F9), toggle
// shader (F10) i tipus de shader POSTFX↔CRTPI (F11). Retorna true si ha
// consumit alguna tecla (per si la capa cridant vol suprimir-la del
// processament específic de l'escena).
auto handle(Screen *screen, Input *input) -> bool;
} // namespace GlobalInputs

View File

@@ -35,7 +35,8 @@ enum inputs_e {
input_window_dec_size,
// GPU / shaders (hotkeys provisionales hasta que haya menú de opciones)
input_toggle_gpu,
input_prev_preset,
input_next_preset,
input_toggle_shader,
input_toggle_shader_type,

View File

@@ -452,7 +452,7 @@ void Screen::registerEmscriptenEventCallbacks() {
// ============================================================================
#ifndef NO_SHADERS
// Aplica al backend el preset del shader actiu segons options.
// Aplica al backend el shader actiu + els seus presets PostFX i CrtPi.
// Només s'ha de cridar quan `videoShaderEnabled=true` (en cas contrari el
// blit() ja força POSTFX+zero params per a desactivar els efectes sense
// tocar els paràmetres emmagatzemats).
@@ -461,16 +461,8 @@ void Screen::applyShaderParams() {
return;
}
shader_backend_->setActiveShader(Options::video.shader.current_shader);
// Preset per defecte (carregador YAML pendent). Valors estil "CRT" de CCAE.
Rendering::PostFXParams POSTFX;
POSTFX.vignette = 0.15F;
POSTFX.scanlines = 0.7F;
POSTFX.chroma = 0.2F;
shader_backend_->setPostFXParams(POSTFX);
// CrtPi: defaults del struct ja raonables (scanline_weight=6.0, bloom=3.5…).
shader_backend_->setCrtPiParams(Rendering::CrtPiParams{});
applyCurrentPostFXPreset();
applyCurrentCrtPiPreset();
}
#endif
@@ -491,6 +483,22 @@ void Screen::initShaders() {
if (shader_backend_->isHardwareAccelerated()) {
shader_backend_->setScaleMode(Options::video.integer_scale);
shader_backend_->setVSync(Options::video.vsync);
// Resol els índexs de preset a partir del nom emmagatzemat al config.
// Si el nom no existeix (preset esborrat del YAML), es queda en 0.
for (int i = 0; i < static_cast<int>(Options::postfx_presets.size()); ++i) {
if (Options::postfx_presets[i].name == Options::video.shader.current_postfx_preset_name) {
Options::current_postfx_preset = i;
break;
}
}
for (int i = 0; i < static_cast<int>(Options::crtpi_presets.size()); ++i) {
if (Options::crtpi_presets[i].name == Options::video.shader.current_crtpi_preset_name) {
Options::current_crtpi_preset = i;
break;
}
}
applyShaderParams(); // aplica preset del shader actiu
}
#endif
@@ -508,22 +516,6 @@ void Screen::shutdownShaders() {
#endif
}
void Screen::setGpuAcceleration(bool enabled) {
if (Options::video.gpu.acceleration == enabled) { return; }
Options::video.gpu.acceleration = enabled;
// Soft toggle: el backend es manté viu (vegeu shutdownShaders). El canvi
// s'aplica al proper arrencada. S'emet una notificació perquè l'usuari
// sap que ha tocat la tecla però el canvi no és immediat.
const color_t YELLOW = {0xFF, 0xFF, 0x00};
const color_t BLACK = {0x00, 0x00, 0x00};
const Uint32 DUR_MS = 2500;
notify(enabled ? "GPU: ON (restart)" : "GPU: OFF (restart)", YELLOW, BLACK, DUR_MS);
}
void Screen::toggleGpuAcceleration() {
setGpuAcceleration(!Options::video.gpu.acceleration);
}
auto Screen::isGpuAccelerated() const -> bool {
#ifndef NO_SHADERS
return shader_backend_ && shader_backend_->isHardwareAccelerated();
@@ -585,3 +577,137 @@ void Screen::toggleActiveShader() {
: Rendering::ShaderType::POSTFX;
#endif
}
// ============================================================================
// Presets de shaders
// ============================================================================
void Screen::applyCurrentPostFXPreset() {
#ifndef NO_SHADERS
if (!shader_backend_ || !shader_backend_->isHardwareAccelerated()) { return; }
if (Options::postfx_presets.empty()) { return; }
if (Options::current_postfx_preset < 0
|| Options::current_postfx_preset >= static_cast<int>(Options::postfx_presets.size())) {
Options::current_postfx_preset = 0;
}
const auto &PRESET = Options::postfx_presets[Options::current_postfx_preset];
Rendering::PostFXParams p;
p.vignette = PRESET.vignette;
p.scanlines = PRESET.scanlines;
p.chroma = PRESET.chroma;
p.mask = PRESET.mask;
p.gamma = PRESET.gamma;
p.curvature = PRESET.curvature;
p.bleeding = PRESET.bleeding;
p.flicker = PRESET.flicker;
shader_backend_->setPostFXParams(p);
#endif
}
void Screen::applyCurrentCrtPiPreset() {
#ifndef NO_SHADERS
if (!shader_backend_ || !shader_backend_->isHardwareAccelerated()) { return; }
if (Options::crtpi_presets.empty()) { return; }
if (Options::current_crtpi_preset < 0
|| Options::current_crtpi_preset >= static_cast<int>(Options::crtpi_presets.size())) {
Options::current_crtpi_preset = 0;
}
const auto &PRESET = Options::crtpi_presets[Options::current_crtpi_preset];
Rendering::CrtPiParams p;
p.scanline_weight = PRESET.scanline_weight;
p.scanline_gap_brightness = PRESET.scanline_gap_brightness;
p.bloom_factor = PRESET.bloom_factor;
p.input_gamma = PRESET.input_gamma;
p.output_gamma = PRESET.output_gamma;
p.mask_brightness = PRESET.mask_brightness;
p.curvature_x = PRESET.curvature_x;
p.curvature_y = PRESET.curvature_y;
p.mask_type = PRESET.mask_type;
p.enable_scanlines = PRESET.enable_scanlines;
p.enable_multisample = PRESET.enable_multisample;
p.enable_gamma = PRESET.enable_gamma;
p.enable_curvature = PRESET.enable_curvature;
p.enable_sharper = PRESET.enable_sharper;
shader_backend_->setCrtPiParams(p);
#endif
}
auto Screen::getCurrentPresetName() const -> const char* {
#ifndef NO_SHADERS
if (!shader_backend_ || !shader_backend_->isHardwareAccelerated()) { return "---"; }
if (Options::video.shader.current_shader == Rendering::ShaderType::POSTFX) {
if (Options::current_postfx_preset >= 0
&& Options::current_postfx_preset < static_cast<int>(Options::postfx_presets.size())) {
return Options::postfx_presets[Options::current_postfx_preset].name.c_str();
}
} else {
if (Options::current_crtpi_preset >= 0
&& Options::current_crtpi_preset < static_cast<int>(Options::crtpi_presets.size())) {
return Options::crtpi_presets[Options::current_crtpi_preset].name.c_str();
}
}
#endif
return "---";
}
auto Screen::nextPreset() -> bool {
#ifndef NO_SHADERS
if (!shader_backend_ || !shader_backend_->isHardwareAccelerated()) { return false; }
if (!Options::video.shader.enabled) { return false; }
if (Options::video.shader.current_shader == Rendering::ShaderType::POSTFX) {
if (Options::postfx_presets.empty()) { return false; }
const int N = static_cast<int>(Options::postfx_presets.size());
Options::current_postfx_preset = (Options::current_postfx_preset + 1) % N;
Options::video.shader.current_postfx_preset_name =
Options::postfx_presets[Options::current_postfx_preset].name;
applyCurrentPostFXPreset();
} else {
if (Options::crtpi_presets.empty()) { return false; }
const int N = static_cast<int>(Options::crtpi_presets.size());
Options::current_crtpi_preset = (Options::current_crtpi_preset + 1) % N;
Options::video.shader.current_crtpi_preset_name =
Options::crtpi_presets[Options::current_crtpi_preset].name;
applyCurrentCrtPiPreset();
}
const color_t GREEN = {0x00, 0xFF, 0x80};
const color_t BLACK = {0x00, 0x00, 0x00};
const Uint32 DUR_MS = 1500;
notify(std::string("Preset: ") + getCurrentPresetName(), GREEN, BLACK, DUR_MS);
return true;
#else
return false;
#endif
}
auto Screen::prevPreset() -> bool {
#ifndef NO_SHADERS
if (!shader_backend_ || !shader_backend_->isHardwareAccelerated()) { return false; }
if (!Options::video.shader.enabled) { return false; }
if (Options::video.shader.current_shader == Rendering::ShaderType::POSTFX) {
if (Options::postfx_presets.empty()) { return false; }
const int N = static_cast<int>(Options::postfx_presets.size());
Options::current_postfx_preset = (Options::current_postfx_preset - 1 + N) % N;
Options::video.shader.current_postfx_preset_name =
Options::postfx_presets[Options::current_postfx_preset].name;
applyCurrentPostFXPreset();
} else {
if (Options::crtpi_presets.empty()) { return false; }
const int N = static_cast<int>(Options::crtpi_presets.size());
Options::current_crtpi_preset = (Options::current_crtpi_preset - 1 + N) % N;
Options::video.shader.current_crtpi_preset_name =
Options::crtpi_presets[Options::current_crtpi_preset].name;
applyCurrentCrtPiPreset();
}
const color_t GREEN = {0x00, 0xFF, 0x80};
const color_t BLACK = {0x00, 0x00, 0x00};
const Uint32 DUR_MS = 1500;
notify(std::string("Preset: ") + getCurrentPresetName(), GREEN, BLACK, DUR_MS);
return true;
#else
return false;
#endif
}

View File

@@ -63,8 +63,6 @@ class Screen {
// GPU / shaders (post-procesado). En builds con NO_SHADERS (Emscripten) son no-op.
void initShaders(); // Crea el backend GPU si no existe y lo inicializa
void shutdownShaders(); // Libera el backend GPU
void setGpuAcceleration(bool enabled); // Crea/destruye el backend según valor, persiste options
void toggleGpuAcceleration(); // Alterna aceleración GPU
auto isGpuAccelerated() const -> bool; // true si el backend existe y reporta hardware OK
void setShaderEnabled(bool enabled); // Activa o desactiva el post-procesado (persiste)
void toggleShaderEnabled(); // Alterna post-procesado
@@ -75,6 +73,14 @@ class Screen {
#endif
void toggleActiveShader(); // Alterna POSTFX ↔ CRTPI
// Presets de shaders (PostFX/CrtPi). Operen sobre el shader actiu.
// Retornen false si GPU off / shaders off / llista buida (igual que a aee_plus).
auto nextPreset() -> bool;
auto prevPreset() -> bool;
auto getCurrentPresetName() const -> const char*;
void applyCurrentPostFXPreset(); // Escriu el preset PostFX actiu al backend
void applyCurrentCrtPiPreset(); // Escriu el preset CrtPi actiu al backend
private:
// Helpers internos de setVideoMode
void applyFullscreen(bool fullscreen); // SDL_SetWindowFullscreen + visibilidad del cursor

View File

@@ -64,6 +64,12 @@ Director::Director(int argc, const char *argv[]) {
Options::setConfigFile(systemFolder + "/config.yaml");
Options::loadFromFile();
// Presets de shaders (creats amb defaults si no existeixen).
Options::setPostFXFile(systemFolder + "/postfx.yaml");
Options::loadPostFXFromFile();
Options::setCrtPiFile(systemFolder + "/crtpi.yaml");
Options::loadCrtPiFromFile();
// Inicializa el sistema de recursos (pack + fallback).
// En wasm siempre se usa filesystem (MEMFS) porque el propio --preload-file
// de emscripten ya empaqueta data/ — no hay resources.pack.
@@ -202,7 +208,8 @@ void Director::initInput() {
input->bindKey(input_window_dec_size, SDL_SCANCODE_F1);
input->bindKey(input_window_inc_size, SDL_SCANCODE_F2);
input->bindKey(input_window_fullscreen, SDL_SCANCODE_F3);
input->bindKey(input_toggle_gpu, SDL_SCANCODE_F9);
input->bindKey(input_prev_preset, SDL_SCANCODE_F8);
input->bindKey(input_next_preset, SDL_SCANCODE_F9);
input->bindKey(input_toggle_shader, SDL_SCANCODE_F10);
input->bindKey(input_toggle_shader_type, SDL_SCANCODE_F11);