Merge branch 'feat/preload-resources': precàrrega completa al boot

This commit is contained in:
2026-05-24 19:32:04 +02:00
5 changed files with 244 additions and 182 deletions
+24 -19
View File
@@ -9,29 +9,34 @@
namespace Resource::Helper {
// Inicialitzar el sistema de recursos
auto initializeResourceSystem(const std::string& pack_file, bool fallback) -> bool {
// Inicialitzar el sistema de recursos
auto initializeResourceSystem(const std::string& pack_file, bool fallback) -> bool {
return Loader::get().initialize(pack_file, fallback);
}
}
// Carregar un file
auto loadFile(const std::string& filepath) -> std::vector<uint8_t> {
// Carregar un file
auto loadFile(const std::string& filepath) -> std::vector<uint8_t> {
// Normalitzar la ruta
std::string normalized = normalizePath(filepath);
// Carregar del sistema de recursos
return Loader::get().loadResource(normalized);
}
}
// Comprovar si existeix un file
auto fileExists(const std::string& filepath) -> bool {
// Llistar recursos amb un prefix donat
auto listResources(const std::string& prefix) -> std::vector<std::string> {
return Loader::get().listResources(prefix);
}
// Comprovar si existeix un file
auto fileExists(const std::string& filepath) -> bool {
std::string normalized = normalizePath(filepath);
return Loader::get().resourceExists(normalized);
}
}
// Obtenir ruta normalitzada per al paquet
// Elimina prefixos "data/", rutes absolutes, etc.
auto getPackPath(const std::string& asset_path) -> std::string {
// Obtenir ruta normalitzada per al paquet
// Elimina prefixos "data/", rutes absolutes, etc.
auto getPackPath(const std::string& asset_path) -> std::string {
std::string path = asset_path;
// Eliminar rutes absolutes (detectar / o C:\ al principi)
@@ -65,16 +70,16 @@ auto getPackPath(const std::string& asset_path) -> std::string {
std::ranges::replace(path, '\\', '/');
return path;
}
}
// Normalitzar ruta (alias de getPackPath)
auto normalizePath(const std::string& path) -> std::string {
// Normalitzar ruta (alias de getPackPath)
auto normalizePath(const std::string& path) -> std::string {
return getPackPath(path);
}
}
// Comprovar si hay paquet carregat
auto isPackLoaded() -> bool {
// Comprovar si hay paquet carregat
auto isPackLoaded() -> bool {
return Loader::get().isPackLoaded();
}
}
} // namespace Resource::Helper
+13 -10
View File
@@ -10,18 +10,21 @@
namespace Resource::Helper {
// Inicialización del sistema
auto initializeResourceSystem(const std::string& pack_file, bool fallback) -> bool;
// Inicialización del sistema
auto initializeResourceSystem(const std::string& pack_file, bool fallback) -> bool;
// Càrrega de archivos
auto loadFile(const std::string& filepath) -> std::vector<uint8_t>;
auto fileExists(const std::string& filepath) -> bool;
// Càrrega de archivos
auto loadFile(const std::string& filepath) -> std::vector<uint8_t>;
auto fileExists(const std::string& filepath) -> bool;
// Normalització de rutes
auto getPackPath(const std::string& asset_path) -> std::string;
auto normalizePath(const std::string& path) -> std::string;
// Llistat de recursos disponibles amb un prefix (ex. "shapes/", "sounds/").
auto listResources(const std::string& prefix) -> std::vector<std::string>;
// Estat
auto isPackLoaded() -> bool;
// Normalització de rutes
auto getPackPath(const std::string& asset_path) -> std::string;
auto normalizePath(const std::string& path) -> std::string;
// Estat
auto isPackLoaded() -> bool;
} // namespace Resource::Helper
+64 -27
View File
@@ -3,20 +3,21 @@
#include "resource_loader.hpp"
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <iostream>
namespace Resource {
// Singleton
auto Loader::get() -> Loader& {
// Singleton
auto Loader::get() -> Loader& {
static Loader instance_;
return instance_;
}
}
// Inicialitzar el sistema de recursos
auto Loader::initialize(const std::string& pack_file, bool enable_fallback) -> bool {
// Inicialitzar el sistema de recursos
auto Loader::initialize(const std::string& pack_file, bool enable_fallback) -> bool {
fallback_enabled_ = enable_fallback;
// Intentar load el paquet
@@ -36,10 +37,10 @@ auto Loader::initialize(const std::string& pack_file, bool enable_fallback) -> b
std::cout << "[ResourceLoader] Paquet carregat: " << pack_file << "\n";
return true;
}
}
// Carregar un recurs
auto Loader::loadResource(const std::string& filename) -> std::vector<uint8_t> {
// Carregar un recurs
auto Loader::loadResource(const std::string& filename) -> std::vector<uint8_t> {
// Intentar load del paquet primer
if (pack_) {
if (pack_->hasResource(filename)) {
@@ -65,10 +66,46 @@ auto Loader::loadResource(const std::string& filename) -> std::vector<uint8_t> {
}
return {};
}
}
// Comprovar si existeix un recurs
auto Loader::resourceExists(const std::string& filename) -> bool {
auto Loader::listResources(const std::string& prefix) -> std::vector<std::string> {
std::vector<std::string> result;
if (pack_) {
for (const auto& path : pack_->getResourceList()) {
if (path.starts_with(prefix)) {
result.push_back(path);
}
}
return result;
}
if (!fallback_enabled_) {
return result;
}
std::string root = base_path_.empty() ? "data/" + prefix : base_path_ + "/data/" + prefix;
if (!std::filesystem::exists(root)) {
return result;
}
for (const auto& entry : std::filesystem::recursive_directory_iterator(root)) {
if (!entry.is_regular_file()) {
continue;
}
std::string full = entry.path().generic_string();
if (auto pos = full.find("/data/"); pos != std::string::npos) {
result.push_back(full.substr(pos + 6));
} else if (full.starts_with("data/")) {
result.push_back(full.substr(5));
}
}
std::ranges::sort(result);
return result;
}
// Comprovar si existeix un recurs
auto Loader::resourceExists(const std::string& filename) -> bool {
// Comprovar al paquet
if (pack_ && pack_->hasResource(filename)) {
return true;
@@ -81,36 +118,36 @@ auto Loader::resourceExists(const std::string& filename) -> bool {
}
return false;
}
}
// Validar el paquet
auto Loader::validatePack() -> bool {
// Validar el paquet
auto Loader::validatePack() -> bool {
if (!pack_) {
std::cerr << "[ResourceLoader] Advertència: no hay paquet carregat per validar\n";
return false;
}
return pack_->validatePack();
}
}
// Comprovar si hay paquet carregat
auto Loader::isPackLoaded() const -> bool {
// Comprovar si hay paquet carregat
auto Loader::isPackLoaded() const -> bool {
return pack_ != nullptr;
}
}
// Establir la ruta base
void Loader::setBasePath(const std::string& path) {
// Establir la ruta base
void Loader::setBasePath(const std::string& path) {
base_path_ = path;
std::cout << "[ResourceLoader] Ruta base establerta: " << base_path_ << "\n";
}
}
// Obtenir la ruta base
auto Loader::getBasePath() const -> const std::string& {
// Obtenir la ruta base
auto Loader::getBasePath() const -> const std::string& {
return base_path_;
}
}
// Carregar des del sistema de archivos (fallback)
auto Loader::loadFromFilesystem(const std::string& filename) -> std::vector<uint8_t> {
// Carregar des del sistema de archivos (fallback)
auto Loader::loadFromFilesystem(const std::string& filename) -> std::vector<uint8_t> {
// The filename is already normalized (e.g., "shapes/logo/letra_j.shp")
// We need to prepend base_path + "data/"
std::string fullpath;
@@ -138,6 +175,6 @@ auto Loader::loadFromFilesystem(const std::string& filename) -> std::vector<uint
std::cout << "[ResourceLoader] Carregat des del sistema de archivos: " << fullpath << "\n";
return data;
}
}
} // namespace Resource
+8 -3
View File
@@ -12,8 +12,8 @@
namespace Resource {
// Singleton per gestionar la càrrega de recursos
class Loader {
// Singleton per gestionar la càrrega de recursos
class Loader {
public:
// Singleton
static auto get() -> Loader&;
@@ -25,6 +25,11 @@ class Loader {
auto loadResource(const std::string& filename) -> std::vector<uint8_t>;
auto resourceExists(const std::string& filename) -> bool;
// Llistat de recursos amb prefix (ex. "shapes/", "sounds/"). Si hi ha
// pack, retorna els fitxers del pack filtrats; si no, escaneja el
// sistema de fitxers recursivament a `data/<prefix>`.
auto listResources(const std::string& prefix) -> std::vector<std::string>;
// Validació
auto validatePack() -> bool;
[[nodiscard]] auto isPackLoaded() const -> bool;
@@ -48,6 +53,6 @@ class Loader {
// Funciones auxiliars
auto loadFromFilesystem(const std::string& filename) -> std::vector<uint8_t>;
};
};
} // namespace Resource
+15 -3
View File
@@ -12,6 +12,7 @@
#include "core/audio/audio.hpp"
#include "core/audio/audio_adapter.hpp"
#include "core/defaults/window.hpp"
#include "core/graphics/shape_loader.hpp"
#include "core/input/input.hpp"
#include "core/input/mouse.hpp"
#include "core/locale/locale.hpp"
@@ -147,10 +148,21 @@ Director::Director(int argc, char* argv[])
Audio::init(AUDIO_CONFIG);
Audio::get()->applySettings(AUDIO_CONFIG);
AudioResource::getMusic("title.ogg");
AudioResource::getMusic("game.ogg");
// Precàrrega blocant de tots els recursos al boot per evitar hits d'I/O i
// de decodificació en transicions (TITLE → GAME, primera explosió, etc.).
// Mateix patró que aee_arcade: iterem `listResources` i forcem la càrrega
// al cache de cada subsistema.
for (const auto& path : Resource::Helper::listResources("music/")) {
AudioResource::getMusic(path.substr(std::string_view{"music/"}.size()));
}
for (const auto& path : Resource::Helper::listResources("sounds/")) {
AudioResource::getSound(path.substr(std::string_view{"sounds/"}.size()));
}
for (const auto& path : Resource::Helper::listResources("shapes/")) {
Graphics::ShapeLoader::load(path.substr(std::string_view{"shapes/"}.size()));
}
if (cfg_->console) {
std::cout << "Música precacheada\n";
std::cout << "Recursos precachejats (música, sons, shapes)\n";
}
context_ = std::make_unique<SceneContext>();