EntityWrapper::Clone should no longer cause freezes
This commit is contained in:
@@ -45,8 +45,9 @@ struct EntityWrapper
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
EntityWrapper firstChildByNameRecursive(const std::string& name, EntityID parent);
|
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);
|
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
|
namespace std
|
||||||
|
|||||||
@@ -94,8 +94,30 @@ EntityWrapper EntityWrapper::Clone(EntityWrapper parent /*= Invalid*/)
|
|||||||
return EntityWrapper::Invalid;
|
return EntityWrapper::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityWrapper clone = cloneRecursive(*this, EntityWrapper::Invalid);
|
// Create a relationship map of children of this entity
|
||||||
this->World->SetParent(clone.ID, parent.ID);
|
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;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,30 +229,6 @@ EntityWrapper EntityWrapper::firstChildByNameRecursive(const std::string& name,
|
|||||||
return EntityWrapper::Invalid;
|
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)
|
void EntityWrapper::childrenWithComponentRecursive(const std::string& componentType, EntityWrapper& entity, std::vector<EntityWrapper>& childrenWithComponent)
|
||||||
{
|
{
|
||||||
auto itPair = this->World->GetDirectChildren(entity.ID);
|
auto itPair = this->World->GetDirectChildren(entity.ID);
|
||||||
@@ -246,3 +244,35 @@ void EntityWrapper::childrenWithComponentRecursive(const std::string& componentT
|
|||||||
childrenWithComponentRecursive(componentType, child, childrenWithComponent);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user