Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

142 rader
3.6 KiB

  1. #pragma once
  2. #include <queue>
  3. #include <ecs/config.h>
  4. #include <ecs/core/utils/bitset.h>
  5. beg_namespace_ecs_core_entity_storage
  6. {
  7. struct entity_handle
  8. {
  9. private:
  10. uint32_t _index;
  11. uint32_t _counter;
  12. public:
  13. entity_handle(uint32_t i, uint32_t c)
  14. : _index (i)
  15. , _counter (c)
  16. { }
  17. inline auto index() const
  18. { return _index; }
  19. inline auto counter() const
  20. { return _counter; }
  21. };
  22. template <typename T_settings, typename T_chunk_meta_data>
  23. struct entity_meta_data
  24. {
  25. public:
  26. using bitset_type = utils::bitset<T_settings>;
  27. using chunk_meta_data_type = T_chunk_meta_data;
  28. using counter_type = uint32_t;
  29. private:
  30. bitset_type _bitset;
  31. counter_type _counter;
  32. chunk_meta_data_type _chunk_meta_data;
  33. public:
  34. entity_meta_data()
  35. : _counter(0)
  36. { }
  37. inline auto& bitset()
  38. { return _bitset; }
  39. inline auto counter() const
  40. { return _counter; }
  41. inline auto& chunk_meta_data()
  42. { return _chunk_meta_data; }
  43. inline void reset()
  44. {
  45. ++_counter;
  46. _bitset.clear();
  47. }
  48. };
  49. template<typename T_container_builder, typename T_settings, typename T_chunk_meta_data>
  50. struct base
  51. {
  52. public:
  53. using entity_handle_type = entity_handle;
  54. using entity_meta_data_type = entity_meta_data<T_settings, T_chunk_meta_data>;
  55. private:
  56. using container_type = typename T_container_builder::template type<entity_meta_data_type>;
  57. using queue_type = std::queue<uint32_t>;
  58. static constexpr decltype(auto) grow_size = 64;
  59. protected:
  60. container_type _container;
  61. queue_type _free_ids;
  62. private:
  63. inline void grow(size_t count)
  64. {
  65. auto old_size = _container.size();
  66. _container.resize(old_size + count);
  67. for (size_t i = old_size; i < _container.size(); ++i)
  68. {
  69. _free_ids.emplace(i);
  70. }
  71. }
  72. public:
  73. inline bool is_valid(const entity_handle& handle) const
  74. {
  75. return handle.index() < _container.size()
  76. && _container.at(handle.index()).counter() == handle.counter();
  77. }
  78. inline decltype(auto) claim()
  79. {
  80. if (_free_ids.empty())
  81. {
  82. grow(grow_size);
  83. }
  84. assert(!_free_ids.empty());
  85. auto index = _free_ids.back();
  86. auto& item = _container.at(index);
  87. _free_ids.pop();
  88. return entity_handle(index, item.counter());
  89. }
  90. inline void reclaim(const entity_handle& handle)
  91. {
  92. if (!is_valid(handle))
  93. throw std::invalid_argument("invalid entity handle");
  94. auto index = handle.index();
  95. auto& item = _container.at(index);
  96. item.reset();
  97. _free_ids.emplace(index);
  98. }
  99. inline void clear()
  100. {
  101. _free_ids = queue_type { };
  102. for (size_t i = 0; i < _container.size(); ++i)
  103. {
  104. _container.at(i).reset();
  105. _free_ids.emplace(i);
  106. }
  107. }
  108. inline auto& meta_data(const entity_handle& handle)
  109. {
  110. if (!is_valid(handle))
  111. throw std::invalid_argument("invalid entity handle");
  112. auto index = handle.index();
  113. return _container.at(index);
  114. }
  115. };
  116. }
  117. end_namespace_ecs_core_entity_storage