Files
Frostbite2D/Fostbite2D/src/fostbite2D/utils/asset.cpp
Lenheart 9f29192ae8 feat(平台): 添加Switch平台支持并实现资源管理器
- 新增Switch平台初始化与清理功能
- 实现Asset资源管理器类,提供文件读写、路径处理等功能
- 完善Window类的销毁逻辑,释放SDL资源
- 更新Switch平台编译配置,移除冗余标志
- 在主程序中集成资源管理器功能
2026-02-21 03:34:48 +08:00

436 lines
11 KiB
C++

#include <fostbite2D/utils/asset.h>
#include <fstream>
#include <sstream>
#include <system_error>
namespace frostbite2D {
Asset &Asset::get() {
static Asset instance;
return instance;
}
fs::path Asset::toPath(const std::string &path) const {
#ifdef _WIN32
return fs::u8path(path);
#else
return fs::path(path);
#endif
}
std::string Asset::fromPath(const fs::path &path) const {
#ifdef _WIN32
return path.u8string();
#else
return path.string();
#endif
}
std::string Asset::resolveFullPath(const std::string &path) const {
if (path.empty()) {
return path;
}
fs::path p = toPath(path);
if (p.is_absolute()) {
return path;
}
if (!workingDirectory_.empty()) {
return fromPath(toPath(workingDirectory_) / p);
}
return path;
}
bool Asset::readTextFile(const std::string &path, std::string &outContent) {
std::string fullPath = resolveFullPath(path);
if (!exists(fullPath)) {
return false;
}
std::ifstream file(toPath(fullPath), std::ios::in | std::ios::binary);
if (!file.is_open()) {
return false;
}
std::ostringstream ss;
ss << file.rdbuf();
outContent = ss.str();
file.close();
return true;
}
bool Asset::writeTextFile(const std::string &path, const std::string &content,
bool append) {
std::string fullPath = resolveFullPath(path);
auto mode = std::ios::out;
if (append) {
mode |= std::ios::app;
}
std::ofstream file(toPath(fullPath), mode);
if (!file.is_open()) {
return false;
}
file << content;
file.close();
return true;
}
bool Asset::readBinaryFile(const std::string &path,
std::vector<uint8> &outData) {
std::string fullPath = resolveFullPath(path);
if (!exists(fullPath)) {
return false;
}
std::ifstream file(toPath(fullPath), std::ios::in | std::ios::binary);
if (!file.is_open()) {
return false;
}
file.seekg(0, std::ios::end);
auto size = file.tellg();
file.seekg(0, std::ios::beg);
outData.resize(static_cast<size_t>(size));
file.read(reinterpret_cast<char *>(outData.data()), size);
file.close();
return true;
}
bool Asset::writeBinaryFile(const std::string &path,
const std::vector<uint8> &data, bool append) {
std::string fullPath = resolveFullPath(path);
auto mode = std::ios::out | std::ios::binary;
if (append) {
mode |= std::ios::app;
}
std::ofstream file(toPath(fullPath), mode);
if (!file.is_open()) {
return false;
}
file.write(reinterpret_cast<const char *>(data.data()), data.size());
file.close();
return true;
}
bool Asset::exists(const std::string &path) const {
std::error_code ec;
return fs::exists(toPath(resolveFullPath(path)), ec);
}
bool Asset::isDirectory(const std::string &path) const {
std::error_code ec;
return fs::is_directory(toPath(resolveFullPath(path)), ec);
}
bool Asset::isRegularFile(const std::string &path) const {
std::error_code ec;
return fs::is_regular_file(toPath(resolveFullPath(path)), ec);
}
bool Asset::createDirectory(const std::string &path) {
std::error_code ec;
return fs::create_directory(toPath(resolveFullPath(path)), ec);
}
bool Asset::createDirectories(const std::string &path) {
std::error_code ec;
return fs::create_directories(toPath(resolveFullPath(path)), ec);
}
bool Asset::removeFile(const std::string &path) {
std::error_code ec;
return fs::remove(toPath(resolveFullPath(path)), ec);
}
bool Asset::removeDirectory(const std::string &path) {
std::error_code ec;
return fs::remove_all(toPath(resolveFullPath(path)), ec) > 0;
}
bool Asset::copyFile(const std::string &from, const std::string &to,
bool overwrite) {
std::error_code ec;
auto options =
overwrite ? fs::copy_options::overwrite_existing : fs::copy_options::none;
return fs::copy_file(toPath(resolveFullPath(from)),
toPath(resolveFullPath(to)), options, ec);
}
bool Asset::moveFile(const std::string &from, const std::string &to) {
std::error_code ec;
fs::rename(toPath(resolveFullPath(from)), toPath(resolveFullPath(to)), ec);
return !ec;
}
bool Asset::rename(const std::string &oldPath, const std::string &newPath) {
std::error_code ec;
fs::rename(toPath(resolveFullPath(oldPath)), toPath(resolveFullPath(newPath)),
ec);
return !ec;
}
std::vector<std::string> Asset::listFiles(const std::string &directoryPath,
bool recursive) {
std::vector<std::string> files;
fs::path fullPath = toPath(resolveFullPath(directoryPath));
std::error_code ec;
if (!fs::exists(fullPath, ec) || !fs::is_directory(fullPath, ec)) {
return files;
}
try {
if (recursive) {
for (const auto &entry : fs::recursive_directory_iterator(fullPath, ec)) {
if (entry.is_regular_file()) {
files.push_back(fromPath(entry.path()));
}
}
} else {
for (const auto &entry : fs::directory_iterator(fullPath, ec)) {
if (entry.is_regular_file()) {
files.push_back(fromPath(entry.path()));
}
}
}
} catch (...) {
}
return files;
}
std::vector<std::string>
Asset::listDirectories(const std::string &directoryPath, bool recursive) {
std::vector<std::string> directories;
fs::path fullPath = toPath(resolveFullPath(directoryPath));
std::error_code ec;
if (!fs::exists(fullPath, ec) || !fs::is_directory(fullPath, ec)) {
return directories;
}
try {
if (recursive) {
for (const auto &entry : fs::recursive_directory_iterator(fullPath, ec)) {
if (entry.is_directory()) {
directories.push_back(fromPath(entry.path()));
}
}
} else {
for (const auto &entry : fs::directory_iterator(fullPath, ec)) {
if (entry.is_directory()) {
directories.push_back(fromPath(entry.path()));
}
}
}
} catch (...) {
}
return directories;
}
std::vector<std::string> Asset::listAll(const std::string &directoryPath,
bool recursive) {
std::vector<std::string> items;
fs::path fullPath = toPath(resolveFullPath(directoryPath));
std::error_code ec;
if (!fs::exists(fullPath, ec) || !fs::is_directory(fullPath, ec)) {
return items;
}
try {
if (recursive) {
for (const auto &entry : fs::recursive_directory_iterator(fullPath, ec)) {
items.push_back(fromPath(entry.path()));
}
} else {
for (const auto &entry : fs::directory_iterator(fullPath, ec)) {
items.push_back(fromPath(entry.path()));
}
}
} catch (...) {
}
return items;
}
std::vector<std::string>
Asset::listFilesWithExtension(const std::string &directoryPath,
const std::string &extension, bool recursive) {
std::vector<std::string> files;
fs::path fullPath = toPath(resolveFullPath(directoryPath));
fs::path ext = toPath(extension);
std::error_code ec;
if (!fs::exists(fullPath, ec) || !fs::is_directory(fullPath, ec)) {
return files;
}
try {
if (recursive) {
for (const auto &entry : fs::recursive_directory_iterator(fullPath, ec)) {
if (entry.is_regular_file() && entry.path().extension() == ext) {
files.push_back(fromPath(entry.path()));
}
}
} else {
for (const auto &entry : fs::directory_iterator(fullPath, ec)) {
if (entry.is_regular_file() && entry.path().extension() == ext) {
files.push_back(fromPath(entry.path()));
}
}
}
} catch (...) {
}
return files;
}
FileInfo Asset::getFileInfo(const std::string &path) {
FileInfo info;
std::string fullPath = resolveFullPath(path);
info.fullPath = fullPath;
if (!exists(fullPath)) {
info.exists = false;
return info;
}
info.exists = true;
info.isDirectory = isDirectory(fullPath);
info.isRegularFile = isRegularFile(fullPath);
fs::path p = toPath(fullPath);
info.name = fromPath(p.filename());
info.extension = fromPath(p.extension());
if (info.isRegularFile) {
std::error_code ec;
info.size = fs::file_size(p, ec);
if (ec) {
info.size = 0;
}
}
return info;
}
std::string Asset::getFileName(const std::string &path) const {
return fromPath(toPath(path).filename());
}
std::string Asset::getFileNameWithoutExtension(const std::string &path) const {
return fromPath(toPath(path).stem());
}
std::string Asset::getExtension(const std::string &path) const {
return fromPath(toPath(path).extension());
}
std::string Asset::getParentPath(const std::string &path) const {
return fromPath(toPath(path).parent_path());
}
std::string Asset::getAbsolutePath(const std::string &path) const {
std::error_code ec;
return fromPath(fs::absolute(toPath(resolveFullPath(path)), ec));
}
std::string Asset::getCanonicalPath(const std::string &path) const {
std::error_code ec;
return fromPath(fs::canonical(toPath(resolveFullPath(path)), ec));
}
std::string Asset::getCurrentPath() const {
std::error_code ec;
return fromPath(fs::current_path(ec));
}
bool Asset::setCurrentPath(const std::string &path) {
std::error_code ec;
fs::current_path(toPath(path), ec);
return !ec;
}
std::string Asset::combinePath(const std::string &left,
const std::string &right) const {
return fromPath(toPath(left) / toPath(right));
}
std::string Asset::normalizePath(const std::string &path) const {
std::error_code ec;
auto p = fs::absolute(toPath(resolveFullPath(path)), ec);
if (ec) {
return path;
}
return fromPath(p.make_preferred());
}
uint64 Asset::getFileSize(const std::string &path) const {
std::error_code ec;
auto size = fs::file_size(toPath(resolveFullPath(path)), ec);
if (ec) {
return 0;
}
return size;
}
bool Asset::isEmpty(const std::string &path) const {
std::error_code ec;
return fs::is_empty(toPath(resolveFullPath(path)), ec);
}
std::optional<std::string> Asset::readFileToString(const std::string &path) {
std::string content;
if (readTextFile(path, content)) {
return content;
}
return std::nullopt;
}
std::optional<std::vector<uint8>>
Asset::readFileToBytes(const std::string &path) {
std::vector<uint8> data;
if (readBinaryFile(path, data)) {
return data;
}
return std::nullopt;
}
void Asset::setWorkingDirectory(const std::string &path) {
workingDirectory_ = path;
}
const std::string &Asset::getWorkingDirectory() const {
return workingDirectory_;
}
std::string Asset::resolvePath(const std::string &relativePath) const {
return resolveFullPath(relativePath);
}
void Asset::setAssetRoot(const std::string &root) { assetRoot_ = root; }
const std::string &Asset::getAssetRoot() const { return assetRoot_; }
std::string Asset::resolveAssetPath(const std::string &relativePath) const {
if (assetRoot_.empty()) {
return resolveFullPath(relativePath);
}
return resolveFullPath(combinePath(assetRoot_, relativePath));
}
} // namespace frostbite2D