#include "MetaCoreFoundation/MetaCoreAssetRegistry.h" #include #include #include #include namespace MetaCore { MetaCoreAssetRegistry& MetaCoreAssetRegistry::Get() { static MetaCoreAssetRegistry instance; return instance; } void MetaCoreAssetRegistry::ScanDirectory(const std::filesystem::path& rootPath) { std::error_code error; if (!std::filesystem::is_directory(rootPath, error)) { return; } // 遍历指定目录下的所有文件,寻找 .mcmeta 文件 std::error_code iteratorError; for (std::filesystem::recursive_directory_iterator iterator(rootPath, std::filesystem::directory_options::skip_permission_denied, iteratorError), end; iterator != end; iterator.increment(iteratorError)) { if (iteratorError) { iteratorError.clear(); continue; } const auto& entry = *iterator; std::error_code entryError; if (!entry.is_regular_file(entryError) || 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(); const std::string sourcePathStr = json["source_path"].get(); const std::filesystem::path sourcePath = rootPath.parent_path() / std::filesystem::path(sourcePathStr); std::error_code sourceError; if (!std::filesystem::exists(sourcePath, sourceError)) { continue; } 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(); 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