Allowing entities to be created and removed

This commit is contained in:
Zoe Roux
2021-06-07 17:57:45 +02:00
parent 328ad91c43
commit 7234d51130
9 changed files with 84 additions and 23 deletions
+7 -4
View File
@@ -11,17 +11,19 @@ namespace WAL
{
unsigned Entity::nextID = 0;
Entity::Entity(Scene &scene, std::string name)
Entity::Entity(Scene &scene, std::string name, bool notifyScene)
: _uid(Entity::nextID++),
_scene(scene),
_name(std::move(name))
_name(std::move(name)),
_notifyScene(notifyScene)
{ }
Entity::Entity(const Entity &other)
: _uid(Entity::nextID++),
_scene(other._scene),
_name(other._name),
_disabled(other._disabled)
_disabled(other._disabled),
_notifyScene(other._notifyScene)
{
for (const auto &cmp : other._components)
this->addComponent(*cmp.second);
@@ -53,7 +55,8 @@ namespace WAL
if (this->hasComponent(type, false))
throw DuplicateError("A component of the type \"" + std::string(type.name()) + "\" already exists.");
this->_components.emplace(type, component.clone(*this));
this->_scene._componentAdded(*this, type);
if (this->_notifyScene)
this->_scene._componentAdded(*this, type);
return *this;
}
+9 -3
View File
@@ -28,6 +28,8 @@ namespace WAL
bool _disabled = false;
//! @brief Has this entity been scheduled for deletion?
bool _shouldDelete = false;
//! @brief Should this entity notify the scene of component changes?
bool _notifyScene;
//! @brief The list of the components of this entity
std::unordered_map<std::type_index, std::unique_ptr<Component>> _components = {};
@@ -40,6 +42,8 @@ namespace WAL
//! @brief Callback called when a component is removed
//! @param type The type of component
void _componentRemoved(const std::type_index &type);
friend Scene;
protected:
//! @brief A reference to the ECS.
Scene &_scene;
@@ -141,7 +145,8 @@ namespace WAL
if (this->hasComponent(type))
throw DuplicateError("A component of the type \"" + std::string(type.name()) + "\" already exists.");
this->_components[type] = std::make_unique<T>(*this, TypeHolder<TNested>()..., std::forward<Types>(params)...);
this->_componentAdded(type);
if (this->_notifyScene)
this->_componentAdded(type);
return *this;
}
@@ -160,12 +165,13 @@ namespace WAL
if (existing == this->_components.end())
throw NotFoundError("No component could be found with the type \"" + std::string(type.name()) + "\".");
this->_components.erase(existing);
this->_componentRemoved(type);
if (this->_notifyScene)
this->_componentRemoved(type);
return *this;
}
//! @brief A default constructor
explicit Entity(Scene &wal, std::string name);
explicit Entity(Scene &wal, std::string name, bool notifyScene = true);
//! @brief An entity is copyable
Entity(const Entity &);
//! @brief An entity is movable.
+17 -1
View File
@@ -24,6 +24,11 @@ namespace WAL
return this->_entities.emplace_back(*this, name);
}
Entity &Scene::scheduleNewEntity(const std::string &name)
{
return this->_newEntities.emplace_back(*this, name, false);
}
void Scene::_componentAdded(Entity &entity, const std::type_index &type)
{
for (auto &view : this->_views) {
@@ -52,7 +57,7 @@ namespace WAL
view->erase(entity);
}
void Scene::deleteMarkedEntities()
void Scene::applyChanges()
{
this->_entities.remove_if([this](auto &entity) {
if (!entity.shouldDelete())
@@ -60,5 +65,16 @@ namespace WAL
this->_entityRemoved(entity);
return true;
});
for (auto &entity : this->_newEntities) {
for (auto &view : this->_views) {
bool valid = std::all_of(view->getTypes().begin(), view->getTypes().end(), [&entity](const auto &type){
return entity.hasComponent(type);
});
if (valid)
view->emplace_back(entity);
}
entity._notifyScene = true;
}
this->_entities.splice(this->_entities.end(), this->_newEntities);
}
} // namespace WAL
+9 -2
View File
@@ -23,6 +23,8 @@ namespace WAL
//! @brief The list of registered entities
std::list<Entity> _entities = {};
//! @brief The list of entities to add on the next call to applyChanges.
std::list<Entity> _newEntities = {};
//! @brief The list of cached views to update.
std::vector<std::shared_ptr<IView>> _views = {};
@@ -46,6 +48,11 @@ namespace WAL
//! @return The created entity is returned.
Entity &addEntity(const std::string &name);
//! @brief Add a new entity to the scene, this entity will be added on the next call to applyChanges.
//! @param name The name of the created entity.
//! @return The created entity is returned.
Entity &scheduleNewEntity(const std::string &name);
template<typename ...Components>
View<Components...> &view()
{
@@ -59,8 +66,8 @@ namespace WAL
return *view;
}
//! @brief Delete entities marked as deleted.
void deleteMarkedEntities();
//! @brief Delete entities marked as deleted and create scheduled entities.
void applyChanges();
//! @brief A default constructor
Scene() = default;
+4 -2
View File
@@ -179,8 +179,10 @@ namespace WAL
void erase(const Entity &entity) override
{
this->_entities.erase(std::remove_if(this->_entities.begin(), this->_entities.end(), [&entity](const auto &ref){
return &std::get<0>(ref).get() == &entity;
}));
if (std::get<0>(ref).get().getUid() == entity.getUid())
return true;
return std::get<0>(ref).get().getUid() == entity.getUid();
}), this->_entities.end());
}
//! @brief Construct a view from a list of entities.
+2 -2
View File
@@ -52,7 +52,7 @@ namespace WAL
}
for (auto &system : this->_systems)
system->update(dtime);
this->scene->deleteMarkedEntities();
this->scene->applyChanges();
callback(*this, state);
}
}
@@ -76,7 +76,7 @@ namespace WAL
}
for (auto &system : wal._systems)
system->update(dtime);
wal.scene->deleteMarkedEntities();
wal.scene->applyChanges();
callback(wal, state);
}
#endif