MetaCore/Source/MetaCoreFoundation/Private/MetaCoreAssetRegistry.cpp

134 lines
5.1 KiB
C++

#include "MetaCoreFoundation/MetaCoreAssetRegistry.h"
#include <nlohmann/json.hpp>
#include <fstream>
#include <algorithm>
namespace MetaCore {
MetaCoreAssetRegistry& MetaCoreAssetRegistry::Get() {
static MetaCoreAssetRegistry instance;
return instance;
}
void MetaCoreAssetRegistry::ScanDirectory(const std::filesystem::path& rootPath) {
if (!std::filesystem::exists(rootPath) || !std::filesystem::is_directory(rootPath)) {
return;
}
// 遍历指定目录下的所有文件,寻找 .mcmeta 文件
for (const auto& entry : std::filesystem::recursive_directory_iterator(rootPath)) {
if (!entry.is_regular_file() || entry.path().extension() != ".mcmeta") {
continue;
}
std::ifstream file(entry.path());
if (!file.is_open()) {
continue;
}
try {
nlohmann::json json;
file >> json;
if (json.contains("guid") && json["guid"].is_string() &&
json.contains("source_path") && json["source_path"].is_string()) {
const std::string guidStr = json["guid"].get<std::string>();
const std::string sourcePathStr = json["source_path"].get<std::string>();
auto parsedGuid = MetaCoreAssetGuid::Parse(guidStr);
if (parsedGuid.has_value()) {
// 规格化路径,确保斜杠在跨平台的一致性
std::filesystem::path portablePath(sourcePathStr);
RegisterAsset(*parsedGuid, portablePath);
// 顺便注册该主模型派生的所有子资产(如 mesh, material 等)
if (json.contains("sub_assets") && json["sub_assets"].is_array()) {
for (const auto& subAssetJson : json["sub_assets"]) {
if (subAssetJson.contains("guid") && subAssetJson["guid"].is_string()) {
const std::string subGuidStr = subAssetJson["guid"].get<std::string>();
auto parsedSubGuid = MetaCoreAssetGuid::Parse(subGuidStr);
if (parsedSubGuid.has_value()) {
RegisterAsset(*parsedSubGuid, portablePath);
}
}
}
}
}
}
} catch (...) {
// 尝试作为二进制 mcmeta 包后备解析 (对标旧资源兼容)
try {
std::ifstream binFile(entry.path(), std::ios::binary);
if (binFile.is_open()) {
char headerBytes[32];
if (binFile.read(headerBytes, 32)) {
std::uint32_t magic = 0;
std::uint32_t formatVersion = 0;
std::memcpy(&magic, headerBytes, 4);
std::memcpy(&formatVersion, headerBytes + 4, 4);
if (magic == 0x4D434F52U && formatVersion == 1U) {
MetaCoreAssetGuid packageGuid{};
std::memcpy(packageGuid.Bytes.data(), headerBytes + 16, 16);
if (packageGuid.IsValid()) {
std::filesystem::path mcmetaPath = entry.path();
std::filesystem::path sourceRelativePath = mcmetaPath.parent_path() / mcmetaPath.stem();
std::filesystem::path relativeToProject = sourceRelativePath.lexically_relative(rootPath.parent_path());
RegisterAsset(packageGuid, relativeToProject);
}
}
}
}
} catch (...) {
// 彻底忽略损坏的文件
}
}
}
}
bool MetaCoreAssetRegistry::RegisterAsset(const MetaCoreAssetGuid& guid, const std::filesystem::path& relativePath) {
if (!guid.IsValid()) {
return false;
}
// 将路径规范化为通用字符串(统一斜杠)
std::string keyPath = relativePath.generic_string();
std::transform(keyPath.begin(), keyPath.end(), keyPath.begin(), ::tolower);
GuidToPath_[guid] = relativePath;
PathToGuid_[keyPath] = guid;
return true;
}
void MetaCoreAssetRegistry::Clear() {
GuidToPath_.clear();
PathToGuid_.clear();
}
std::filesystem::path MetaCoreAssetRegistry::ResolveGuidToPath(const MetaCoreAssetGuid& guid) const {
const auto it = GuidToPath_.find(guid);
if (it != GuidToPath_.end()) {
return it->second;
}
return {};
}
MetaCoreAssetGuid MetaCoreAssetRegistry::ResolvePathToGuid(const std::filesystem::path& relativePath) const {
std::string keyPath = relativePath.generic_string();
std::transform(keyPath.begin(), keyPath.end(), keyPath.begin(), ::tolower);
const auto it = PathToGuid_.find(keyPath);
if (it != PathToGuid_.end()) {
return it->second;
}
return {};
}
bool MetaCoreAssetRegistry::HasAsset(const MetaCoreAssetGuid& guid) const {
return GuidToPath_.count(guid) > 0;
}
} // namespace MetaCore