// // Created by Zoe Roux on 2021-06-03. // #pragma once #include #include #include #include #include "Entity/Entity.hpp" namespace WAL { template class ViewEntity { private: std::tuple, std::reference_wrapper...> _value; public: explicit ViewEntity(std::tuple, std::reference_wrapper...> value) : _value(value) {} Entity *operator->() { return &(std::get<0>(this->_value).get()); } Entity &operator*() { return std::get<0>(this->_value); } operator Entity &() { return std::get<0>(this->_value); } template T &get() { return std::get>(this->_value); } }; template class ViewIterator { private: It _it; public: ViewEntity operator*() { ViewEntity entity(*this->_it); return entity; } ViewEntity operator->() { ViewEntity entity(*this->_it); return entity; } ViewIterator &operator++() { this->_it++; return *this; } ViewIterator operator++(int) { ViewIterator copy = *this; this->_it++; return *this; } bool operator==(const ViewIterator &other) const { return this->_it == other._it; } bool operator!=(const ViewIterator &other) const { return !this->operator==(other); } explicit ViewIterator(It current) : _it(current) {} }; //! @brief A basic view used to manipulate view without knowing their type at compile time. class IView { public: //! @brief The list of types that every entity of the view has. virtual const std::vector &getTypes() const = 0; virtual void emplace_back(Entity &) = 0; virtual void erase(const Entity &) = 0; //! @brief A default destructor virtual ~IView() = default; }; //! @brief A view allowing one to easily access entities containing a set list of component. //! A view is always updated and only references to entities are kept. template class View : public IView { private: using entity_type = std::tuple, std::reference_wrapper...>; //! @brief The list of entities in the view. std::vector _entities = {}; //! @brief The list of types that every entity of the view has. std::vector _types = {}; public: using iterator = ViewIterator::iterator, Components...>; iterator begin() { return iterator(this->_entities.begin()); } iterator end() { return iterator(this->_entities.begin()); } const std::vector &getTypes() const override { return this->_types; } void emplace_back(Entity &) override { } void erase(const Entity &) override { } //! @brief Construct a view from a list of entities. //! Those entities are never copied but references to them are kept internally. explicit View(std::list &scene) { this->_types = {typeid(Components)...}; for (auto &entity : scene) { auto tuple = std::make_tuple(entity, entity.getComponentOrDefault()...); std::apply(&this->_entities.emplace_back, tuple); } // std::copy_if(scene.begin(), scene.end(), std::back_inserter(this->entities), [](Entity &entity) { // return (entity.hasComponent() && ...); // }); } //! @brief Copying a view is not possible since a view must be managed by a scene. View(const View &) = delete; //! @brief A default destructor ~View() = default; //! @brief A view is not assignable. View &operator=(const View &) = delete; }; }