#ifndef CORE_COMPONENTS_H #define CORE_COMPONENTS_H #include "core/HashMap.h" #include "core/List.h" #define isInvalidKeySize(key) ((key) == 0) #define equalSize(a, b) ((a) == (b)) #define hashSize(key) (key) LIST(size_t, Size) HASHMAP(size_t, size_t, Size) typedef size_t Entity; #define COMPONENTS(T, N) \ typedef struct { \ HashMapSize entityToIndex; \ ListSize indexToEntity; \ List##N components; \ } Components##N; \ \ typedef struct { \ Entity entity; \ T* component; \ } ComponentNode##N; \ \ typedef struct { \ const Entity* indexToEntity; \ const Entity* indexToEntityEnd; \ T* component; \ T* componentEnd; \ ComponentNode##N node; \ } ComponentIterator##N; \ \ void initComponents##N(Components##N* c); \ void destroyComponents##N(Components##N* c); \ T* getOrAddComponent##N(Components##N* c, Entity e); \ T* searchComponent##N(Components##N* c, Entity e); \ bool removeComponent##N(Components##N* c, Entity e); \ void initComponentIterator##N(ComponentIterator##N* ci, Components##N* c); \ bool hasNextComponentNode##N(ComponentIterator##N* ci); \ ComponentNode##N* nextComponentNode##N(ComponentIterator##N* ci); \ T* getComponentsStart##N(Components##N* c); \ T* getComponentsEnd##N(Components##N* c); #define COMPONENTS_SOURCE(T, N) \ void initComponents##N(Components##N* c) { \ initHashMapSize(&c->entityToIndex); \ initListSize(&c->indexToEntity); \ initList##N(&c->components); \ } \ \ void destroyComponents##N(Components##N* c) { \ destroyHashMapSize(&c->entityToIndex); \ destroyListSize(&c->indexToEntity); \ destroyList##N(&c->components); \ } \ \ T* getOrAddComponent##N(Components##N* c, Entity e) { \ void* component = searchComponent##N(c, e); \ if(component != nullptr) { \ return component; \ } \ size_t index = c->components.length; \ *putHashMapKeySize(&c->entityToIndex, e) = index; \ addListDataSize(&c->indexToEntity, e); \ return addEmptyListData##N(&c->components); \ } \ \ T* searchComponent##N(Components##N* c, Entity e) { \ size_t* index = searchHashMapKeySize(&c->entityToIndex, e); \ if(index == nullptr) { \ return nullptr; \ } \ return getListIndex##N(&c->components, *index); \ } \ \ bool removeComponent##N(Components##N* c, Entity e) { \ size_t* indexP = searchHashMapKeySize(&c->entityToIndex, e); \ if(indexP == nullptr) { \ return false; \ } \ size_t lastIndex = c->components.length - 1; \ size_t index = *indexP; \ removeHashMapKeySize(&c->entityToIndex, e); \ removeListIndexBySwap##N(&c->components, index); \ if(index == lastIndex) { \ removeListIndexBySwapSize(&c->indexToEntity, index); \ return true; \ } \ Entity other = *getListIndexSize(&c->indexToEntity, lastIndex); \ removeListIndexBySwapSize(&c->indexToEntity, index); \ *putHashMapKeySize(&c->entityToIndex, other) = index; \ return true; \ } \ \ void initComponentIterator##N(ComponentIterator##N* ci, \ Components##N* c) { \ ci->indexToEntity = getListStartSize(&c->indexToEntity); \ ci->indexToEntityEnd = getListEndSize(&c->indexToEntity); \ ci->component = getListStart##N(&c->components); \ ci->componentEnd = getListEnd##N(&c->components); \ ci->node = (ComponentNode##N){0}; \ } \ \ bool hasNextComponentNode##N(ComponentIterator##N* ci) { \ return ci->indexToEntity != ci->indexToEntityEnd; \ } \ \ ComponentNode##N* nextComponentNode##N(ComponentIterator##N* ci) { \ ci->node.component = ci->component; \ ci->node.entity = *ci->indexToEntity; \ ci->indexToEntity++; \ ci->component++; \ return &ci->node; \ } \ \ T* getComponentsStart##N(Components##N* c) { \ return getListStart##N(&c->components); \ } \ \ T* getComponentsEnd##N(Components##N* c) { \ return getListEnd##N(&c->components); \ } \ LIST_SOURCE(size_t, Size) \ HASHMAP_SOURCE(size_t, size_t, Size) #endif