add node merge

This commit is contained in:
SHAM-DP 2023-03-03 21:50:00 +08:00
parent f27dbb92b3
commit a833de2c91
6 changed files with 111 additions and 29 deletions

View File

@ -23,6 +23,7 @@
#include "Serialization/SHSerialization.h"
#include <Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h>
#include "Serialization/Prefab/SHPrefabManager.h"
#include <Scene/SHSceneManager.h>
namespace SHADE
{
@ -415,7 +416,10 @@ namespace SHADE
{
auto createdEntitiesList = SHSerialization::DeserializeEntitiesFromString(SHAssetManager::GetData<SHPrefabAsset>(asset->id)->data);
SHEditorWindowManager::GetEditorWindow<SHHierarchyPanel>()->SetScrollTo(createdEntitiesList.begin()->second);
SHPrefabManager::AddEntity(asset->id, createdEntitiesList.begin()->second);
std::vector<EntityID> eidList;
SHPrefabManager::RecursivelyFlattenEntityHierarchy(SHSceneManager::GetCurrentSceneGraph().GetNode(createdEntitiesList.begin()->second), eidList);
SHPrefabManager::AddPrefabInstance(asset->id, eidList);
//SHPrefabManager::AddEntity(asset->id, createdEntitiesList.begin()->second);
}
}
break;

View File

@ -390,7 +390,8 @@ namespace SHADE
std::ranges::transform(createdEntitiesList, std::back_inserter(eidList), [](std::pair<EntityID, EntityID> 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;
}
}

View File

@ -8,6 +8,7 @@
namespace SHADE
{
SHPrefabManager::PrefabMap SHPrefabManager::prefabMap{};
SHPrefabManager::PrefabEntityDatabase SHPrefabManager::prefabEntityDatabase{};
AssetID SHPrefabManager::GetPrefabAssetID(EntityID eid) noexcept
{
@ -23,7 +24,10 @@ namespace SHADE
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<EntityID> eidList)
{
prefabMap[prefabAssetID].push_back(eid);
prefabMap.insert({ prefabAssetID, eidList });
std::size_t size = eidList.size();
for (std::size_t i = 0; i < size; ++i)
{
prefabEntityDatabase[eidList[i]] = { prefabAssetID, i };
}
}
void SHPrefabManager::RemoveEntity(AssetID const& prefabAssetID, EntityID const& eid) noexcept
void SHPrefabManager::RemovePrefabInstance(AssetID prefabAssetID, EntityID rootEid)
{
if (prefabMap.contains(prefabAssetID))
if (auto iter = prefabMap.find(prefabAssetID); iter != prefabMap.end())
{
(void)std::ranges::remove(prefabMap[prefabAssetID], eid);
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<EntityID>& 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<EntityID> eidList;
RecursivelyFlattenEntityHierarchy(entityNode, eidList);
AddPrefabInstance(assetID, eidList);
auto assetData = SHAssetManager::GetData<SHPrefabAsset>(assetID);
assetData->data = SHSerialization::SerializeEntityToString(eid, assetID);

View File

@ -5,7 +5,7 @@
#include "ECS_Base/General/SHFamily.h"
#include "ECS_Base/Components/SHComponent.h"
#include <unordered_map>
#include <>
#include <Scene/SHSceneNode.h>
namespace SHADE
{
@ -20,24 +20,26 @@ namespace SHADE
PES_ADDED
};
using PrefabMap = std::unordered_map<AssetID, std::vector<EntityID>>;
//using PrefabDatabase = std::unordered_multimap<AssetID,
using PrefabEntitiesComponentStatusData = std::unordered_map<EntityID, std::unordered_map<SHFamilyID<SHComponent>,PrefabEntityComponentStatus>>;
using PrefabMap = std::unordered_multimap<AssetID, std::vector<EntityID>>;
using PrefabEntityDatabase = std::unordered_map<EntityID, std::pair<AssetID, EntityID>>;
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<EntityID> eidList);
static void RemovePrefabInstance(AssetID prefabAssetID, EntityID rootEid);
static void RecursivelyFlattenEntityHierarchy(SHSceneNode* node, std::vector<EntityID>& 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;

View File

@ -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<std::string>();
//if(node[PrefabID].IsDefined())
//{
// AssetID prefabAssetID = node[PrefabID].as<AssetID>();
// YAML::Node prefabNode = YAML::Load(SHAssetManager::GetData<SHPrefabAsset>(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<SHScriptEngine>()->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;
}
}

View File

@ -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";
};
}