diff --git a/lib/wal/CMakeLists.txt b/lib/wal/CMakeLists.txt index 6fc78ef7..02613603 100644 --- a/lib/wal/CMakeLists.txt +++ b/lib/wal/CMakeLists.txt @@ -19,6 +19,6 @@ add_library(wal sources/Events/EventManager.hpp sources/Exception/WalError.cpp sources/Exception/WalError.hpp -) + sources/Entity/Entity.cpp sources/Component/Component.cpp) target_include_directories(wal PUBLIC sources) \ No newline at end of file diff --git a/lib/wal/sources/Component/Component.cpp b/lib/wal/sources/Component/Component.cpp new file mode 100644 index 00000000..5d2948c7 --- /dev/null +++ b/lib/wal/sources/Component/Component.cpp @@ -0,0 +1,43 @@ +// +// Created by Zoe Roux on 2021-05-14. +// + +#include "Component/Component.hpp" + +namespace WAL +{ + Component::Component(std::string name, Entity &entity) + : _name(std::move(name)), + _entity(entity) + { } + + std::string Component::getName() const + { + return this->_name; + } + + bool Component::isDisabled() const + { + return this->_disabled; + } + + void Component::setDisable(bool disabled) + { + this->_disabled = disabled; + } + + const std::vector &Component::getDependencies() const + { + return this->_dependencies; + } + + void Component::onStart() + { + //TODO handle events here + } + + void Component::onStop() + { + //TODO handle events here + } +} \ No newline at end of file diff --git a/lib/wal/sources/Component/Component.hpp b/lib/wal/sources/Component/Component.hpp index 7589ae6a..64d325a9 100644 --- a/lib/wal/sources/Component/Component.hpp +++ b/lib/wal/sources/Component/Component.hpp @@ -5,6 +5,7 @@ #include #include +#include namespace WAL { @@ -18,35 +19,42 @@ namespace WAL //! @brief The name of this component std::string _name; //! @brief Is this component disabled? - bool _disabled; + bool _disabled = false; + protected: + //! @brief The entity that own this component + Entity &_entity; //! @brief The list of dependencies of this component. - // TODO check if there is a better type than strings - std::vector _dependencies; + std::vector _dependencies; + + //! @brief A component can't be instantiated, it should be derived. + explicit Component(std::string name, Entity &entity); + //! @brief A component can't be instantiated, it should be derived. + Component(const Component &) = default; public: + //! @brief A component can't be assigned + Component &operator=(const Component &) = delete; + //! @brief A virtual destructor + virtual ~Component() = default; + + //! @brief Clone a component for another or the same entity. + //! @param entity The entity that owns the ne component. + virtual Component *clone(Entity &entity) const = 0; + //! @brief Get the name of this component - std::string _getName() const; + std::string getName() const; //! @brief Used if the component is disabled - bool isDisable() const; + bool isDisabled() const; //! @brief Disable this component. void setDisable(bool disabled); + //! @brief Get the dependencies of this component. + const std::vector &getDependencies() const; + //! @brief The entity or this component has just been enabled. - //! @param entity The entity that has this component - virtual void onStart(Entity &entity); + virtual void onStart(); //! @brief The entity or this component has just been disable. - //! @param entity The entity that has this component - virtual void onStop(Entity &entity); - - //! @brief A virtual destructor (that also calls onStop) - virtual ~Component(); - protected: - //! @brief A component can't be instantiated, it should be derived. - Component() = default; - //! @brief A component can't be instantiated, it should be derived. - Component(const Component &) = default; - //! @brief A component can't be instantiated, it should be derived. - Component &operator=(const Component &) = default; + virtual void onStop(); }; } \ No newline at end of file diff --git a/lib/wal/sources/Entity/Entity.cpp b/lib/wal/sources/Entity/Entity.cpp new file mode 100644 index 00000000..859e2e3e --- /dev/null +++ b/lib/wal/sources/Entity/Entity.cpp @@ -0,0 +1,55 @@ +// +// Created by Zoe Roux on 2021-05-14. +// + +#include "Entity/Entity.hpp" + +#include + +namespace WAL +{ + unsigned Entity::nextID = 0; + + Entity::Entity(std::string name) + : _uid(Entity::nextID++), + _name(std::move(name)) + { } + + Entity::Entity(const Entity &other) + : _uid(Entity::nextID++), + _name(other._name), + _disabled(other._disabled) + { + for (const auto &cmp : other._components) + this->addComponent(*cmp); + } + + unsigned Entity::getUid() const + { + return this->_uid; + } + + std::string Entity::getName() const + { + return this->_name; + } + + bool Entity::isDisable() const + { + return this->_disabled; + } + + void Entity::setDisable(bool disabled) + { + this->_disabled = disabled; + } + + Entity &Entity::addComponent(const Component &component) + { + // TODO handle duplicates +// if (this->hasComponent()) +// throw DuplicateError("A component of the type \"" + std::string(typeid(T).name()) + "\" already exists."); + this->_components.emplace_back(component.clone(*this)); + return *this; + } +} \ No newline at end of file diff --git a/lib/wal/sources/Entity/Entity.hpp b/lib/wal/sources/Entity/Entity.hpp index 6b71a5f6..7ad68586 100644 --- a/lib/wal/sources/Entity/Entity.hpp +++ b/lib/wal/sources/Entity/Entity.hpp @@ -4,7 +4,10 @@ #include #include +#include +#include #include "Component/Component.hpp" +#include "Exception/WalError.hpp" namespace WAL { @@ -17,9 +20,12 @@ namespace WAL //! @brief An entity name (this is useful for debugging) std::string _name; //! @brief Is this entity enabled? - bool _disabled; + bool _disabled = false; //! @brief The list of the components of this entity - std::vector _components; + std::vector> _components = {}; + + //! @brief This ID will be the one of the next entity created. + static unsigned nextID; public: //! @brief Get the ID of the entity. unsigned getUid() const; @@ -33,30 +39,70 @@ namespace WAL void setDisable(bool disabled); //! @brief Get a component of a specific type - //! @throw ComponentNotFoundError if the component could not be found + //! @throw NotFoundError if the component could not be found template - T getComponent(); + T getComponent() + { + const std::type_info &type = typeid(T); + auto &existing = std::find(this->_components.begin(), this->_components.end(), [&type] (auto &cmp) { + return typeid(*cmp) == type; + }); + if (existing == this->_components.end()) + throw NotFoundError("No component could be found with the type \"" + std::string(type.name()) + "\"."); + return *existing; + } + + template + bool hasComponent() const + { + const std::type_info &type = typeid(T); + auto existing = std::find(this->_components.begin(), this->_components.end(), [&type] (const auto &cmp) { + return typeid(*cmp) == type; + }); + return existing != this->_components.end(); + } //! @brief Add a component to this entity. The component is constructed in place. + //! @throw DuplicateError is thrown if a component with the same type already exist. //! @return This entity is returned template - Entity &addComponent(Types ...params); + Entity &addComponent(Types ...params) + { + if (this->hasComponent()) + throw DuplicateError("A component of the type \"" + std::string(typeid(T).name()) + "\" already exists."); + this->_components.push_back(std::make_unique(params...)); + return *this; + } //! @brief Copy a component to this entity. //! @return This entity is returned. Entity &addComponent(const Component &component); //! @brief Remove a specific component (by type). + //! @throw NotFoundError is thrown if the component could not be found. + //! @return This entity is returned. template - Entity &removeComponent(); + Entity &removeComponent() + { + const std::type_info &type = typeid(T); + auto &existing =std::find(this->_components.begin(), this->_components.end(), [&type] (auto &cmp) { + return typeid(*cmp) == type; + }); + if (existing == this->_components.end()) + throw NotFoundError("No component could be found with the type \"" + std::string(type.name()) + "\"."); + this->_components.erase(existing); + return *this; + } //! @brief A default constructor - Entity(const std::string &name); + explicit Entity(std::string name); //! @brief An entity is copyable Entity(const Entity &); + //! @brief An entity is movable. + Entity(Entity &&) = default; //! @brief A default destructor ~Entity() = default; //! @brief An entity is assignable - Entity &operator=(const Entity &); + Entity &operator=(const Entity &) = default; }; } \ No newline at end of file diff --git a/lib/wal/sources/Exception/WalError.cpp b/lib/wal/sources/Exception/WalError.cpp index acfc32d5..53581300 100644 --- a/lib/wal/sources/Exception/WalError.cpp +++ b/lib/wal/sources/Exception/WalError.cpp @@ -10,7 +10,7 @@ namespace WAL : std::runtime_error(what) {} - SystemExistError::SystemExistError(const std::string &what) + DuplicateError::DuplicateError(const std::string &what) : WalError(what) {} diff --git a/lib/wal/sources/Exception/WalError.hpp b/lib/wal/sources/Exception/WalError.hpp index 7b456a53..0c791647 100644 --- a/lib/wal/sources/Exception/WalError.hpp +++ b/lib/wal/sources/Exception/WalError.hpp @@ -24,18 +24,18 @@ namespace WAL WalError &operator=(const WalError &) = default; }; - //! @brief An exception informing the user that a system already exists. - class SystemExistError : public WalError + //! @brief An exception informing the user that something already exists. + class DuplicateError : public WalError { public: //! @brief Create a new wal exception - explicit SystemExistError(const std::string &what); + explicit DuplicateError(const std::string &what); //! @brief A wal exception is copy constructable - SystemExistError(const SystemExistError &) = default; + DuplicateError(const DuplicateError &) = default; //! @brief A default destructor - ~SystemExistError() override = default; + ~DuplicateError() override = default; //! @brief A default assignment operator - SystemExistError &operator=(const SystemExistError &) = default; + DuplicateError &operator=(const DuplicateError &) = default; }; //! @brief An exception informing the user that something could not be found diff --git a/lib/wal/sources/Wal.hpp b/lib/wal/sources/Wal.hpp index d280f739..4a8bec8a 100644 --- a/lib/wal/sources/Wal.hpp +++ b/lib/wal/sources/Wal.hpp @@ -37,10 +37,10 @@ namespace WAL { const std::type_info &type = typeid(T); auto &existing =std::find(this->_systems.begin(), this->_systems.end(), [&type] (auto &sys) { - return typeid(sys) == type; + return typeid(*sys) == type; }); if (existing != this->_systems.end()) - throw SystemExistError("A system of the type \"" + std::string(type.name()) + "\" already exists."); + throw DuplicateError("A system of the type \"" + std::string(type.name()) + "\" already exists."); this->_systems.push_back(std::make_unique(params...)); return *this; } @@ -52,10 +52,10 @@ namespace WAL { const std::type_info &type = typeid(T); auto &existing =std::find(this->_systems.begin(), this->_systems.end(), [&type] (auto &sys) { - return typeid(sys) == type; + return typeid(*sys) == type; }); if (existing != this->_systems.end()) - throw SystemExistError("A system of the type \"" + std::string(type.name()) + "\" already exists."); + throw DuplicateError("A system of the type \"" + std::string(type.name()) + "\" already exists."); this->_systems.push_back(std::make_unique(system)); return *this; } @@ -66,10 +66,11 @@ namespace WAL { const std::type_info &type = typeid(T); auto &existing =std::find(this->_systems.begin(), this->_systems.end(), [&type] (auto &sys) { - return typeid(sys) == type; + return typeid(*sys) == type; }); if (existing == this->_systems.end()) throw NotFoundError("No system could be found with the type \"" + std::string(type.name()) + "\"."); + this->_systems.erase(existing); return *this; } @@ -85,7 +86,7 @@ namespace WAL WAL(const WAL &) = delete; //! @brief A default destructor ~WAL() = default; - //! @brief A default assignment operator - WAL &operator=(const WAL &) = default; + //! @brief A WAL can't be assigned. + WAL &operator=(const WAL &) = delete; }; }