Files
coffee-crisis/source/core/resources/asset.cpp
T

177 lines
4.7 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 &executable_path) {
Asset::instance = new Asset(executable_path);
}
void Asset::destroy() {
delete Asset::instance;
Asset::instance = nullptr;
}
auto Asset::get() -> Asset * {
return Asset::instance;
}
// Constructor
Asset::Asset(const std::string &executable_path)
: executable_path_(executable_path.substr(0, executable_path.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 FILE_NAME = file.substr(file.find_last_of("\\/") + 1);
longest_name_ = SDL_max(longest_name_, FILE_NAME.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 LAST_INDEX = f.file.find_last_of('/') + 1;
const std::string FILE_NAME = f.file.substr(LAST_INDEX);
if (FILE_NAME == 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 FILE_NAME = 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 << FILE_NAME + " ";
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;
}