183 lines
5.4 KiB
C++
183 lines
5.4 KiB
C++
// resource_helper.cpp
|
|
// Resource helper implementation
|
|
|
|
#include "resource_helper.hpp"
|
|
|
|
#include <algorithm>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
|
|
#include "resource_loader.hpp"
|
|
|
|
namespace Resource::Helper {
|
|
|
|
static bool resource_system_initialized = false;
|
|
|
|
// Initialize the resource system
|
|
auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback)
|
|
-> bool {
|
|
if (resource_system_initialized) {
|
|
std::cout << "ResourceHelper: Already initialized\n";
|
|
return true;
|
|
}
|
|
|
|
std::cout << "ResourceHelper: Initializing with pack: " << pack_file << '\n';
|
|
std::cout << "ResourceHelper: Fallback enabled: " << (enable_fallback ? "Yes" : "No")
|
|
<< '\n';
|
|
|
|
bool success = Loader::get().initialize(pack_file, enable_fallback);
|
|
if (success) {
|
|
resource_system_initialized = true;
|
|
std::cout << "ResourceHelper: Initialization successful\n";
|
|
} else {
|
|
std::cerr << "ResourceHelper: Initialization failed\n";
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
// Shutdown the resource system
|
|
void shutdownResourceSystem() {
|
|
if (resource_system_initialized) {
|
|
Loader::get().shutdown();
|
|
resource_system_initialized = false;
|
|
std::cout << "ResourceHelper: Shutdown complete\n";
|
|
}
|
|
}
|
|
|
|
// Load a file
|
|
auto loadFile(const std::string& filepath) -> std::vector<uint8_t> {
|
|
if (!resource_system_initialized) {
|
|
std::cerr << "ResourceHelper: System not initialized, loading from filesystem\n";
|
|
// Fallback to direct filesystem access
|
|
std::ifstream file(filepath, std::ios::binary | std::ios::ate);
|
|
if (!file) {
|
|
return {};
|
|
}
|
|
std::streamsize file_size = file.tellg();
|
|
file.seekg(0, std::ios::beg);
|
|
std::vector<uint8_t> data(file_size);
|
|
file.read(reinterpret_cast<char*>(data.data()), file_size);
|
|
return data;
|
|
}
|
|
|
|
// Determine if we should use the pack
|
|
if (shouldUseResourcePack(filepath)) {
|
|
// Convert to pack path
|
|
std::string pack_path = getPackPath(filepath);
|
|
|
|
// Try to load from pack
|
|
auto data = Loader::get().loadResource(pack_path);
|
|
if (!data.empty()) {
|
|
return data;
|
|
}
|
|
|
|
// If pack loading failed, try filesystem as fallback
|
|
std::cerr << "ResourceHelper: Pack failed for " << pack_path
|
|
<< ", trying filesystem\n";
|
|
}
|
|
|
|
// Load from filesystem
|
|
return Loader::get().loadResource(filepath);
|
|
}
|
|
|
|
// Check if a file exists
|
|
auto fileExists(const std::string& filepath) -> bool {
|
|
if (!resource_system_initialized) {
|
|
return std::filesystem::exists(filepath);
|
|
}
|
|
|
|
// Check pack if appropriate
|
|
if (shouldUseResourcePack(filepath)) {
|
|
std::string pack_path = getPackPath(filepath);
|
|
if (Loader::get().resourceExists(pack_path)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Check filesystem
|
|
return std::filesystem::exists(filepath);
|
|
}
|
|
|
|
// Convert asset path to pack path
|
|
auto getPackPath(const std::string& asset_path) -> std::string {
|
|
std::string path = asset_path;
|
|
|
|
// Convert backslashes to forward slashes
|
|
std::ranges::replace(path, '\\', '/');
|
|
|
|
// If it's an absolute path containing "/data/", extract everything after "/data/"
|
|
// This handles paths like: /Users/sergio/.../data/palette/file.pal -> palette/file.pal
|
|
size_t data_pos = path.find("/data/");
|
|
if (data_pos != std::string::npos) {
|
|
return path.substr(data_pos + 6); // +6 to skip "/data/"
|
|
}
|
|
|
|
// Remove leading slashes
|
|
while (!path.empty() && path[0] == '/') {
|
|
path = path.substr(1);
|
|
}
|
|
|
|
// Remove "./" prefix if present
|
|
if (path.starts_with("./")) {
|
|
path = path.substr(2);
|
|
}
|
|
|
|
// Remove "../" prefixes (for macOS bundle paths in development)
|
|
while (path.starts_with("../")) {
|
|
path = path.substr(3);
|
|
}
|
|
|
|
// Remove "Resources/" prefix if present (for macOS bundle)
|
|
const std::string RESOURCES_PREFIX = "Resources/";
|
|
if (path.starts_with(RESOURCES_PREFIX)) {
|
|
path = path.substr(RESOURCES_PREFIX.length());
|
|
}
|
|
|
|
// Remove "data/" prefix if present
|
|
const std::string DATA_PREFIX = "data/";
|
|
if (path.starts_with(DATA_PREFIX)) {
|
|
path = path.substr(DATA_PREFIX.length());
|
|
}
|
|
|
|
return path;
|
|
}
|
|
|
|
// Check if file should use resource pack
|
|
auto shouldUseResourcePack(const std::string& filepath) -> bool {
|
|
std::string path = filepath;
|
|
std::ranges::replace(path, '\\', '/');
|
|
|
|
// Don't use pack for most config files (except config/assets.yaml which is loaded
|
|
// directly via Loader::loadAssetsConfig() in release builds)
|
|
if (path.find("config/") != std::string::npos) {
|
|
return false;
|
|
}
|
|
|
|
// Use pack for data files
|
|
if (path.find("data/") != std::string::npos) {
|
|
return true;
|
|
}
|
|
|
|
// Check if it looks like a data file (has common extensions)
|
|
if (path.find(".ogg") != std::string::npos || path.find(".wav") != std::string::npos ||
|
|
path.find(".gif") != std::string::npos || path.find(".png") != std::string::npos ||
|
|
path.find(".pal") != std::string::npos || path.find(".yaml") != std::string::npos ||
|
|
path.find(".txt") != std::string::npos || path.find(".glsl") != std::string::npos) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Check if pack is loaded
|
|
auto isPackLoaded() -> bool {
|
|
if (!resource_system_initialized) {
|
|
return false;
|
|
}
|
|
return Loader::get().isPackLoaded();
|
|
}
|
|
|
|
} // namespace Resource::Helper
|