|
@@ -6,42 +6,121 @@ typedef uint32 Entity;
|
|
|
|
|
|
template<typename T>
|
|
|
class Components final {
|
|
|
- HashMap<Entity, T> components;
|
|
|
+ HashMap<Entity, int> entityToIndex;
|
|
|
+ List<Entity> indexToEntity;
|
|
|
+ List<T> components;
|
|
|
|
|
|
public:
|
|
|
- Components() {
|
|
|
- }
|
|
|
+ template<typename R>
|
|
|
+ struct Node {
|
|
|
+ const Entity& entity;
|
|
|
+ R& component;
|
|
|
+ };
|
|
|
+
|
|
|
+ template<typename C, typename R>
|
|
|
+ class EntityIterator final {
|
|
|
+ C& components;
|
|
|
+ int index;
|
|
|
+
|
|
|
+ public:
|
|
|
+ EntityIterator(C& components, int 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 {
|
|
|
+ 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>
|
|
|
void add(Entity e, Args&&... args) {
|
|
|
- components.tryEmplace(e, std::forward<Args>(args)...);
|
|
|
+ int index = components.getLength();
|
|
|
+ if(entityToIndex.tryEmplace(e, index)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ components.add(std::forward<Args>(args)...);
|
|
|
+ indexToEntity.add(e);
|
|
|
}
|
|
|
|
|
|
void remove(Entity e) {
|
|
|
- components.remove(e);
|
|
|
+ int* indexP = entityToIndex.search(e);
|
|
|
+ if(indexP == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ int lastIndex = components.getLength() - 1;
|
|
|
+ int index = *indexP;
|
|
|
+ entityToIndex.remove(e);
|
|
|
+ components.removeBySwap(index);
|
|
|
+ if(index == lastIndex) {
|
|
|
+ indexToEntity.removeBySwap(index);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Entity other = indexToEntity[lastIndex];
|
|
|
+ indexToEntity.removeBySwap(index);
|
|
|
+ entityToIndex.add(other, index);
|
|
|
}
|
|
|
|
|
|
T* search(Entity e) {
|
|
|
- return components.search(e);
|
|
|
+ int* index = entityToIndex.search(e);
|
|
|
+ if(index == nullptr) {
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+ return &(components[*index]);
|
|
|
}
|
|
|
|
|
|
const T* search(Entity e) const {
|
|
|
- return components.search(e);
|
|
|
+ const int* index = entityToIndex.search(e);
|
|
|
+ if(index == nullptr) {
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+ return &(components[*index]);
|
|
|
}
|
|
|
|
|
|
- auto begin() {
|
|
|
+ T* begin() {
|
|
|
return components.begin();
|
|
|
}
|
|
|
|
|
|
- const auto begin() const {
|
|
|
+ const T* begin() const {
|
|
|
return components.begin();
|
|
|
}
|
|
|
|
|
|
- auto end() {
|
|
|
+ T* end() {
|
|
|
return components.end();
|
|
|
}
|
|
|
|
|
|
- const auto end() const {
|
|
|
+ const T* end() const {
|
|
|
return components.end();
|
|
|
}
|
|
|
+
|
|
|
+ EntityIteratorAdapter<Components, T> entities() {
|
|
|
+ return {*this};
|
|
|
+ }
|
|
|
+
|
|
|
+ EntityIteratorAdapter<const Components, const T> entities() const {
|
|
|
+ return {*this};
|
|
|
+ }
|
|
|
};
|