#include "MetaCoreScene/MetaCoreScenePackage.h" #include "MetaCoreFoundation/MetaCoreGeneratedReflection.h" #include "MetaCoreFoundation/MetaCoreHash.h" #include "MetaCoreFoundation/MetaCorePackage.h" #include "MetaCoreFoundation/MetaCoreProject.h" #include #include namespace MetaCore { namespace { [[nodiscard]] MetaCorePackageDocument MetaCoreBuildTypedScenePackage( const MetaCoreAssetGuid& assetGuid, const std::string& objectName, std::vector payload ) { MetaCorePackageDocument document; document.Header.PackageType = MetaCorePackageType::Scene; document.Header.PackageGuid = assetGuid; document.Header.SourceHash = MetaCoreHashBytes(std::span(payload.data(), payload.size())); document.NameTable = {objectName, "MetaCoreSceneDocument"}; document.Exports.push_back(MetaCoreExportEntry{ assetGuid, objectName, MetaCoreMakeTypeId("MetaCoreSceneDocument"), 0, static_cast(payload.size()) }); document.PayloadSections.push_back(std::move(payload)); return document; } template [[nodiscard]] std::optional MetaCoreReadTypedPayload( const MetaCorePackageDocument& document, const MetaCoreTypeRegistry& registry, std::string_view expectedTypeName ) { if (document.Exports.empty() || document.PayloadSections.empty()) { return std::nullopt; } const MetaCoreExportEntry& exportEntry = document.Exports.front(); if (exportEntry.TypeId != MetaCoreMakeTypeId(expectedTypeName) || exportEntry.PayloadIndex >= document.PayloadSections.size()) { return std::nullopt; } T payload{}; if (!MetaCoreDeserializeFromBytes(document.PayloadSections[exportEntry.PayloadIndex], payload, registry)) { return std::nullopt; } return payload; } [[nodiscard]] std::optional MetaCoreFindJsonStringValue(std::string_view json, std::string_view key) { const std::string needle = "\"" + std::string(key) + "\""; std::size_t keyPosition = json.find(needle); if (keyPosition == std::string_view::npos) { return std::nullopt; } std::size_t colonPosition = json.find(':', keyPosition + needle.size()); if (colonPosition == std::string_view::npos) { return std::nullopt; } std::size_t firstQuote = json.find('"', colonPosition + 1); if (firstQuote == std::string_view::npos) { return std::nullopt; } std::size_t secondQuote = firstQuote + 1; while (secondQuote < json.size()) { secondQuote = json.find('"', secondQuote); if (secondQuote == std::string_view::npos) { return std::nullopt; } if (secondQuote == firstQuote + 1 || json[secondQuote - 1] != '\\') { break; } ++secondQuote; } return std::string(json.substr(firstQuote + 1, secondQuote - firstQuote - 1)); } } // namespace MetaCoreTypeRegistry MetaCoreBuildScenePackageTypeRegistry() { MetaCoreTypeRegistry registry; MetaCoreRegisterFoundationGeneratedTypes(registry); MetaCoreRegisterSceneGeneratedTypes(registry); return registry; } bool MetaCoreWriteScenePackage( const std::filesystem::path& path, const MetaCoreSceneDocument& document ) { const MetaCoreTypeRegistry registry = MetaCoreBuildScenePackageTypeRegistry(); const auto payload = MetaCoreSerializeToBytes(document, registry); if (!payload.has_value()) { return false; } const std::string objectName = path.stem().string().empty() ? "Scene" : path.stem().string(); MetaCorePackageDocument package = MetaCoreBuildTypedScenePackage( MetaCoreAssetGuid::Generate(), objectName, *payload ); return MetaCoreWritePackageFile(path, std::move(package), registry); } std::optional MetaCoreReadScenePackage(const std::filesystem::path& path) { const MetaCoreTypeRegistry registry = MetaCoreBuildScenePackageTypeRegistry(); const auto package = MetaCoreReadPackageFile(path, registry); if (!package.has_value() || package->Header.PackageType != MetaCorePackageType::Scene) { return std::nullopt; } return MetaCoreReadTypedPayload(*package, registry, "MetaCoreSceneDocument"); } std::optional MetaCoreResolveStartupScenePackagePath(const std::filesystem::path& projectFilePath) { const auto projectDocument = MetaCoreReadProjectFile(projectFilePath); if (!projectDocument.has_value() || projectDocument->StartupScenePath.empty()) { return std::nullopt; } const std::filesystem::path relativeStartupScenePath = projectDocument->StartupScenePath.lexically_normal(); const std::filesystem::path projectRoot = projectFilePath.parent_path(); std::vector candidates; if (relativeStartupScenePath.extension() == ".json") { candidates.push_back((projectRoot / relativeStartupScenePath).replace_extension("")); } candidates.push_back(projectRoot / relativeStartupScenePath); for (const std::filesystem::path& candidate : candidates) { std::error_code errorCode; if (std::filesystem::exists(candidate, errorCode)) { return std::filesystem::weakly_canonical(candidate, errorCode); } } return (projectRoot / relativeStartupScenePath).lexically_normal(); } std::optional MetaCoreLoadStartupSceneDocument(const std::filesystem::path& projectFilePath) { const auto startupScenePath = MetaCoreResolveStartupScenePackagePath(projectFilePath); if (!startupScenePath.has_value()) { return std::nullopt; } return MetaCoreReadScenePackage(*startupScenePath); } } // namespace MetaCore