resource_list: loadFromString delega a parsers en namespace anònim
This commit is contained in:
@@ -16,6 +16,71 @@
|
|||||||
|
|
||||||
namespace Resource {
|
namespace Resource {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// Un item del format modern: pot ser string (path) o mapping ({path, required?, absolute?})
|
||||||
|
void parseAssetItem(List& list, const fkyaml::node& item, List::Type type, const std::string& prefix, const std::string& system_folder, const std::string& category, const std::string& type_str) {
|
||||||
|
try {
|
||||||
|
if (item.is_string()) {
|
||||||
|
auto path = List::replaceVariables(item.get_value<std::string>(), prefix, system_folder);
|
||||||
|
list.add(path, type, true, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (item.is_mapping() && item.contains("path")) {
|
||||||
|
auto path = List::replaceVariables(item["path"].get_value<std::string>(), prefix, system_folder);
|
||||||
|
const bool REQUIRED = !item.contains("required") || item["required"].get_value<bool>();
|
||||||
|
const bool ABSOLUTE = item.contains("absolute") && item["absolute"].get_value<bool>();
|
||||||
|
list.add(path, type, REQUIRED, ABSOLUTE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: Invalid item in type '%s', category '%s', skipping", type_str.c_str(), category.c_str());
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error parsing asset in category '%s', type '%s': %s", category.c_str(), type_str.c_str(), e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// (TIPO: [items...]) del format modern. Itera els items i delega a parseAssetItem.
|
||||||
|
void parseModernType(List& list, const fkyaml::node& items_node, List::Type type, const std::string& type_str, const std::string& category, const std::string& prefix, const std::string& system_folder) {
|
||||||
|
if (!items_node.is_sequence()) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: Type '%s' in category '%s' is not a sequence, skipping", type_str.c_str(), category.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const auto& item : items_node) {
|
||||||
|
parseAssetItem(list, item, type, prefix, system_folder, category, type_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// {type, path, required?, absolute?} del format antic
|
||||||
|
void parseLegacyAsset(List& list, const fkyaml::node& asset, const std::string& category, const std::string& prefix, const std::string& system_folder) {
|
||||||
|
try {
|
||||||
|
if (!asset.contains("type") || !asset.contains("path")) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: Asset in category '%s' missing 'type' or 'path', skipping", category.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto type_str = asset["type"].get_value<std::string>();
|
||||||
|
auto path = asset["path"].get_value<std::string>();
|
||||||
|
const bool REQUIRED = !asset.contains("required") || asset["required"].get_value<bool>();
|
||||||
|
const bool ABSOLUTE = asset.contains("absolute") && asset["absolute"].get_value<bool>();
|
||||||
|
path = List::replaceVariables(path, prefix, system_folder);
|
||||||
|
list.add(path, List::parseAssetType(type_str), REQUIRED, ABSOLUTE);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error parsing asset in category '%s': %s", category.c_str(), e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Categoria amb format modern (TIPO → [items]). Itera els tipus.
|
||||||
|
void parseModernCategory(List& list, const fkyaml::node& category_assets, const std::string& category, const std::string& prefix, const std::string& system_folder) {
|
||||||
|
for (auto type_it = category_assets.begin(); type_it != category_assets.end(); ++type_it) {
|
||||||
|
try {
|
||||||
|
auto type_str = type_it.key().get_value<std::string>();
|
||||||
|
const List::Type TYPE = List::parseAssetType(type_str);
|
||||||
|
parseModernType(list, type_it.value(), TYPE, type_str, category, prefix, system_folder);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error parsing type in category '%s': %s", category.c_str(), e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
// Singleton
|
// Singleton
|
||||||
List* List::instance = nullptr;
|
List* List::instance = nullptr;
|
||||||
|
|
||||||
@@ -160,17 +225,13 @@ namespace Resource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Carga recursos desde un string de configuración (para release con pack)
|
// Carga recursos desde un string de configuración (para release con pack)
|
||||||
void List::loadFromString(const std::string& config_content, const std::string& prefix, const std::string& system_folder) { // NOLINT(readability-function-cognitive-complexity)
|
void List::loadFromString(const std::string& config_content, const std::string& prefix, const std::string& system_folder) {
|
||||||
try {
|
try {
|
||||||
// Parsear YAML
|
|
||||||
auto yaml = fkyaml::node::deserialize(config_content);
|
auto yaml = fkyaml::node::deserialize(config_content);
|
||||||
|
|
||||||
// Verificar estructura básica
|
|
||||||
if (!yaml.contains("assets")) {
|
if (!yaml.contains("assets")) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid assets.yaml format - missing 'assets' key");
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid assets.yaml format - missing 'assets' key");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& assets = yaml["assets"];
|
const auto& assets = yaml["assets"];
|
||||||
|
|
||||||
// Iterar sobre cada categoría (fonts, palettes, etc.)
|
// Iterar sobre cada categoría (fonts, palettes, etc.)
|
||||||
@@ -179,105 +240,19 @@ namespace Resource {
|
|||||||
const auto& category_assets = it.value();
|
const auto& category_assets = it.value();
|
||||||
|
|
||||||
if (category_assets.is_mapping()) {
|
if (category_assets.is_mapping()) {
|
||||||
// Nuevo formato: categoría → { TIPO: [paths...], TIPO2: [paths...] }
|
parseModernCategory(*this, category_assets, category, prefix, system_folder);
|
||||||
for (auto type_it = category_assets.begin(); type_it != category_assets.end(); ++type_it) {
|
|
||||||
try {
|
|
||||||
auto type_str = type_it.key().get_value<std::string>();
|
|
||||||
Type type = parseAssetType(type_str);
|
|
||||||
const auto& items = type_it.value();
|
|
||||||
|
|
||||||
if (!items.is_sequence()) {
|
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Warning: Type '%s' in category '%s' is not a sequence, skipping",
|
|
||||||
type_str.c_str(),
|
|
||||||
category.c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& item : items) {
|
|
||||||
try {
|
|
||||||
if (item.is_string()) {
|
|
||||||
// Formato simple: solo el path
|
|
||||||
auto path = replaceVariables(item.get_value<std::string>(), prefix, system_folder);
|
|
||||||
addToMap(path, type, true, false);
|
|
||||||
} else if (item.is_mapping() && item.contains("path")) {
|
|
||||||
// Formato expandido: { path, required?, absolute? }
|
|
||||||
auto path = replaceVariables(item["path"].get_value<std::string>(), prefix, system_folder);
|
|
||||||
bool required = !item.contains("required") || item["required"].get_value<bool>();
|
|
||||||
bool absolute = item.contains("absolute") && item["absolute"].get_value<bool>();
|
|
||||||
addToMap(path, type, required, absolute);
|
|
||||||
} else {
|
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Warning: Invalid item in type '%s', category '%s', skipping",
|
|
||||||
type_str.c_str(),
|
|
||||||
category.c_str());
|
|
||||||
}
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Error parsing asset in category '%s', type '%s': %s",
|
|
||||||
category.c_str(),
|
|
||||||
type_str.c_str(),
|
|
||||||
e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Error parsing type in category '%s': %s",
|
|
||||||
category.c_str(),
|
|
||||||
e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (category_assets.is_sequence()) {
|
} else if (category_assets.is_sequence()) {
|
||||||
// Formato antiguo (retrocompatibilidad): categoría → [{type, path}, ...]
|
for (const auto& asset : category_assets) { parseLegacyAsset(*this, asset, category, prefix, system_folder); }
|
||||||
for (const auto& asset : category_assets) {
|
|
||||||
try {
|
|
||||||
if (!asset.contains("type") || !asset.contains("path")) {
|
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Warning: Asset in category '%s' missing 'type' or 'path', skipping",
|
|
||||||
category.c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto type_str = asset["type"].get_value<std::string>();
|
|
||||||
auto path = asset["path"].get_value<std::string>();
|
|
||||||
bool required = true;
|
|
||||||
bool absolute = false;
|
|
||||||
|
|
||||||
if (asset.contains("required")) {
|
|
||||||
required = asset["required"].get_value<bool>();
|
|
||||||
}
|
|
||||||
if (asset.contains("absolute")) {
|
|
||||||
absolute = asset["absolute"].get_value<bool>();
|
|
||||||
}
|
|
||||||
|
|
||||||
path = replaceVariables(path, prefix, system_folder);
|
|
||||||
Type type = parseAssetType(type_str);
|
|
||||||
addToMap(path, type, required, absolute);
|
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Error parsing asset in category '%s': %s",
|
|
||||||
category.c_str(),
|
|
||||||
e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: Category '%s' has invalid format, skipping", category.c_str());
|
||||||
"Warning: Category '%s' has invalid format, skipping",
|
|
||||||
category.c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Loaded " << file_list_.size() << " assets from YAML config" << '\n';
|
std::cout << "Loaded " << file_list_.size() << " assets from YAML config" << '\n';
|
||||||
|
|
||||||
} catch (const fkyaml::exception& e) {
|
} catch (const fkyaml::exception& e) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "YAML parsing error: %s", e.what());
|
||||||
"YAML parsing error: %s",
|
|
||||||
e.what());
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error loading assets: %s", e.what());
|
||||||
"Error loading assets: %s",
|
|
||||||
e.what());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ namespace Resource {
|
|||||||
[[nodiscard]] auto getListByType(Type type) const -> std::vector<std::string>;
|
[[nodiscard]] auto getListByType(Type type) const -> std::vector<std::string>;
|
||||||
[[nodiscard]] auto exists(const std::string& filename) const -> bool; // Verifica si un asset existe
|
[[nodiscard]] auto exists(const std::string& filename) const -> bool; // Verifica si un asset existe
|
||||||
|
|
||||||
|
// --- Helpers static (públics perquè els fan servir parsers externs del .cpp) ---
|
||||||
|
[[nodiscard]] static auto parseAssetType(const std::string& type_str) -> Type; // Convierte string a tipo
|
||||||
|
[[nodiscard]] static auto replaceVariables(const std::string& path, const std::string& prefix, const std::string& system_folder) -> std::string; // Reemplaza variables en la ruta
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Estructuras privadas ---
|
// --- Estructuras privadas ---
|
||||||
struct Item {
|
struct Item {
|
||||||
@@ -63,9 +67,7 @@ namespace Resource {
|
|||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
[[nodiscard]] static auto getTypeName(Type type) -> std::string; // Obtiene el nombre del tipo
|
[[nodiscard]] static auto getTypeName(Type type) -> std::string; // Obtiene el nombre del tipo
|
||||||
[[nodiscard]] static auto parseAssetType(const std::string& type_str) -> Type; // Convierte string a tipo
|
|
||||||
void addToMap(const std::string& file_path, Type type, bool required, bool absolute); // Añade archivo al mapa
|
void addToMap(const std::string& file_path, Type type, bool required, bool absolute); // Añade archivo al mapa
|
||||||
[[nodiscard]] static auto replaceVariables(const std::string& path, const std::string& prefix, const std::string& system_folder) -> std::string; // Reemplaza variables en la ruta
|
|
||||||
static auto parseOptions(const std::string& options, bool& required, bool& absolute) -> void; // Parsea opciones
|
static auto parseOptions(const std::string& options, bool& required, bool& absolute) -> void; // Parsea opciones
|
||||||
|
|
||||||
// --- Constructores y destructor privados (singleton) ---
|
// --- Constructores y destructor privados (singleton) ---
|
||||||
|
|||||||
Reference in New Issue
Block a user