#include "MetaCoreFoundation/MetaCoreAssetRegistry.h" #include #include #include 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(); const std::string sourcePathStr = json["source_path"].get(); 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()) { RegisterSubAsset(*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; } UnregisterAsset(guid); const std::string keyPath = NormalizePathKey(relativePath); GuidToPath_[guid] = relativePath; PathToGuid_[keyPath] = guid; PrimaryAssetGuids_.insert(guid); return true; } bool MetaCoreAssetRegistry::RegisterSubAsset(const MetaCoreAssetGuid& guid, const std::filesystem::path& relativePath) { if (!guid.IsValid()) { return false; } UnregisterAsset(guid); GuidToPath_[guid] = relativePath; return true; } void MetaCoreAssetRegistry::UnregisterAsset(const MetaCoreAssetGuid& guid) { const auto iterator = GuidToPath_.find(guid); if (iterator == GuidToPath_.end()) { return; } const std::string keyPath = NormalizePathKey(iterator->second); if (const auto pathIterator = PathToGuid_.find(keyPath); pathIterator != PathToGuid_.end() && pathIterator->second == guid) { PathToGuid_.erase(pathIterator); } GuidToPath_.erase(iterator); PrimaryAssetGuids_.erase(guid); } bool MetaCoreAssetRegistry::MoveAsset(const MetaCoreAssetGuid& guid, const std::filesystem::path& newRelativePath) { if (!guid.IsValid() || !GuidToPath_.contains(guid)) { return false; } const bool isPrimaryAsset = PrimaryAssetGuids_.contains(guid); return isPrimaryAsset ? RegisterAsset(guid, newRelativePath) : RegisterSubAsset(guid, newRelativePath); } void MetaCoreAssetRegistry::Clear() { GuidToPath_.clear(); PathToGuid_.clear(); PrimaryAssetGuids_.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 { const std::string keyPath = NormalizePathKey(relativePath); const auto it = PathToGuid_.find(keyPath); if (it != PathToGuid_.end()) { return it->second; } return {}; } std::string MetaCoreAssetRegistry::NormalizePathKey(const std::filesystem::path& path) { std::string keyPath = path.lexically_normal().generic_string(); #if defined(_WIN32) std::transform(keyPath.begin(), keyPath.end(), keyPath.begin(), [](unsigned char value) { return value >= 'A' && value <= 'Z' ? static_cast(value - 'A' + 'a') : static_cast(value); }); #endif return keyPath; } bool MetaCoreAssetRegistry::HasAsset(const MetaCoreAssetGuid& guid) const { return GuidToPath_.count(guid) > 0; } } // namespace MetaCore