From a833de2c9188a40a59e0f21323bf74dd31a90e2e Mon Sep 17 00:00:00 2001 From: SHAM-DP Date: Fri, 3 Mar 2023 21:50:00 +0800 Subject: [PATCH] add node merge --- .../AssetBrowser/SHAssetBrowser.cpp | 6 +- .../HierarchyPanel/SHHierarchyPanel.cpp | 3 +- .../Serialization/Prefab/SHPrefabManager.cpp | 66 +++++++++++++------ .../Serialization/Prefab/SHPrefabManager.h | 16 +++-- .../src/Serialization/SHSerialization.cpp | 47 +++++++++++++ .../src/Serialization/SHSerialization.h | 2 +- 6 files changed, 111 insertions(+), 29 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp index a0aaf0fa..13af4eb7 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp @@ -23,6 +23,7 @@ #include "Serialization/SHSerialization.h" #include #include "Serialization/Prefab/SHPrefabManager.h" +#include namespace SHADE { @@ -415,7 +416,10 @@ namespace SHADE { auto createdEntitiesList = SHSerialization::DeserializeEntitiesFromString(SHAssetManager::GetData(asset->id)->data); SHEditorWindowManager::GetEditorWindow()->SetScrollTo(createdEntitiesList.begin()->second); - SHPrefabManager::AddEntity(asset->id, createdEntitiesList.begin()->second); + std::vector eidList; + SHPrefabManager::RecursivelyFlattenEntityHierarchy(SHSceneManager::GetCurrentSceneGraph().GetNode(createdEntitiesList.begin()->second), eidList); + SHPrefabManager::AddPrefabInstance(asset->id, eidList); + //SHPrefabManager::AddEntity(asset->id, createdEntitiesList.begin()->second); } } break; diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index 8f0a8193..d740d047 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -390,7 +390,8 @@ namespace SHADE std::ranges::transform(createdEntitiesList, std::back_inserter(eidList), [](std::pair pair){return pair.second;} ); ParentSelectedEntities(eid, eidList); SetScrollTo(createdEntitiesList.begin()->second); - SHPrefabManager::AddEntity(assetId, createdEntitiesList.begin()->second); + SHPrefabManager::AddPrefabInstance(assetId, eidList); + //SHPrefabManager::AddEntity(assetId, createdEntitiesList.begin()->second); skipFrame = true; } } diff --git a/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.cpp b/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.cpp index 7ddc6491..7b87754e 100644 --- a/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.cpp +++ b/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.cpp @@ -8,22 +8,26 @@ namespace SHADE { SHPrefabManager::PrefabMap SHPrefabManager::prefabMap{}; + SHPrefabManager::PrefabEntityDatabase SHPrefabManager::prefabEntityDatabase{}; AssetID SHPrefabManager::GetPrefabAssetID(EntityID eid) noexcept { - for(auto const& [assetId, entityList] : prefabMap) + for (auto const& [assetId, entityList] : prefabMap) { - if(std::ranges::find(entityList, eid) != entityList.end()) - { - return assetId; - } + if (std::ranges::find(entityList, eid) != entityList.end()) + { + return assetId; + } } return 0; } void SHPrefabManager::AddPrefab(AssetID const& prefabAssetID) noexcept { - prefabMap[prefabAssetID] = {}; + //if (prefabMap.contains(prefabAssetID)) + //{ + // prefabMap.insert(prefabAssetID, {}); + //} } void SHPrefabManager::RemovePrefab(AssetID const& prefabAssetID) noexcept @@ -35,35 +39,59 @@ namespace SHADE { if (prefabMap.contains(prefabAssetID)) { - prefabMap[prefabAssetID].clear(); + prefabMap.erase(prefabAssetID); } } void SHPrefabManager::UpdateAllPrefabEntities(AssetID const& prefabAssetID) noexcept { - //Loop through all entities and deserialize new data } - void SHPrefabManager::AddEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept + void SHPrefabManager::AddPrefabInstance(AssetID prefabAssetID, std::vector eidList) { - - prefabMap[prefabAssetID].push_back(eid); - - } - - void SHPrefabManager::RemoveEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept - { - if (prefabMap.contains(prefabAssetID)) + prefabMap.insert({ prefabAssetID, eidList }); + std::size_t size = eidList.size(); + for (std::size_t i = 0; i < size; ++i) { - (void)std::ranges::remove(prefabMap[prefabAssetID], eid); + prefabEntityDatabase[eidList[i]] = { prefabAssetID, i }; + } + } + + void SHPrefabManager::RemovePrefabInstance(AssetID prefabAssetID, EntityID rootEid) + { + if (auto iter = prefabMap.find(prefabAssetID); iter != prefabMap.end()) + { + while (iter != prefabMap.upper_bound(prefabAssetID)) + { + if (std::ranges::find(iter->second, rootEid) != iter->second.end()) + { + prefabMap.erase(iter); + } + ++iter; + } + } + } + + void SHPrefabManager::RecursivelyFlattenEntityHierarchy(SHSceneNode* node, std::vector& eidList) + { + if (!node) + return; + eidList.push_back(node->GetEntityID()); + auto const& children = node->GetChildren(); + for (auto childNode : children) + { + RecursivelyFlattenEntityHierarchy(childNode, eidList); } } void SHPrefabManager::SaveEntityAsPrefab(EntityID const& eid) noexcept { SHEntity* const entity = SHEntityManager::GetEntityByID(eid); + SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(eid); AssetID const assetID = SHAssetManager::CreateNewAsset(AssetType::PREFAB, entity->name); - AddEntity(assetID, eid); + std::vector eidList; + RecursivelyFlattenEntityHierarchy(entityNode, eidList); + AddPrefabInstance(assetID, eidList); auto assetData = SHAssetManager::GetData(assetID); assetData->data = SHSerialization::SerializeEntityToString(eid, assetID); diff --git a/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.h b/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.h index 0c56ce4d..ecd66e7e 100644 --- a/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.h +++ b/SHADE_Engine/src/Serialization/Prefab/SHPrefabManager.h @@ -5,7 +5,7 @@ #include "ECS_Base/General/SHFamily.h" #include "ECS_Base/Components/SHComponent.h" #include -#include <> +#include namespace SHADE { @@ -20,24 +20,26 @@ namespace SHADE PES_ADDED }; - using PrefabMap = std::unordered_map>; - //using PrefabDatabase = std::unordered_multimap,PrefabEntityComponentStatus>>; + using PrefabMap = std::unordered_multimap>; + using PrefabEntityDatabase = std::unordered_map>; static AssetID GetPrefabAssetID(EntityID eid) noexcept; static void AddPrefab(AssetID const& prefabAssetID) noexcept; static void RemovePrefab(AssetID const& prefabAssetID) noexcept; static void ClearPrefab(AssetID const& prefabAssetID) noexcept; static void UpdateAllPrefabEntities(AssetID const& prefabAssetID) noexcept; - static void AddEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept; - static void RemoveEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept; + static void AddPrefabInstance(AssetID prefabAssetID, std::vector eidList); + static void RemovePrefabInstance(AssetID prefabAssetID, EntityID rootEid); + static void RecursivelyFlattenEntityHierarchy(SHSceneNode* node, std::vector& eidList); + //static void AddEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept; + //static void RemoveEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept; static void SaveEntityAsPrefab(EntityID const& eid) noexcept; static void Clear() noexcept; static bool Empty() noexcept; private: static PrefabMap prefabMap; - static PrefabEntitiesComponentStatusData prefabEntitiesComponentStatusData; + static PrefabEntityDatabase prefabEntityDatabase; friend class SHSerialization; friend struct SHSerializationHelper; diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index 4e2036d3..860ccb39 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -52,6 +52,7 @@ namespace SHADE auto const& children = root->GetChildren(); out << YAML::BeginSeq; + //auto pred = [&out](SHSceneNode* node) {out << SerializeEntityToNode(node); }; auto pred = [&out](SHSceneNode* node) {out << SerializeEntityToNode(node); }; sceneGraph.Traverse(pred); //out << SerializeEntityToNode(child); @@ -97,6 +98,14 @@ namespace SHADE std::string name = "UnnamedEntitiy"; if (node[EntityNameNode]) name = node[EntityNameNode].as(); + + //if(node[PrefabID].IsDefined()) + //{ + // AssetID prefabAssetID = node[PrefabID].as(); + // YAML::Node prefabNode = YAML::Load(SHAssetManager::GetData(prefabAssetID)->data); + // + //} + //Compile component IDs const auto componentIDList = SHSerialization::GetComponentIDList(node[ComponentsNode]); eid = SHEntityManager::CreateEntity(componentIDList, eid, name, parentEID); @@ -462,6 +471,44 @@ namespace SHADE SHSystemManager::GetSystem()->DeserialiseScripts(eid, entityNode[ScriptsNode]); } + const YAML::Node& cnode(const YAML::Node& n) { + return n; + } + YAML::Node SHSerialization::MergeNodes(YAML::Node a, YAML::Node b) + { + if (!b.IsMap()) { + + return b.IsNull() ? a : b; + } + if (!a.IsMap()) { + + return b; + } + if (!b.size()) { + + return a; + } + + auto c = YAML::Node(YAML::NodeType::Map); + for (auto n : a) { + if (n.first.IsScalar()) { + const std::string& key = n.first.Scalar(); + auto t = YAML::Node(cnode(b)[key]); + if (t) { + c[n.first] = MergeNodes(n.second, t); + continue; + } + } + c[n.first] = n.second; + } + + for (auto n : b) { + if (!n.first.IsScalar() || !cnode(c)[n.first.Scalar()]) { + c[n.first] = n.second; + } + } + return c; + } } diff --git a/SHADE_Engine/src/Serialization/SHSerialization.h b/SHADE_Engine/src/Serialization/SHSerialization.h index 5e3f4bd3..3848bbe4 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.h +++ b/SHADE_Engine/src/Serialization/SHSerialization.h @@ -56,7 +56,7 @@ namespace SHADE private: //static void ResolveSerializedEntityID(YAML::Emitter& out, YAML::iterator& it, YAML::Node const& entityNode, CreatedEntitiesList const& createdEntities); static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid); - + static YAML::Node MergeNodes(YAML::Node lhsNode, YAML::Node rhsNode); static constexpr std::string_view NewSceneName = "New Scene"; }; } \ No newline at end of file