diff --git a/SandboxProject/Library/Cooked/Windows/42011f8d-0404-4168-9910-71a4e7ddd13e_08b298c97945ab53.mccooked b/SandboxProject/Library/Cooked/Windows/42011f8d-0404-4168-9910-71a4e7ddd13e_08b298c97945ab53.mccooked new file mode 100644 index 0000000..9a6ed48 Binary files /dev/null and b/SandboxProject/Library/Cooked/Windows/42011f8d-0404-4168-9910-71a4e7ddd13e_08b298c97945ab53.mccooked differ diff --git a/SandboxProject/Library/Cooked/Windows/4a2a315a-ef41-4931-b0f2-0e286fd34df4_4aace3861e64b31f.mccooked b/SandboxProject/Library/Cooked/Windows/4a2a315a-ef41-4931-b0f2-0e286fd34df4_4aace3861e64b31f.mccooked new file mode 100644 index 0000000..9a6ed48 Binary files /dev/null and b/SandboxProject/Library/Cooked/Windows/4a2a315a-ef41-4931-b0f2-0e286fd34df4_4aace3861e64b31f.mccooked differ diff --git a/SandboxProject/Library/Cooked/Windows/CookManifest.bin b/SandboxProject/Library/Cooked/Windows/CookManifest.bin index 9d5a3d0..7b9477c 100644 Binary files a/SandboxProject/Library/Cooked/Windows/CookManifest.bin and b/SandboxProject/Library/Cooked/Windows/CookManifest.bin differ diff --git a/SandboxProject/Library/Cooked/Windows/a2f792dc-75c8-433b-9b99-09f3414902c4_9bccbdef12905449.mccooked b/SandboxProject/Library/Cooked/Windows/a2f792dc-75c8-433b-9b99-09f3414902c4_9bccbdef12905449.mccooked new file mode 100644 index 0000000..9a6ed48 Binary files /dev/null and b/SandboxProject/Library/Cooked/Windows/a2f792dc-75c8-433b-9b99-09f3414902c4_9bccbdef12905449.mccooked differ diff --git a/SandboxProject/Library/Cooked/Windows/c177bd3d-c557-4266-a4ae-dcd844a54b2f_bf6a12aaf0c383a9.mccooked b/SandboxProject/Library/Cooked/Windows/c177bd3d-c557-4266-a4ae-dcd844a54b2f_bf6a12aaf0c383a9.mccooked new file mode 100644 index 0000000..9a6ed48 Binary files /dev/null and b/SandboxProject/Library/Cooked/Windows/c177bd3d-c557-4266-a4ae-dcd844a54b2f_bf6a12aaf0c383a9.mccooked differ diff --git a/SandboxProject/Library/Cooked/Windows/c59719c9-705f-43e9-9024-a54a7ed60abb_9b39a8d3606d9c03.mccooked b/SandboxProject/Library/Cooked/Windows/c59719c9-705f-43e9-9024-a54a7ed60abb_9b39a8d3606d9c03.mccooked new file mode 100644 index 0000000..9a6ed48 Binary files /dev/null and b/SandboxProject/Library/Cooked/Windows/c59719c9-705f-43e9-9024-a54a7ed60abb_9b39a8d3606d9c03.mccooked differ diff --git a/Source/MetaCoreEditor/Private/MetaCoreBuiltinCoreServicesModule.cpp b/Source/MetaCoreEditor/Private/MetaCoreBuiltinCoreServicesModule.cpp index e305259..268d53f 100644 --- a/Source/MetaCoreEditor/Private/MetaCoreBuiltinCoreServicesModule.cpp +++ b/Source/MetaCoreEditor/Private/MetaCoreBuiltinCoreServicesModule.cpp @@ -59,6 +59,20 @@ bool MetaCoreWriteMetaJson( json["package_path"] = metadata.PackagePath.generic_string(); json["source_hash"] = metadata.SourceHash; + // 序列化子资产列表 + if (!metadata.SubAssets.empty()) { + auto subAssetsJson = nlohmann::json::array(); + for (const auto& subAsset : metadata.SubAssets) { + nlohmann::json subAssetJson; + subAssetJson["guid"] = subAsset.Guid.ToString(); + subAssetJson["type"] = subAsset.Type; + subAssetJson["name"] = subAsset.Name; + subAssetJson["index"] = subAsset.Index; + subAssetsJson.push_back(subAssetJson); + } + json["sub_assets"] = subAssetsJson; + } + // 将 JSON 漂亮格式化并写入文件 std::ofstream output(absoluteMetaPath); if (!output.is_open()) { @@ -102,6 +116,32 @@ bool MetaCoreReadMetaJson( if (json.contains("source_hash") && json["source_hash"].is_number_integer()) { outMetadata.SourceHash = json["source_hash"].get(); } + + // 解析子资产列表 + outMetadata.SubAssets.clear(); + if (json.contains("sub_assets") && json["sub_assets"].is_array()) { + for (const auto& subAssetJson : json["sub_assets"]) { + MetaCoreSubAssetMetadata subAsset; + if (subAssetJson.contains("guid") && subAssetJson["guid"].is_string()) { + auto parsed = MetaCoreAssetGuid::Parse(subAssetJson["guid"].get()); + if (parsed.has_value()) { + subAsset.Guid = *parsed; + } + } + if (subAssetJson.contains("type") && subAssetJson["type"].is_string()) { + subAsset.Type = subAssetJson["type"].get(); + } + if (subAssetJson.contains("name") && subAssetJson["name"].is_string()) { + subAsset.Name = subAssetJson["name"].get(); + } + if (subAssetJson.contains("index") && subAssetJson["index"].is_number_integer()) { + subAsset.Index = subAssetJson["index"].get(); + } + if (subAsset.Guid.IsValid()) { + outMetadata.SubAssets.push_back(subAsset); + } + } + } return true; } catch (...) { return false; @@ -4097,6 +4137,43 @@ bool MetaCoreBuiltinImportPipelineService::ImportSourceFile(const std::filesyste meshPayloads, existingModelImportSettings ); + + // 收集生成的子资产信息到元数据中,以便落盘和注册表在下次启动时扫描解析 + metadata.SubAssets.clear(); + for (std::size_t index = 0; index < importedAsset.GeneratedMeshAssets.size(); ++index) { + const auto& mesh = importedAsset.GeneratedMeshAssets[index]; + if (mesh.AssetGuid.IsValid()) { + MetaCoreSubAssetMetadata sub; + sub.Guid = mesh.AssetGuid; + sub.Type = "mesh"; + sub.Name = mesh.Name; + sub.Index = static_cast(index); + metadata.SubAssets.push_back(sub); + } + } + for (std::size_t index = 0; index < importedAsset.GeneratedMaterialAssets.size(); ++index) { + const auto& mat = importedAsset.GeneratedMaterialAssets[index]; + if (mat.AssetGuid.IsValid()) { + MetaCoreSubAssetMetadata sub; + sub.Guid = mat.AssetGuid; + sub.Type = "material"; + sub.Name = mat.Name; + sub.Index = static_cast(index); + metadata.SubAssets.push_back(sub); + } + } + for (std::size_t index = 0; index < importedAsset.GeneratedTextureAssets.size(); ++index) { + const auto& tex = importedAsset.GeneratedTextureAssets[index]; + if (tex.AssetGuid.IsValid()) { + MetaCoreSubAssetMetadata sub; + sub.Guid = tex.AssetGuid; + sub.Type = "texture"; + sub.Name = tex.Name; + sub.Index = static_cast(index); + metadata.SubAssets.push_back(sub); + } + } + importedAssetBytes = MetaCoreSerializeToBytes(importedAsset, registry); importedAssetTypeName = "MetaCoreModelAssetDocument"; diff --git a/Source/MetaCoreEditor/Public/MetaCoreEditor/MetaCoreEditorAssetTypes.h b/Source/MetaCoreEditor/Public/MetaCoreEditor/MetaCoreEditorAssetTypes.h index 32e3d58..e57755a 100644 --- a/Source/MetaCoreEditor/Public/MetaCoreEditor/MetaCoreEditorAssetTypes.h +++ b/Source/MetaCoreEditor/Public/MetaCoreEditor/MetaCoreEditorAssetTypes.h @@ -40,6 +40,23 @@ enum class MetaCoreUiVerticalAlignment { Stretch }; +MC_STRUCT() +struct MetaCoreSubAssetMetadata { + MC_GENERATED_BODY() + + MC_PROPERTY() + MetaCoreAssetGuid Guid{}; + + MC_PROPERTY() + std::string Type{}; + + MC_PROPERTY() + std::string Name{}; + + MC_PROPERTY() + std::int32_t Index = 0; +}; + MC_STRUCT() struct MetaCoreAssetMetadataDocument { MC_GENERATED_BODY() @@ -61,6 +78,9 @@ struct MetaCoreAssetMetadataDocument { MC_PROPERTY() std::uint64_t SourceHash = 0; + + MC_PROPERTY() + std::vector SubAssets{}; }; MC_STRUCT() diff --git a/Source/MetaCoreFoundation/Private/MetaCoreAssetRegistry.cpp b/Source/MetaCoreFoundation/Private/MetaCoreAssetRegistry.cpp index 5823d4c..3587740 100644 --- a/Source/MetaCoreFoundation/Private/MetaCoreAssetRegistry.cpp +++ b/Source/MetaCoreFoundation/Private/MetaCoreAssetRegistry.cpp @@ -42,6 +42,19 @@ void MetaCoreAssetRegistry::ScanDirectory(const std::filesystem::path& rootPath) // 规格化路径,确保斜杠在跨平台的一致性 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 (...) {