#pragma once #include #include #include #include #include "asset_base.hpp" #include "type_base.hpp" struct Scene : public AssetBase { public: static constexpr std::array Extensions = { ".unity" }; private: std::unordered_map IDtoAsset; public: int64_t GetNewID(int64_t lastID = 0) { for (;; ++lastID) { if (IDtoAsset.find(lastID) == IDtoAsset.end()) return lastID; } } template void Parse(ParsedProject& project, std::string& content) { using ObjectTypesT = typename ParsedProject::ObjectTypes; auto& sceneData = project.CreateSceneData(GUID); // Create ParseContext for component parsing ParseContext context(*this, project.Assets); auto names = ObjectTypesT::get_names(); ParseSceneYaml(content, true, names, [&sceneData, &context](std::string_view componentName, int64_t ID, ryml::Tree&& tree) { sceneData.AddComponent(componentName, ID, std::move(tree), context); }); // Link all components after parsing LinkAssets(project); } template void LinkAssets(ParsedProject& project) { using ObjectTypesT = typename ParsedProject::ObjectTypes; auto& sceneData = project.GetSceneData(GUID); // Build the assets map (ID -> pointer) std::unordered_map assetsMap; ObjectTypesT::ForEachT([&]() -> void { auto& components = sceneData.template GetComponents(); for (auto& component : components) { assetsMap.emplace(component.ID, &component); } }); // Link all components ObjectTypesT::ForEachT([&]() -> void { auto& components = sceneData.template GetComponents(); for (auto& component : components) { component.Link(assetsMap); } }); } template void MergeComponents(const ParsedProject& project, const Scene& otherScene) { using ObjectTypesT = typename ParsedProject::ObjectTypes; auto& thisSceneData = project.GetSceneData(GUID); auto& otherSceneData = project.GetSceneData(otherScene.GUID); std::unordered_map newIDMap{}; int64_t lastID = std::random_device{}(); ObjectTypesT::ForEachT([&]() -> void { auto& thisComponents = thisSceneData.template GetComponents(); auto& otherComponents = otherSceneData.template GetComponents(); for (auto otherComponentCopy : otherComponents) { int64_t originalID = otherComponentCopy.ID; lastID = GetNewID(lastID); otherComponentCopy.ID = lastID; // register the new ID to the scene newIDMap.emplace(originalID, lastID); // add the component to the scene thisComponents.emplace_back(std::move(otherComponentCopy)); } }); auto& IDMapLinked = reinterpret_cast&>(newIDMap); ObjectTypesT::ForEachT([&]() -> void { auto& thisComponents = thisSceneData.template GetComponents(); for (auto& component : thisComponents) { component.Link(IDMapLinked); } }); } };