multi_instance_storage.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #include <utility>
  2. #include <vector>
  3. #include <gtest/gtest.h>
  4. #include <entt/entity/pool.hpp>
  5. #include <entt/entity/registry.hpp>
  6. #include <entt/entity/sparse_set.hpp>
  7. #include <entt/entity/storage.hpp>
  8. /**
  9. * Yeah, I could have used a single memory chunk and a free list and associated
  10. * entities with a pointer to their first element, but this is just an example
  11. * of how to create a custom storage class.
  12. * You can have fun regarding the actual implementation.
  13. */
  14. template<typename Entity, typename Type>
  15. struct multi_instance_storage: entt::basic_storage<Entity, std::vector<Type>> {
  16. using underlying_storage = entt::basic_storage<Entity, std::vector<Type>>;
  17. using value_type = typename underlying_storage::value_type;
  18. using entity_type = typename underlying_storage::entity_type;
  19. using size_type = typename underlying_storage::size_type;
  20. using iterator = typename underlying_storage::iterator;
  21. using const_iterator = typename underlying_storage::const_iterator;
  22. template<typename... Args> void insert(Args &&...) = delete;
  23. using underlying_storage::remove;
  24. using underlying_storage::erase;
  25. template<typename... Args>
  26. Type & emplace(const entity_type entt, Args &&... args) {
  27. std::vector<Type> *vec = underlying_storage::try_get(entt);
  28. if(!vec) {
  29. vec = &underlying_storage::emplace(entt);
  30. }
  31. return vec->emplace_back(Type{std::forward<Args>(args)...});
  32. }
  33. void remove(const entity_type entt, const size_type index) {
  34. auto &vec = underlying_storage::get(entt);
  35. vec.erase(vec.begin() + index);
  36. if(vec.empty()) {
  37. underlying_storage::remove(entt);
  38. }
  39. }
  40. };
  41. struct single_instance_type { int value; };
  42. struct multi_instance_type { int value; };
  43. template<typename Entity>
  44. struct entt::pool<Entity, multi_instance_type> {
  45. using type = storage_adapter_mixin<multi_instance_storage<Entity, multi_instance_type>>;
  46. };
  47. TEST(Example, MultiInstanceStorage) {
  48. entt::registry registry;
  49. const auto entity = registry.create();
  50. ASSERT_FALSE(registry.has<multi_instance_type>(entity));
  51. registry.emplace<multi_instance_type>(entity, 0);
  52. ASSERT_TRUE(registry.has<multi_instance_type>(entity));
  53. ASSERT_EQ(registry.get<multi_instance_type>(entity).size(), 1u);
  54. registry.remove<multi_instance_type>(entity, 0u);
  55. ASSERT_FALSE(registry.has<multi_instance_type>(entity));
  56. registry.emplace<multi_instance_type>(entity, 42);
  57. registry.emplace<multi_instance_type>(entity, 3);
  58. registry.emplace<multi_instance_type>(entity, 0);
  59. ASSERT_EQ(registry.get<multi_instance_type>(entity).size(), 3u);
  60. ASSERT_EQ(registry.get<multi_instance_type>(entity)[0].value, 42);
  61. ASSERT_EQ(registry.get<multi_instance_type>(entity)[1].value, 3);
  62. ASSERT_EQ(registry.get<multi_instance_type>(entity)[2].value, 0);
  63. registry.remove<multi_instance_type>(entity, 1u);
  64. ASSERT_TRUE(registry.has<multi_instance_type>(entity));
  65. ASSERT_EQ(registry.get<multi_instance_type>(entity).size(), 2u);
  66. ASSERT_EQ(registry.get<multi_instance_type>(entity)[0].value, 42);
  67. ASSERT_EQ(registry.get<multi_instance_type>(entity)[1].value, 0);
  68. registry.remove<multi_instance_type>(entity);
  69. ASSERT_FALSE(registry.has<multi_instance_type>(entity));
  70. }