export module Core.Components; export import Core.Utility; export import Core.New; import Core.HashMap; import Core.List; import Core.Meta; export namespace Core { using Entity = size_t; template class Components final { HashMap entityToIndex{}; List indexToEntity{}; List components{}; public: template struct Node final { Entity entity; R& component; }; template class Iterator final { using EntityIterator = decltype(C().indexToEntity.begin()); using ComponentIterator = decltype(C().components.begin()); using Component = decltype(*ComponentIterator()); EntityIterator entityIterator{}; ComponentIterator componentIterator{}; public: Iterator(EntityIterator e, ComponentIterator c) : entityIterator(e), componentIterator(c) { } Iterator& operator++() { ++entityIterator; ++componentIterator; return *this; } bool operator!=(const Iterator& other) const { return entityIterator != other.entityIterator; } Node operator*() const { return {*entityIterator, *componentIterator}; } }; template struct IteratorAdapter final { C& c; Iterator begin() { return Iterator( c.indexToEntity.begin(), c.components.begin()); } Iterator end() { return Iterator(c.indexToEntity.end(), c.components.end()); } }; template bool put(T*& t, Entity e, Args&&... args) { size_t index = components.getLength(); size_t* indexP = nullptr; if(!entityToIndex.tryEmplace(indexP, e, index)) { return false; } indexToEntity.add(e); 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 e) { size_t* indexP = entityToIndex.search(e); if(indexP == nullptr) { return false; } size_t lastIndex = components.getLength() - 1; size_t index = *indexP; entityToIndex.remove(e); 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) { return const_cast( static_cast(this)->search(e)); } 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(); } IteratorAdapter entities() { return {*this}; } IteratorAdapter entities() const { return {*this}; } }; }