#ifndef CORE_COMPONENTS_HPP #define CORE_COMPONENTS_HPP #include "core/data/HashMap.hpp" namespace Core { using Entity = int; template<typename T> class Components final { HashMap<Entity, size_t> entityToIndex{}; List<Entity> indexToEntity{}; List<T> components{}; public: template<typename R> struct Node final { const Entity& entity; R& component; }; template<typename C, typename R> class EntityIterator final { C& components; size_t index; public: EntityIterator(C& components_, size_t index_) : components(components_), index(index_) { } EntityIterator& operator++() { index++; return *this; } bool operator!=(const EntityIterator& other) const { return index != other.index; } Node<R> operator*() const { return {components.indexToEntity[index], components.components[index]}; } }; template<typename C, typename R> struct EntityIteratorAdapter final { C& components; EntityIterator<C, R> begin() { return EntityIterator<C, R>(components, 0); } EntityIterator<C, R> end() { return EntityIterator<C, R>(components, components.components.getLength()); } }; template<typename... Args> bool put(T*& t, Entity ent, Args&&... args) { size_t index = components.getLength(); size_t* indexP = nullptr; if(!entityToIndex.tryEmplace(indexP, ent, index)) { return false; } indexToEntity.add(ent); t = &components.put(Core::forward<Args>(args)...); return true; } template<typename... Args> bool add(Entity e, Args&&... args) { T* t = nullptr; return put(t, e, Core::forward<Args>(args)...); } bool remove(Entity ent) { size_t* indexP = entityToIndex.search(ent); if(indexP == nullptr) { return false; } size_t lastIndex = components.getLength() - 1; size_t index = *indexP; entityToIndex.remove(ent); components.removeBySwap(index); if(index == lastIndex) { indexToEntity.removeBySwap(index); return true; } Entity other = indexToEntity[lastIndex]; indexToEntity.removeBySwap(index); entityToIndex.add(other, index); return true; } T* search(Entity e) { size_t* index = entityToIndex.search(e); if(index == nullptr) { return nullptr; } return &(components[*index]); } const T* search(Entity e) const { const size_t* index = entityToIndex.search(e); if(index == nullptr) { return nullptr; } return &(components[*index]); } auto begin() { return components.begin(); } auto begin() const { return components.begin(); } auto end() { return components.end(); } auto end() const { return components.end(); } EntityIteratorAdapter<Components, T> entities() { return {*this}; } EntityIteratorAdapter<const Components, const T> entities() const { return {*this}; } }; } #endif