Paleta UI compartida (sega-cube.pal) i constants semàntiques UiColor (v0.7.1)
This commit is contained in:
1 parent
e6f3c888e6
commit
bee9b650db
12 files changed
+396
-19
No files matched your search
@@ -45,6 +45,7 @@ set(APP_SOURCES
|
||||
source/core/rendering/sdl3gpu/pipelines/crtpi_pipeline.cpp
|
||||
source/core/resources/resource_helper.cpp
|
||||
source/core/resources/resource_cache.cpp
|
||||
source/core/resources/palette_loader.cpp
|
||||
source/utils/utils.cpp
|
||||
source/game/options.cpp
|
||||
source/game/scenes/game_scene.cpp
|
||||
|
||||
@@ -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,14 +8,11 @@
|
||||
#include "core/rendering/text.hpp"
|
||||
#include "core/resources/resource_cache.hpp"
|
||||
#include "game/options.hpp"
|
||||
#include "game/ui/ui_palette.hpp"
|
||||
#include "utils/defines.hpp"
|
||||
|
||||
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 PADDING_V = (RenderInfo::HEIGHT - TEXT_SIZE) / 2;
|
||||
|
||||
@@ -35,10 +32,14 @@ auto RenderInfo::get() -> RenderInfo& {
|
||||
RenderInfo::~RenderInfo() = default;
|
||||
|
||||
void RenderInfo::init() {
|
||||
// El fitxer s'indexa al Cache perquè també el puguen reutilitzar altres
|
||||
// HUDs que vulguen la mateixa font sense recarregar-la.
|
||||
// Paleta compartida de UI: qualsevol HUD que la vulga només ha de cridar
|
||||
// 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");
|
||||
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");
|
||||
|
||||
// Restaura l'estat guardat a config.yaml (video.render_info).
|
||||
@@ -93,7 +94,7 @@ void RenderInfo::render() {
|
||||
static_cast<int>(y_) + PADDING_V,
|
||||
line,
|
||||
1,
|
||||
TEXT_COLOR);
|
||||
UiColor::RENDER_INFO_TEXT);
|
||||
}
|
||||
|
||||
void RenderInfo::toggle() {
|
||||
|
||||
@@ -63,14 +63,6 @@ auto Surface::loadSurface(const std::string& file_path) -> SurfaceData {
|
||||
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) {
|
||||
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);
|
||||
|
||||
@@ -47,9 +47,6 @@ class Surface {
|
||||
|
||||
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.
|
||||
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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "core/resources/palette_loader.hpp"
|
||||
#include "core/resources/resource_helper.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
@@ -28,6 +29,12 @@ namespace Resource {
|
||||
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 it = std::ranges::find_if(surfaces_, [&name](const auto& s) { return s.name == name; });
|
||||
if (it == surfaces_.end()) {
|
||||
@@ -46,4 +53,13 @@ namespace Resource {
|
||||
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
|
||||
@@ -25,9 +25,13 @@ namespace Resource {
|
||||
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.
|
||||
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 getAnimationData(const std::string& name) -> const AnimationResource&;
|
||||
auto getPalette(const std::string& name) -> const Palette&;
|
||||
|
||||
private:
|
||||
Cache() = default;
|
||||
@@ -35,6 +39,7 @@ namespace Resource {
|
||||
|
||||
std::vector<SurfaceResource> surfaces_;
|
||||
std::vector<AnimationResource> animations_;
|
||||
std::vector<PaletteResource> palettes_;
|
||||
};
|
||||
|
||||
} // namespace Resource
|
||||
@@ -16,3 +16,8 @@ struct AnimationResource {
|
||||
std::string name;
|
||||
std::vector<std::uint8_t> yaml_data;
|
||||
};
|
||||
|
||||
struct PaletteResource {
|
||||
std::string name;
|
||||
Palette palette;
|
||||
};
|
||||
@@ -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
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Texts {
|
||||
constexpr const char* WINDOW_TITLE = "© 2026 Aventures en Egipte — 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 GameCanvas {
|
||||
|
||||
Reference in new issue
Block a user