EntityWrapper::Clone should no longer cause freezes

This commit is contained in:
2016-03-12 23:44:28 +01:00
parent ba93ebbe88
commit 2bfbd72189
2 changed files with 58 additions and 27 deletions
+2 -1
View File
@@ -45,8 +45,9 @@ struct EntityWrapper
private:
EntityWrapper firstChildByNameRecursive(const std::string& name, EntityID parent);
EntityWrapper cloneRecursive(EntityWrapper entity, EntityWrapper parent);
void childrenWithComponentRecursive(const std::string& componentType, EntityWrapper& entity, std::vector<EntityWrapper>& childrenWithComponent);
static void fillRelationships(std::unordered_multimap<EntityWrapper, EntityWrapper>& relationMap, EntityWrapper entity);
static void recreateRelationships(const std::unordered_multimap<EntityWrapper, EntityWrapper>& relationMap, EntityWrapper templateEntity, EntityWrapper parent = EntityWrapper::Invalid);
};
namespace std
+56 -26
View File
@@ -94,8 +94,30 @@ EntityWrapper EntityWrapper::Clone(EntityWrapper parent /*= Invalid*/)
return EntityWrapper::Invalid;
}
EntityWrapper clone = cloneRecursive(*this, EntityWrapper::Invalid);
this->World->SetParent(clone.ID, parent.ID);
// Create a relationship map of children of this entity
std::unordered_multimap<EntityWrapper, EntityWrapper> relationships;
fillRelationships(relationships, *this);
::World* targetWorld = this->World;
if (parent.Valid()) {
targetWorld = parent.World;
}
// Create root entity
EntityWrapper clone(targetWorld, targetWorld->CreateEntity(parent.ID));
// Copy name
clone.World->SetName(clone.ID, this->Name());
// Clone components
for (auto& kv : this->World->GetComponentPools()) {
if (kv.second->KnowsEntity(this->ID)) {
ComponentWrapper c1 = kv.second->GetByEntity(this->ID);
ComponentWrapper c2 = clone.World->AttachComponent(clone.ID, kv.first);
c1.Copy(c2);
}
}
// Recreate entity tree
recreateRelationships(relationships, *this, clone);
return clone;
}
@@ -207,30 +229,6 @@ EntityWrapper EntityWrapper::firstChildByNameRecursive(const std::string& name,
return EntityWrapper::Invalid;
}
EntityWrapper EntityWrapper::cloneRecursive(EntityWrapper entity, EntityWrapper parent)
{
EntityWrapper clone = EntityWrapper(entity.World, entity.World->CreateEntity(parent.ID));
entity.World->SetName(clone.ID, entity.Name());
// Clone components
for (auto& kv : entity.World->GetComponentPools()) {
if (kv.second->KnowsEntity(entity.ID)) {
ComponentWrapper c1 = kv.second->GetByEntity(entity.ID);
ComponentWrapper c2 = entity.World->AttachComponent(clone.ID, kv.first);
c1.Copy(c2);
}
}
// Clone children
auto children = entity.World->GetDirectChildren(entity.ID);
for (auto it = children.first; it != children.second; ++it) {
EntityWrapper child(entity.World, it->second);
cloneRecursive(child, clone);
}
return clone;
}
void EntityWrapper::childrenWithComponentRecursive(const std::string& componentType, EntityWrapper& entity, std::vector<EntityWrapper>& childrenWithComponent)
{
auto itPair = this->World->GetDirectChildren(entity.ID);
@@ -246,3 +244,35 @@ void EntityWrapper::childrenWithComponentRecursive(const std::string& componentT
childrenWithComponentRecursive(componentType, child, childrenWithComponent);
}
}
void EntityWrapper::fillRelationships(std::unordered_multimap<EntityWrapper, EntityWrapper>& relationMap, EntityWrapper entity)
{
auto children = entity.World->GetDirectChildren(entity.ID);
for (auto it = children.first; it != children.second; ++it) {
EntityWrapper child(entity.World, it->second);
relationMap.insert(std::make_pair(entity, child));
fillRelationships(relationMap, child);
}
}
void EntityWrapper::recreateRelationships(const std::unordered_multimap<EntityWrapper, EntityWrapper>& relationMap, EntityWrapper templateEntity, EntityWrapper parent /*= EntityWrapper::Invalid*/)
{
// Recursively create children
auto children = relationMap.equal_range(templateEntity);
for (auto it = children.first; it != children.second; ++it) {
EntityWrapper child = it->second;
// Create clone entity
EntityWrapper clone(parent.World, parent.World->CreateEntity(parent.ID));
// Copy name
clone.World->SetName(clone.ID, child.Name());
// Clone components
for (auto& kv : child.World->GetComponentPools()) {
if (kv.second->KnowsEntity(child.ID)) {
ComponentWrapper c1 = kv.second->GetByEntity(child.ID);
ComponentWrapper c2 = clone.World->AttachComponent(clone.ID, kv.first);
c1.Copy(c2);
}
}
recreateRelationships(relationMap, child, clone);
}
}