Components.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #ifndef CORE_COMPONENTS_H
  2. #define CORE_COMPONENTS_H
  3. #include "core/HashMap.h"
  4. #include "core/List.h"
  5. #define isInvalidKeySize(key) ((key) == 0)
  6. #define equalSize(a, b) ((a) == (b))
  7. #define hashSize(key) (key)
  8. LIST(size_t, Size)
  9. HASHMAP(size_t, size_t, Size)
  10. typedef size_t Entity;
  11. #define COMPONENTS(T, N) \
  12. typedef struct { \
  13. HashMapSize entityToIndex; \
  14. ListSize indexToEntity; \
  15. List##N components; \
  16. } Components##N; \
  17. \
  18. typedef struct { \
  19. Entity entity; \
  20. T* component; \
  21. } ComponentNode##N; \
  22. \
  23. typedef struct { \
  24. const Entity* indexToEntity; \
  25. const Entity* indexToEntityEnd; \
  26. T* component; \
  27. T* componentEnd; \
  28. ComponentNode##N node; \
  29. } ComponentIterator##N; \
  30. \
  31. void initComponents##N(Components##N* c); \
  32. void destroyComponents##N(Components##N* c); \
  33. T* getOrAddComponent##N(Components##N* c, Entity e); \
  34. T* searchComponent##N(Components##N* c, Entity e); \
  35. bool removeComponent##N(Components##N* c, Entity e); \
  36. void initComponentIterator##N(ComponentIterator##N* ci, Components##N* c); \
  37. bool hasNextComponentNode##N(ComponentIterator##N* ci); \
  38. ComponentNode##N* nextComponentNode##N(ComponentIterator##N* ci); \
  39. T* getComponentsStart##N(Components##N* c); \
  40. T* getComponentsEnd##N(Components##N* c);
  41. #define COMPONENTS_SOURCE(T, N) \
  42. void initComponents##N(Components##N* c) { \
  43. initHashMapSize(&c->entityToIndex); \
  44. initListSize(&c->indexToEntity); \
  45. initList##N(&c->components); \
  46. } \
  47. \
  48. void destroyComponents##N(Components##N* c) { \
  49. destroyHashMapSize(&c->entityToIndex); \
  50. destroyListSize(&c->indexToEntity); \
  51. destroyList##N(&c->components); \
  52. } \
  53. \
  54. T* getOrAddComponent##N(Components##N* c, Entity e) { \
  55. void* component = searchComponent##N(c, e); \
  56. if(component != nullptr) { \
  57. return component; \
  58. } \
  59. size_t index = c->components.length; \
  60. *putHashMapKeySize(&c->entityToIndex, e) = index; \
  61. addListDataSize(&c->indexToEntity, e); \
  62. return addEmptyListData##N(&c->components); \
  63. } \
  64. \
  65. T* searchComponent##N(Components##N* c, Entity e) { \
  66. size_t* index = searchHashMapKeySize(&c->entityToIndex, e); \
  67. if(index == nullptr) { \
  68. return nullptr; \
  69. } \
  70. return getListIndex##N(&c->components, *index); \
  71. } \
  72. \
  73. bool removeComponent##N(Components##N* c, Entity e) { \
  74. size_t* indexP = searchHashMapKeySize(&c->entityToIndex, e); \
  75. if(indexP == nullptr) { \
  76. return false; \
  77. } \
  78. size_t lastIndex = c->components.length - 1; \
  79. size_t index = *indexP; \
  80. removeHashMapKeySize(&c->entityToIndex, e); \
  81. removeListIndexBySwap##N(&c->components, index); \
  82. if(index == lastIndex) { \
  83. removeListIndexBySwapSize(&c->indexToEntity, index); \
  84. return true; \
  85. } \
  86. Entity other = *getListIndexSize(&c->indexToEntity, lastIndex); \
  87. removeListIndexBySwapSize(&c->indexToEntity, index); \
  88. *putHashMapKeySize(&c->entityToIndex, other) = index; \
  89. return true; \
  90. } \
  91. \
  92. void initComponentIterator##N(ComponentIterator##N* ci, \
  93. Components##N* c) { \
  94. ci->indexToEntity = getListStartSize(&c->indexToEntity); \
  95. ci->indexToEntityEnd = getListEndSize(&c->indexToEntity); \
  96. ci->component = getListStart##N(&c->components); \
  97. ci->componentEnd = getListEnd##N(&c->components); \
  98. ci->node = (ComponentNode##N){0}; \
  99. } \
  100. \
  101. bool hasNextComponentNode##N(ComponentIterator##N* ci) { \
  102. return ci->indexToEntity != ci->indexToEntityEnd; \
  103. } \
  104. \
  105. ComponentNode##N* nextComponentNode##N(ComponentIterator##N* ci) { \
  106. ci->node.component = ci->component; \
  107. ci->node.entity = *ci->indexToEntity; \
  108. ci->indexToEntity++; \
  109. ci->component++; \
  110. return &ci->node; \
  111. } \
  112. \
  113. T* getComponentsStart##N(Components##N* c) { \
  114. return getListStart##N(&c->components); \
  115. } \
  116. \
  117. T* getComponentsEnd##N(Components##N* c) { \
  118. return getListEnd##N(&c->components); \
  119. } \
  120. LIST_SOURCE(size_t, Size) \
  121. HASHMAP_SOURCE(size_t, size_t, Size)
  122. #endif