#ifndef CORE_COMPONENTS_HPP #define CORE_COMPONENTS_HPP #include "core/data/HashMap.hpp" namespace Core { using Entity = int; template class Components final { HashMap entityToIndex{}; List indexToEntity{}; List components{}; public: template struct Node final { const Entity& entity; R& component; }; template 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 operator*() const { return {components.indexToEntity[index], components.components[index]}; } }; template struct EntityIteratorAdapter final { C& components; EntityIterator begin() { return EntityIterator(components, 0); } EntityIterator end() { return EntityIterator(components, components.components.getLength()); } }; template 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)...); return true; } template bool add(Entity e, Args&&... args) { T* t = nullptr; return put(t, e, Core::forward(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 entities() { return {*this}; } EntityIteratorAdapter entities() const { return {*this}; } }; } #endif