瀏覽代碼

example: multi instance storage

Michele Caini 5 年之前
父節點
當前提交
eb8e96f413
共有 2 個文件被更改,包括 94 次插入0 次删除
  1. 1 0
      test/CMakeLists.txt
  2. 93 0
      test/example/multi_instance_storage.cpp

+ 1 - 0
test/CMakeLists.txt

@@ -97,6 +97,7 @@ endif()
 
 if(BUILD_EXAMPLE)
     SETUP_BASIC_TEST(custom_identifier example/custom_identifier.cpp)
+    SETUP_BASIC_TEST(multi_instance_storage example/multi_instance_storage.cpp)
 endif()
 
 # Test lib

+ 93 - 0
test/example/multi_instance_storage.cpp

@@ -0,0 +1,93 @@
+#include <utility>
+#include <vector>
+#include <gtest/gtest.h>
+#include <entt/entity/pool.hpp>
+#include <entt/entity/registry.hpp>
+#include <entt/entity/sparse_set.hpp>
+#include <entt/entity/storage.hpp>
+
+/**
+ * Yeah, I could have used a single memory chunk and a free list and associated
+ * entities with a pointer to their first element, but this is just an example
+ * of how to create a custom storage class.
+ * You can have fun regarding the actual implementation.
+ */
+template<typename Entity, typename Type>
+struct multi_instance_storage: entt::basic_storage<Entity, std::vector<Type>> {
+    using underlying_storage = entt::basic_storage<Entity, std::vector<Type>>;
+
+    using value_type = typename underlying_storage::value_type;
+    using entity_type = typename underlying_storage::entity_type;
+    using size_type = typename underlying_storage::size_type;
+    using iterator = typename underlying_storage::iterator;
+    using const_iterator = typename underlying_storage::const_iterator;
+
+    template<typename... Args>
+    void insert(Args &&...) = delete;
+
+    using underlying_storage::erase;
+
+    template<typename... Args>
+    Type & emplace(const entity_type entt, Args &&... args) {
+        std::vector<Type> *vec = underlying_storage::try_get(entt);
+
+        if(!vec) {
+            vec = &underlying_storage::emplace(entt);
+        }
+
+        return vec->emplace_back(Type{std::forward<Args>(args)...});
+    }
+
+    void erase(const entity_type entt, const size_type index) {
+        auto &vec = underlying_storage::get(entt);
+        vec.erase(vec.begin() + index);
+
+        if(vec.empty()) {
+            underlying_storage::erase(entt);
+        }
+    }
+};
+
+struct single_instance_type { int value; };
+struct multi_instance_type { int value; };
+
+template<typename Entity>
+struct entt::pool<Entity, multi_instance_type> {
+    using type = storage_adapter<multi_instance_storage<Entity, multi_instance_type>>;
+};
+
+TEST(Example, MultiInstanceStorage) {
+    entt::registry registry;
+    const auto entity = registry.create();
+
+    ASSERT_FALSE(registry.has<multi_instance_type>(entity));
+
+    registry.emplace<multi_instance_type>(entity, 0);
+
+    ASSERT_TRUE(registry.has<multi_instance_type>(entity));
+    ASSERT_EQ(registry.get<multi_instance_type>(entity).size(), 1u);
+    
+    registry.remove<multi_instance_type>(entity, 0u);
+    
+    ASSERT_FALSE(registry.has<multi_instance_type>(entity));
+    
+    registry.emplace<multi_instance_type>(entity, 42);
+    registry.emplace<multi_instance_type>(entity, 3);
+    registry.emplace<multi_instance_type>(entity, 0);
+    
+    ASSERT_EQ(registry.get<multi_instance_type>(entity).size(), 3u);
+    ASSERT_EQ(registry.get<multi_instance_type>(entity)[0].value, 42);
+    ASSERT_EQ(registry.get<multi_instance_type>(entity)[1].value, 3);
+    ASSERT_EQ(registry.get<multi_instance_type>(entity)[2].value, 0);
+    
+    registry.remove<multi_instance_type>(entity, 1u);
+
+    ASSERT_TRUE(registry.has<multi_instance_type>(entity));
+    ASSERT_EQ(registry.get<multi_instance_type>(entity).size(), 2u);
+    ASSERT_EQ(registry.get<multi_instance_type>(entity)[0].value, 42);
+    ASSERT_EQ(registry.get<multi_instance_type>(entity)[1].value, 0);
+    
+    registry.remove<multi_instance_type>(entity);
+    
+    ASSERT_FALSE(registry.has<multi_instance_type>(entity));
+}