decrementada la responsabilitat d'Screen i afegit PaletteManager

This commit is contained in:
2026-03-31 07:14:58 +02:00
parent 16924cf503
commit 3fc6795593
6 changed files with 224 additions and 159 deletions

View File

@@ -0,0 +1,104 @@
#include "core/rendering/palette_manager.hpp"
#include <algorithm>
#include <cctype>
#include <string>
#include "core/rendering/surface.hpp"
#include "core/resources/resource_cache.hpp"
#include "game/options.hpp"
#include "utils/utils.hpp"
PaletteManager::PaletteManager(
std::vector<std::string> raw_paths,
const std::string& initial_name,
std::shared_ptr<Surface> game_surface,
std::shared_ptr<Surface> border_surface,
OnChangeCallback on_change)
: palettes_(std::move(raw_paths)),
game_surface_(std::move(game_surface)),
border_surface_(std::move(border_surface)),
on_change_(std::move(on_change)) {
current_ = findIndex(initial_name);
// Leer y aplicar paleta inicial directamente desde el archivo
// (Resource::Cache aún no está disponible en este punto del ciclo de vida)
const auto initial_palette = readPalFile(palettes_.at(current_));
game_surface_->setPalette(initial_palette);
border_surface_->setPalette(initial_palette);
// Procesar la lista: conservar solo los nombres de archivo (sin ruta)
processPathList();
}
void PaletteManager::next() {
if (++current_ == palettes_.size()) {
current_ = 0;
}
apply();
}
void PaletteManager::previous() {
current_ = (current_ > 0) ? current_ - 1 : palettes_.size() - 1;
apply();
}
auto PaletteManager::setByName(const std::string& name) -> bool {
const std::string upper_name = toUpper(name + ".pal");
for (size_t i = 0; i < palettes_.size(); ++i) {
if (toUpper(palettes_[i]) == upper_name) {
current_ = i;
apply();
return true;
}
}
return false;
}
auto PaletteManager::getNames() const -> std::vector<std::string> {
std::vector<std::string> names;
names.reserve(palettes_.size());
for (const auto& p : palettes_) {
std::string name = p;
const size_t pos = name.find(".pal");
if (pos != std::string::npos) { name.erase(pos, 4); }
std::ranges::transform(name, name.begin(), ::toupper);
names.push_back(std::move(name));
}
return names;
}
auto PaletteManager::getCurrentName() const -> std::string {
std::string name = palettes_.at(current_);
const size_t pos = name.find(".pal");
if (pos != std::string::npos) { name.erase(pos, 4); }
std::ranges::transform(name, name.begin(), ::toupper);
return name;
}
void PaletteManager::apply() {
game_surface_->loadPalette(Resource::Cache::get()->getPalette(palettes_.at(current_)));
border_surface_->loadPalette(Resource::Cache::get()->getPalette(palettes_.at(current_)));
Options::video.palette = getCurrentName();
if (on_change_) {
on_change_();
}
}
auto PaletteManager::findIndex(const std::string& name) const -> size_t {
const std::string upper_name = toUpper(name + ".pal");
for (size_t i = 0; i < palettes_.size(); ++i) {
if (toUpper(getFileName(palettes_[i])) == upper_name) {
return i;
}
}
return 0;
}
void PaletteManager::processPathList() {
for (auto& palette : palettes_) {
palette = getFileName(palette);
}
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include <functional>
#include <memory>
#include <string>
#include <vector>
class Surface;
class PaletteManager {
public:
using OnChangeCallback = std::function<void()>;
PaletteManager(
std::vector<std::string> raw_paths,
const std::string& initial_name,
std::shared_ptr<Surface> game_surface,
std::shared_ptr<Surface> border_surface,
OnChangeCallback on_change = nullptr);
void next(); // Avanza a la siguiente paleta
void previous(); // Retrocede a la paleta anterior
auto setByName(const std::string& name) -> bool; // Cambia a paleta por nombre; false si no existe
[[nodiscard]] auto getNames() const -> std::vector<std::string>; // Nombres disponibles (mayúsculas, sin .pal)
[[nodiscard]] auto getCurrentName() const -> std::string; // Nombre de la paleta actual (mayúsculas, sin .pal)
private:
void apply(); // Aplica la paleta actual a ambas surfaces
[[nodiscard]] auto findIndex(const std::string& name) const -> size_t; // Localiza paleta por nombre en el vector
void processPathList(); // Extrae nombres de archivo de las rutas completas
std::vector<std::string> palettes_;
size_t current_{0};
std::shared_ptr<Surface> game_surface_;
std::shared_ptr<Surface> border_surface_;
OnChangeCallback on_change_;
};

View File

@@ -42,8 +42,7 @@ auto Screen::get() -> Screen* {
}
// Constructor
Screen::Screen()
: palettes_(Resource::List::get()->getListByType(Resource::List::Type::PALETTE)) {
Screen::Screen() {
// Arranca SDL VIDEO, crea la ventana y el renderizador
initSDLVideo();
if (Options::video.fullscreen) { SDL_HideCursor(); }
@@ -55,7 +54,6 @@ Screen::Screen()
// Ajusta los tamaños
game_surface_dstrect_ = {.x = Options::video.border.width, .y = Options::video.border.height, .w = Options::game.width, .h = Options::game.height};
current_palette_ = findPalette(Options::video.palette);
// Define el color del borde para el modo de pantalla completa
border_color_ = static_cast<Uint8>(PaletteColor::BLACK);
@@ -76,19 +74,27 @@ Screen::Screen()
}
SDL_SetTextureScaleMode(border_texture_, SDL_SCALEMODE_NEAREST);
// Cargar la paleta una sola vez
auto initial_palette = readPalFile(palettes_.at(current_palette_));
// Crea la surface donde se dibujan los graficos del juego
// Crea las surfaces (PaletteManager aplicará la paleta inicial en su constructor)
game_surface_ = std::make_shared<Surface>(Options::game.width, Options::game.height);
game_surface_->setPalette(initial_palette);
game_surface_->clear(static_cast<Uint8>(PaletteColor::BLACK));
// Crea la surface para el borde de colores
border_surface_ = std::make_shared<Surface>(Options::game.width + (Options::video.border.width * 2), Options::game.height + (Options::video.border.height * 2));
border_surface_->setPalette(initial_palette);
border_surface_->clear(border_color_);
// Crea el gestor de paletas; aplica la paleta inicial a ambas surfaces
palette_manager_ = std::make_unique<PaletteManager>(
Resource::List::get()->getListByType(Resource::List::Type::PALETTE),
Options::video.palette,
game_surface_,
border_surface_,
[this]() {
// Actualizar caché ARGB del borde cuando cambia la paleta
if (border_is_solid_) {
border_surface_->toARGBBuffer(border_pixel_buffer_.data());
border_argb_color_ = border_pixel_buffer_[0];
}
});
// Cachear el color ARGB inicial del borde (borde sólido por defecto)
border_surface_->toARGBBuffer(border_pixel_buffer_.data());
border_argb_color_ = border_pixel_buffer_[0];
@@ -99,9 +105,6 @@ Screen::Screen()
// Crea el objeto de texto para la pantalla de carga
createText();
// Extrae el nombre de las paletas desde su ruta
processPaletteList();
// Renderizar una vez la textura vacía para que tenga contenido válido
// antes de inicializar los shaders (evita pantalla negra)
SDL_RenderTexture(renderer_, game_texture_, nullptr, nullptr);
@@ -357,55 +360,10 @@ void Screen::setRendererSurface(const std::shared_ptr<Surface>& surface) {
}
// Cambia la paleta
void Screen::nextPalette() {
++current_palette_;
if (current_palette_ == static_cast<int>(palettes_.size())) {
current_palette_ = 0;
}
setPalete();
}
void Screen::nextPalette() { palette_manager_->next(); }
// Cambia la paleta
void Screen::previousPalette() {
if (current_palette_ > 0) {
--current_palette_;
} else {
current_palette_ = static_cast<Uint8>(palettes_.size() - 1);
}
setPalete();
}
// Establece la paleta
void Screen::setPalete() { // NOLINT(readability-convert-member-functions-to-static)
game_surface_->loadPalette(Resource::Cache::get()->getPalette(palettes_.at(current_palette_)));
border_surface_->loadPalette(Resource::Cache::get()->getPalette(palettes_.at(current_palette_)));
Options::video.palette = palettes_.at(current_palette_);
// Eliminar ".gif"
size_t pos = Options::video.palette.find(".pal");
if (pos != std::string::npos) {
Options::video.palette.erase(pos, 4);
}
// Convertir a mayúsculas
std::ranges::transform(Options::video.palette, Options::video.palette.begin(), ::toupper);
// Actualizar caché si el borde es sólido (la paleta cambia el valor ARGB del color)
if (border_is_solid_) {
border_surface_->toARGBBuffer(border_pixel_buffer_.data());
border_argb_color_ = border_pixel_buffer_[0];
}
}
// Extrae los nombres de las paletas
void Screen::processPaletteList() {
for (auto& palette : palettes_) {
palette = getFileName(palette);
}
}
void Screen::previousPalette() { palette_manager_->previous(); }
// Copia la surface a la textura
void Screen::surfaceToTexture() { // NOLINT(readability-convert-member-functions-to-static)
@@ -485,44 +443,11 @@ void Screen::renderOverlays() {
if (Console::get() != nullptr) { Console::get()->render(); } // Console (encima)
}
// Localiza la paleta dentro del vector de paletas
auto Screen::findPalette(const std::string& name) -> size_t { // NOLINT(readability-convert-member-functions-to-static)
std::string upper_name = toUpper(name + ".pal");
for (size_t i = 0; i < palettes_.size(); ++i) {
if (toUpper(getFileName(palettes_[i])) == upper_name) {
return i;
}
}
return static_cast<size_t>(0);
}
// Cambia a una paleta por nombre (case-insensitive); devuelve false si no existe
bool Screen::setPaletteByName(const std::string& name) {
const std::string upper_name = toUpper(name + ".pal");
for (size_t i = 0; i < palettes_.size(); ++i) {
if (toUpper(getFileName(palettes_[i])) == upper_name) {
current_palette_ = static_cast<Uint8>(i);
setPalete();
return true;
}
}
return false;
}
auto Screen::setPaletteByName(const std::string& name) -> bool { return palette_manager_->setByName(name); }
// Devuelve los nombres de paletas disponibles (mayúsculas, sin extensión .pal)
auto Screen::getPaletteNames() const -> std::vector<std::string> {
std::vector<std::string> names;
names.reserve(palettes_.size());
for (const auto& p : palettes_) {
std::string name = p;
const size_t pos = name.find(".pal");
if (pos != std::string::npos) { name.erase(pos, 4); }
std::ranges::transform(name, name.begin(), ::toupper);
names.push_back(std::move(name));
}
return names;
}
auto Screen::getPaletteNames() const -> std::vector<std::string> { return palette_manager_->getNames(); }
// Limpia la game_surface_
void Screen::clearSurface(Uint8 index) { game_surface_->clear(index); }

View File

@@ -9,8 +9,9 @@
#include <utility> // Para std::pair
#include <vector> // Para vector
#include "core/rendering/shader_backend.hpp" // Para Rendering::ShaderType, ShaderBackend
#include "utils/utils.hpp" // Para Color
#include "core/rendering/palette_manager.hpp" // Para PaletteManager
#include "core/rendering/shader_backend.hpp" // Para Rendering::ShaderType, ShaderBackend
#include "utils/utils.hpp" // Para Color
class Surface;
class Text;
@@ -35,15 +36,15 @@ class Screen {
void update(float delta_time); // Actualiza la lógica de la clase
// Video y ventana
void setVideoMode(bool mode); // Establece el modo de video
void toggleVideoMode(); // Cambia entre pantalla completa y ventana
void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero
void toggleVSync(); // Alterna entre activar y desactivar el V-Sync
auto decWindowZoom() -> bool; // Reduce el tamaño de la ventana
auto incWindowZoom() -> bool; // Aumenta el tamaño de la ventana
void setVideoMode(bool mode); // Establece el modo de video
void toggleVideoMode(); // Cambia entre pantalla completa y ventana
void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero
void toggleVSync(); // Alterna entre activar y desactivar el V-Sync
auto decWindowZoom() -> bool; // Reduce el tamaño de la ventana
auto incWindowZoom() -> bool; // Aumenta el tamaño de la ventana
auto setWindowZoom(int zoom) -> bool; // Establece zoom directo; false si fuera de [1, max_zoom]
void show(); // Muestra la ventana
void hide(); // Oculta la ventana
void show(); // Muestra la ventana
void hide(); // Oculta la ventana
// Borde
void setBorderColor(Uint8 color); // Cambia el color del borde
@@ -55,8 +56,7 @@ class Screen {
// Paletas y PostFX
void nextPalette(); // Cambia a la siguiente paleta
void previousPalette(); // Cambia a la paleta anterior
void setPalete(); // Establece la paleta actual
bool setPaletteByName(const std::string& name); // Cambia a paleta por nombre; false si no existe
auto setPaletteByName(const std::string& name) -> bool; // Cambia a paleta por nombre; false si no existe
[[nodiscard]] auto getPaletteNames() const -> std::vector<std::string>; // Nombres disponibles (mayúsculas, sin .pal)
void toggleShaders(); // Activa/desactiva todos los shaders respetando current_shader
void toggleSupersampling(); // Activa/desactiva el supersampling global
@@ -120,20 +120,18 @@ class Screen {
static Screen* screen;
// Métodos privados
void renderNotifications() const; // Dibuja las notificaciones
void adjustWindowSize(); // Calcula el tamaño de la ventana
void adjustRenderLogicalSize(); // Ajusta el tamaño lógico del renderizador
void processPaletteList(); // Extrae los nombres de las paletas
void surfaceToTexture(); // Copia la surface a la textura
void textureToRenderer(); // Copia la textura al renderizador
void renderOverlays(); // Renderiza todos los overlays
auto findPalette(const std::string& name) -> size_t; // Localiza la paleta dentro del vector de paletas
void initShaders(); // Inicializa los shaders
void applyCurrentPostFXPreset(); // Aplica los parámetros del preset PostFX actual al backend
void applyCurrentCrtPiPreset(); // Aplica los parámetros del preset CrtPi actual al backend
void getDisplayInfo(); // Obtiene información sobre la pantalla
auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana
void createText(); // Crea el objeto de texto
void renderNotifications() const; // Dibuja las notificaciones
void adjustWindowSize(); // Calcula el tamaño de la ventana
void adjustRenderLogicalSize(); // Ajusta el tamaño lógico del renderizador
void surfaceToTexture(); // Copia la surface a la textura
void textureToRenderer(); // Copia la textura al renderizador
void renderOverlays(); // Renderiza todos los overlays
void initShaders(); // Inicializa los shaders
void applyCurrentPostFXPreset(); // Aplica los parámetros del preset PostFX actual al backend
void applyCurrentCrtPiPreset(); // Aplica los parámetros del preset CrtPi actual al backend
void getDisplayInfo(); // Obtiene información sobre la pantalla
auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana
void createText(); // Crea el objeto de texto
// Constructor y destructor
Screen();
@@ -167,9 +165,8 @@ class Screen {
SDL_FRect game_surface_dstrect_; // Coordenadas donde se dibuja la textura del juego
// Paletas y colores
Uint8 border_color_{0}; // Color del borde
std::vector<std::string> palettes_; // Listado de ficheros de paleta disponibles
Uint8 current_palette_{0}; // Índice para el vector de paletas
Uint8 border_color_{0}; // Color del borde
std::unique_ptr<PaletteManager> palette_manager_; // Gestor de paletas de color
// Estado y configuración
bool notifications_enabled_{false}; // Indica si se muestran las notificaciones