Paleta UI compartida (sega-cube.pal) i constants semàntiques UiColor (v0.7.1)

This commit is contained in:
JailDesigner committed 2026-04-19 09:30:29 +02:00
1 parent e6f3c888e6
commit bee9b650db
12 files changed
+396 -19

No files matched your search

+1
View File
@@ -45,6 +45,7 @@ set(APP_SOURCES
source/core/rendering/sdl3gpu/pipelines/crtpi_pipeline.cpp source/core/rendering/sdl3gpu/pipelines/crtpi_pipeline.cpp
source/core/resources/resource_helper.cpp source/core/resources/resource_helper.cpp
source/core/resources/resource_cache.cpp source/core/resources/resource_cache.cpp
source/core/resources/palette_loader.cpp
source/utils/utils.cpp source/utils/utils.cpp
source/game/options.cpp source/game/options.cpp
source/game/scenes/game_scene.cpp source/game/scenes/game_scene.cpp
+259
View File
@@ -0,0 +1,259 @@
JASC-PAL
0100
256
0 0 0
0 36 0
0 72 0
0 109 0
0 145 0
0 182 0
0 218 0
0 255 0
85 0 0
85 36 0
85 72 0
85 109 0
85 145 0
85 182 0
85 218 0
85 255 0
170 0 0
170 36 0
170 72 0
170 109 0
170 145 0
170 182 0
170 218 0
170 255 0
255 0 0
255 36 0
255 72 0
255 109 0
255 145 0
255 182 0
255 218 0
255 255 0
0 0 36
0 36 36
0 72 36
0 109 36
0 145 36
0 182 36
0 218 36
0 255 36
85 0 36
85 36 36
85 72 36
85 109 36
85 145 36
85 182 36
85 218 36
85 255 36
170 0 36
170 36 36
170 72 36
170 109 36
170 145 36
170 182 36
170 218 36
170 255 36
255 0 36
255 36 36
255 72 36
255 109 36
255 145 36
255 182 36
255 218 36
255 255 36
0 0 72
0 36 72
0 72 72
0 109 72
0 145 72
0 182 72
0 218 72
0 255 72
85 0 72
85 36 72
85 72 72
85 109 72
85 145 72
85 182 72
85 218 72
85 255 72
170 0 72
170 36 72
170 72 72
170 109 72
170 145 72
170 182 72
170 218 72
170 255 72
255 0 72
255 36 72
255 72 72
255 109 72
255 145 72
255 182 72
255 218 72
255 255 72
0 0 109
0 36 109
0 72 109
0 109 109
0 145 109
0 182 109
0 218 109
0 255 109
85 0 109
85 36 109
85 72 109
85 109 109
85 145 109
85 182 109
85 218 109
85 255 109
170 0 109
170 36 109
170 72 109
170 109 109
170 145 109
170 182 109
170 218 109
170 255 109
255 0 109
255 36 109
255 72 109
255 109 109
255 145 109
255 182 109
255 218 109
255 255 109
0 0 145
0 36 145
0 72 145
0 109 145
0 145 145
0 182 145
0 218 145
0 255 145
85 0 145
85 36 145
85 72 145
85 109 145
85 145 145
85 182 145
85 218 145
85 255 145
170 0 145
170 36 145
170 72 145
170 109 145
170 145 145
170 182 145
170 218 145
170 255 145
255 0 145
255 36 145
255 72 145
255 109 145
255 145 145
255 182 145
255 218 145
255 255 145
0 0 182
0 36 182
0 72 182
0 109 182
0 145 182
0 182 182
0 218 182
0 255 182
85 0 182
85 36 182
85 72 182
85 109 182
85 145 182
85 182 182
85 218 182
85 255 182
170 0 182
170 36 182
170 72 182
170 109 182
170 145 182
170 182 182
170 218 182
170 255 182
255 0 182
255 36 182
255 72 182
255 109 182
255 145 182
255 182 182
255 218 182
255 255 182
0 0 218
0 36 218
0 72 218
0 109 218
0 145 218
0 182 218
0 218 218
0 255 218
85 0 218
85 36 218
85 72 218
85 109 218
85 145 218
85 182 218
85 218 218
85 255 218
170 0 218
170 36 218
170 72 218
170 109 218
170 145 218
170 182 218
170 218 218
170 255 218
255 0 218
255 36 218
255 72 218
255 109 218
255 145 218
255 182 218
255 218 218
255 255 218
0 0 255
0 36 255
0 72 255
0 109 255
0 145 255
0 182 255
0 218 255
0 255 255
85 0 255
85 36 255
85 72 255
85 109 255
85 145 255
85 182 255
85 218 255
85 255 255
170 0 255
170 36 255
170 72 255
170 109 255
170 145 255
170 182 255
170 218 255
170 255 255
255 0 255
255 36 255
255 72 255
255 109 255
255 145 255
255 182 255
255 218 255
255 255 255
+8 -7
View File
@@ -8,14 +8,11 @@
#include "core/rendering/text.hpp" #include "core/rendering/text.hpp"
#include "core/resources/resource_cache.hpp" #include "core/resources/resource_cache.hpp"
#include "game/options.hpp" #include "game/options.hpp"
#include "game/ui/ui_palette.hpp"
#include "utils/defines.hpp" #include "utils/defines.hpp"
namespace { namespace {
// La paleta de 8bithud.gif només té 2 entrades (0=negre, 1=blanc); per a
// poder colorar el text lliurement caldrà una paleta compartida, com al
// projecte_2026. De moment ens quedem amb blanc.
constexpr Uint8 TEXT_COLOR = 1;
constexpr int TEXT_SIZE = 8; constexpr int TEXT_SIZE = 8;
constexpr int PADDING_V = (RenderInfo::HEIGHT - TEXT_SIZE) / 2; constexpr int PADDING_V = (RenderInfo::HEIGHT - TEXT_SIZE) / 2;
@@ -35,10 +32,14 @@ auto RenderInfo::get() -> RenderInfo& {
RenderInfo::~RenderInfo() = default; RenderInfo::~RenderInfo() = default;
void RenderInfo::init() { void RenderInfo::init() {
// El fitxer s'indexa al Cache perquè també el puguen reutilitzar altres // Paleta compartida de UI: qualsevol HUD que la vulga només ha de cridar
// HUDs que vulguen la mateixa font sense recarregar-la. // Cache::getPalette("ui") i aplicar-la a la seua surface. El .gif propi
// de la font (2 colors) es descarta a favor d'aquesta.
Resource::Cache::get().loadPalette("ui", "data/palettes/sega-cube.pal");
Resource::Cache::get().loadSurface("8bithud.gif", "data/font/8bithud.gif"); Resource::Cache::get().loadSurface("8bithud.gif", "data/font/8bithud.gif");
auto font_surface = Resource::Cache::get().getSurface("8bithud.gif"); auto font_surface = Resource::Cache::get().getSurface("8bithud.gif");
font_surface->setPalette(Resource::Cache::get().getPalette("ui"));
text_ = std::make_unique<Text>(font_surface, "data/font/8bithud.fnt"); text_ = std::make_unique<Text>(font_surface, "data/font/8bithud.fnt");
// Restaura l'estat guardat a config.yaml (video.render_info). // Restaura l'estat guardat a config.yaml (video.render_info).
@@ -93,7 +94,7 @@ void RenderInfo::render() {
static_cast<int>(y_) + PADDING_V, static_cast<int>(y_) + PADDING_V,
line, line,
1, 1,
TEXT_COLOR); UiColor::RENDER_INFO_TEXT);
} }
void RenderInfo::toggle() { void RenderInfo::toggle() {
-8
View File
@@ -63,14 +63,6 @@ auto Surface::loadSurface(const std::string& file_path) -> SurfaceData {
return {static_cast<int>(w), static_cast<int>(h), pixels}; return {static_cast<int>(w), static_cast<int>(h), pixels};
} }
void Surface::loadPalette(const std::string& file_path) {
palette_ = loadPaletteFromGif(file_path);
}
void Surface::loadPalette(const Palette& palette) {
palette_ = palette;
}
void Surface::clear(Uint8 color) { void Surface::clear(Uint8 color) {
const std::size_t TOTAL = static_cast<std::size_t>(surface_data_->width) * static_cast<std::size_t>(surface_data_->height); const std::size_t TOTAL = static_cast<std::size_t>(surface_data_->width) * static_cast<std::size_t>(surface_data_->height);
std::fill(surface_data_->data.get(), surface_data_->data.get() + TOTAL, color); std::fill(surface_data_->data.get(), surface_data_->data.get() + TOTAL, color);
-3
View File
@@ -47,9 +47,6 @@ class Surface {
static auto loadSurface(const std::string& file_path) -> SurfaceData; static auto loadSurface(const std::string& file_path) -> SurfaceData;
void loadPalette(const std::string& file_path);
void loadPalette(const Palette& palette);
// Vobla la regió indicada al framebuffer ARGB del joc usant la paleta propia. // Vobla la regió indicada al framebuffer ARGB del joc usant la paleta propia.
void render(int x, int y, const SDL_FRect* src_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE) const; void render(int x, int y, const SDL_FRect* src_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE) const;
// Igual que render() però substituint els píxels amb valor source_color per // Igual que render() però substituint els píxels amb valor source_color per
+65
View File
@@ -0,0 +1,65 @@
#include "core/resources/palette_loader.hpp"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <filesystem>
#include <sstream>
#include <stdexcept>
#include <string>
#include "core/rendering/surface.hpp"
#include "core/resources/resource_helper.hpp"
namespace Resource::PaletteLoader {
auto parseJasc(const std::vector<std::uint8_t>& bytes) -> Palette {
std::string content(bytes.begin(), bytes.end());
std::istringstream stream(content);
std::string line;
// Capçalera: "JASC-PAL" / "0100" / count.
std::getline(stream, line);
if (!line.starts_with("JASC-PAL")) {
throw std::runtime_error("PaletteLoader: fitxer no és JASC-PAL");
}
std::getline(stream, line); // versió, ignorada per ara
std::getline(stream, line);
int declared_count = 0;
try {
declared_count = std::stoi(line);
} catch (...) {
throw std::runtime_error("PaletteLoader: count JASC-PAL invàlid");
}
Palette palette{};
const std::size_t MAX = std::min(static_cast<std::size_t>(declared_count), palette.size());
std::size_t i = 0;
while (i < MAX && std::getline(stream, line)) {
if (line.empty()) { continue; }
std::istringstream ls(line);
int r = 0;
int g = 0;
int b = 0;
ls >> r >> g >> b;
palette[i] = 0xFF000000U | (static_cast<std::uint32_t>(r & 0xFF) << 16) | (static_cast<std::uint32_t>(g & 0xFF) << 8) | static_cast<std::uint32_t>(b & 0xFF);
++i;
}
return palette;
}
auto loadFromFile(const std::string& file_path) -> Palette {
auto ext = std::filesystem::path(file_path).extension().string();
std::ranges::transform(ext, ext.begin(), [](unsigned char c) { return std::tolower(c); });
auto bytes = Resource::Helper::loadFile(file_path);
if (bytes.empty()) {
throw std::runtime_error("PaletteLoader: no s'ha pogut llegir " + file_path);
}
if (ext == ".pal") { return parseJasc(bytes); }
if (ext == ".gif") { return loadPaletteFromGif(file_path); }
throw std::runtime_error("PaletteLoader: format de paleta no suportat: " + ext);
}
} // namespace Resource::PaletteLoader
+22
View File
@@ -0,0 +1,22 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include "core/rendering/surface.hpp"
namespace Resource::PaletteLoader {
// Detecta el format pel sufix i retorna una Palette (256 entrades ARGB).
// Actualment suporta:
// - ".pal" → JASC-PAL versió 0100 (plaintext "R G B" per línia).
// - ".gif" → paleta global del GIF (reutilitza el decoder existent).
// Cridar-lo amb un altre sufix llança std::runtime_error.
auto loadFromFile(const std::string& file_path) -> Palette;
// Parser pur del format JASC-PAL, útil si ja es té el contingut en memòria
// (p.ex. des d'un resources.pack). No fa I/O.
auto parseJasc(const std::vector<std::uint8_t>& bytes) -> Palette;
} // namespace Resource::PaletteLoader
+16
View File
@@ -4,6 +4,7 @@
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
#include "core/resources/palette_loader.hpp"
#include "core/resources/resource_helper.hpp" #include "core/resources/resource_helper.hpp"
#include "utils/utils.hpp" #include "utils/utils.hpp"
@@ -28,6 +29,12 @@ namespace Resource {
printWithDots("Animation : ", getFileName(file_path), "[ LOADED ]"); printWithDots("Animation : ", getFileName(file_path), "[ LOADED ]");
} }
void Cache::loadPalette(const std::string& name, const std::string& file_path) {
auto palette = PaletteLoader::loadFromFile(file_path);
palettes_.emplace_back(PaletteResource{.name = name, .palette = palette});
printWithDots("Palette : ", getFileName(file_path), "[ LOADED ]");
}
auto Cache::getSurface(const std::string& name) -> std::shared_ptr<Surface> { auto Cache::getSurface(const std::string& name) -> std::shared_ptr<Surface> {
auto it = std::ranges::find_if(surfaces_, [&name](const auto& s) { return s.name == name; }); auto it = std::ranges::find_if(surfaces_, [&name](const auto& s) { return s.name == name; });
if (it == surfaces_.end()) { if (it == surfaces_.end()) {
@@ -46,4 +53,13 @@ namespace Resource {
return *it; return *it;
} }
auto Cache::getPalette(const std::string& name) -> const Palette& {
auto it = std::ranges::find_if(palettes_, [&name](const auto& p) { return p.name == name; });
if (it == palettes_.end()) {
std::cerr << "Cache: palette not found: " << name << '\n';
throw std::runtime_error("Palette not found: " + name);
}
return it->palette;
}
} // namespace Resource } // namespace Resource
+5
View File
@@ -25,9 +25,13 @@ namespace Resource {
void loadSurface(const std::string& name, const std::string& file_path); void loadSurface(const std::string& name, const std::string& file_path);
// Llig el YAML d'animació en cru i el registra amb el nom donat. // Llig el YAML d'animació en cru i el registra amb el nom donat.
void loadAnimation(const std::string& name, const std::string& file_path); void loadAnimation(const std::string& name, const std::string& file_path);
// Carrega una paleta (.pal JASC o .gif) i la registra amb el nom donat.
// Pensat per a paletes compartides (UI, fonts, tilesets reciclats).
void loadPalette(const std::string& name, const std::string& file_path);
auto getSurface(const std::string& name) -> std::shared_ptr<Surface>; auto getSurface(const std::string& name) -> std::shared_ptr<Surface>;
auto getAnimationData(const std::string& name) -> const AnimationResource&; auto getAnimationData(const std::string& name) -> const AnimationResource&;
auto getPalette(const std::string& name) -> const Palette&;
private: private:
Cache() = default; Cache() = default;
@@ -35,6 +39,7 @@ namespace Resource {
std::vector<SurfaceResource> surfaces_; std::vector<SurfaceResource> surfaces_;
std::vector<AnimationResource> animations_; std::vector<AnimationResource> animations_;
std::vector<PaletteResource> palettes_;
}; };
} // namespace Resource } // namespace Resource
+5
View File
@@ -16,3 +16,8 @@ struct AnimationResource {
std::string name; std::string name;
std::vector<std::uint8_t> yaml_data; std::vector<std::uint8_t> yaml_data;
}; };
struct PaletteResource {
std::string name;
Palette palette;
};
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include <SDL3/SDL.h>
// Constants semàntiques que mapegen cada element de la UI al seu color dins
// de la paleta compartida (registre "ui" a Resource::Cache, carregada des de
// data/palettes/sega-cube.pal). Canviar l'aparença d'un component només
// requereix canviar la seua constant ací — no cal buscar l'índex pel codi.
namespace UiColor {
// Color per al text de l'overlay de debug RenderInfo (F3).
constexpr Uint8 RENDER_INFO_TEXT = 9;
} // namespace UiColor
+1 -1
View File
@@ -3,7 +3,7 @@
namespace Texts { namespace Texts {
constexpr const char* WINDOW_TITLE = "© 2026 Aventures en Egipte — JailDesigner"; constexpr const char* WINDOW_TITLE = "© 2026 Aventures en Egipte — JailDesigner";
constexpr const char* COPYRIGHT = "© 2026 JailDesigner"; constexpr const char* COPYRIGHT = "© 2026 JailDesigner";
constexpr const char* VERSION = "0.7.0"; // Single source of truth — Makefile el grep constexpr const char* VERSION = "0.7.1"; // Single source of truth — Makefile el grep
} // namespace Texts } // namespace Texts
namespace GameCanvas { namespace GameCanvas {