167 lines
4.6 KiB
C++
167 lines
4.6 KiB
C++
#include "core/resources/asset.h"
|
|
|
|
#include <SDL3/SDL.h>
|
|
|
|
#include <cstddef> // for size_t
|
|
#include <iostream> // for basic_ostream, operator<<, cout, endl
|
|
|
|
#include "core/resources/resource_helper.h"
|
|
|
|
// Instancia única
|
|
Asset *Asset::instance = nullptr;
|
|
|
|
// Singleton API
|
|
void Asset::init(const std::string &executablePath) {
|
|
Asset::instance = new Asset(executablePath);
|
|
}
|
|
|
|
void Asset::destroy() {
|
|
delete Asset::instance;
|
|
Asset::instance = nullptr;
|
|
}
|
|
|
|
auto Asset::get() -> Asset * {
|
|
return Asset::instance;
|
|
}
|
|
|
|
// Constructor
|
|
Asset::Asset(const std::string &executablePath)
|
|
: executable_path_(executablePath.substr(0, executablePath.find_last_of("\\/"))) {
|
|
}
|
|
|
|
// Añade un elemento a la lista
|
|
void Asset::add(const std::string &file, Type type, bool required, bool absolute) {
|
|
Item temp;
|
|
temp.file = absolute ? file : executable_path_ + file;
|
|
temp.type = type;
|
|
temp.required = required;
|
|
file_list_.push_back(temp);
|
|
|
|
const std::string filename = file.substr(file.find_last_of("\\/") + 1);
|
|
longest_name_ = SDL_max(longest_name_, filename.size());
|
|
}
|
|
|
|
// Devuelve el fichero de un elemento de la lista a partir de una cadena
|
|
auto Asset::get(const std::string &text) -> std::string {
|
|
for (const auto &f : file_list_) {
|
|
const size_t lastIndex = f.file.find_last_of('/') + 1;
|
|
const std::string file = f.file.substr(lastIndex);
|
|
|
|
if (file == text) {
|
|
return f.file;
|
|
}
|
|
}
|
|
|
|
if (verbose_) {
|
|
std::cout << "Warning: file " << text.c_str() << " not found" << '\n';
|
|
}
|
|
return "";
|
|
}
|
|
|
|
// Comprueba que existen todos los elementos
|
|
auto Asset::check() -> bool {
|
|
bool success = true;
|
|
|
|
if (verbose_) {
|
|
std::cout << "\n** Checking files" << '\n';
|
|
|
|
std::cout << "Executable path is: " << executable_path_ << '\n';
|
|
std::cout << "Sample filepath: " << file_list_.back().file << '\n';
|
|
}
|
|
|
|
// Comprueba la lista de ficheros clasificandolos por tipo
|
|
for (int i = 0; i < static_cast<int>(Type::COUNT); ++i) {
|
|
const Type TYPE = static_cast<Type>(i);
|
|
|
|
// Comprueba si hay ficheros de ese tipo
|
|
bool any = false;
|
|
|
|
for (const auto &f : file_list_) {
|
|
if (f.required && f.type == TYPE) {
|
|
any = true;
|
|
}
|
|
}
|
|
|
|
// Si hay ficheros de ese tipo, comprueba si existen
|
|
if (any) {
|
|
if (verbose_) {
|
|
std::cout << "\n>> " << getTypeName(TYPE).c_str() << " FILES" << '\n';
|
|
}
|
|
|
|
for (const auto &f : file_list_) {
|
|
if (f.required && f.type == TYPE) {
|
|
success &= checkFile(f.file);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Resultado
|
|
if (verbose_) {
|
|
if (success) {
|
|
std::cout << "\n** All files OK.\n"
|
|
<< '\n';
|
|
} else {
|
|
std::cout << "\n** A file is missing. Exiting.\n"
|
|
<< '\n';
|
|
}
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
// Comprueba que existe un fichero
|
|
auto Asset::checkFile(const std::string &path) const -> bool {
|
|
bool success = false;
|
|
std::string result = "ERROR";
|
|
|
|
// Comprueba si existe el fichero (pack o filesystem)
|
|
const std::string filename = path.substr(path.find_last_of("\\/") + 1);
|
|
if (ResourceHelper::shouldUseResourcePack(path)) {
|
|
auto bytes = ResourceHelper::loadFile(path);
|
|
if (!bytes.empty()) {
|
|
result = "OK";
|
|
success = true;
|
|
}
|
|
} else {
|
|
SDL_IOStream *file = SDL_IOFromFile(path.c_str(), "rb");
|
|
if (file != nullptr) {
|
|
result = "OK";
|
|
success = true;
|
|
SDL_CloseIO(file);
|
|
}
|
|
}
|
|
|
|
if (verbose_) {
|
|
std::cout.setf(std::ios::left, std::ios::adjustfield);
|
|
std::cout << "Checking file: ";
|
|
std::cout.width(longest_name_ + 2);
|
|
std::cout.fill('.');
|
|
std::cout << filename + " ";
|
|
std::cout << " [" + result + "]" << '\n';
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
// Devuelve el nombre del tipo de recurso
|
|
auto Asset::getTypeName(Type type) -> std::string {
|
|
switch (type) {
|
|
case Type::BITMAP: return "BITMAP";
|
|
case Type::MUSIC: return "MUSIC";
|
|
case Type::SOUND: return "SOUND";
|
|
case Type::FONT: return "FONT";
|
|
case Type::LANG: return "LANG";
|
|
case Type::DATA: return "DATA";
|
|
case Type::ROOM: return "ROOM";
|
|
case Type::ENEMY: return "ENEMY";
|
|
case Type::ITEM: return "ITEM";
|
|
case Type::COUNT:
|
|
default: return "ERROR";
|
|
}
|
|
}
|
|
|
|
// Establece si ha de mostrar texto por pantalla
|
|
void Asset::setVerbose(bool value) {
|
|
verbose_ = value;
|
|
} |