Răsfoiți Sursa

entt::component is now available

Michele Caini 6 ani în urmă
părinte
comite
7691a9bdad

+ 0 - 3
TODO

@@ -10,9 +10,6 @@
 * allow for built-in parallel each if possible
 * allow to replace std:: with custom implementations
 * remove runtime views, welcome reflection and what about snapshot?
-* empty components model allows for shared components and prefabs unity-like
-  - each with entity return the shared component multiple times, one per entity that refers to it
-  - each components only return actual component, so shared components are returned only once
 * types defined at runtime that refer to the same compile-time type (but to different pools) are possible, the library is almost there
 * add opaque input iterators to views and groups that return tuples <entity, T &...> (proxy), multi-pass guaranteed
 * add fast lane for raw iterations, extend mt doc to describe allowed add/remove with pre-allocations on fast lanes

+ 13 - 0
src/entt/core/type_traits.hpp

@@ -154,6 +154,19 @@ template<class Type>
 constexpr auto is_named_type_v = is_named_type<Type>::value;
 
 
+/**
+ * @brief Defines an enum class to use for opaque identifiers and a dedicate
+ * `to_integer` function to convert the identifiers to their underlying type.
+ * @param clazz The name to use for the enum class.
+ * @param type The underlying type for the enum class.
+ */
+#define ENTT_OPAQUE_TYPE(clazz, type)\
+    enum class clazz: type {};\
+    constexpr auto to_integer(const clazz id) ENTT_NOEXCEPT {\
+        return std::underlying_type_t<clazz>(id);\
+    }
+
+
 }
 
 

+ 0 - 14
src/entt/entity/entity.hpp

@@ -165,20 +165,6 @@ constexpr bool operator!=(const Entity entity, null other) ENTT_NOEXCEPT {
 constexpr auto null = internal::null{};
 
 
-/**
- * @brief Defines an enum class to use for entity identifiers and a dedicate
- * `to_integer` function to convert the identifiers to their underlying type.
- * @param clazz The name to use for the enum class.
- * @param type The underlying type for the enum class.
- */
-#define ENTT_ENTITY_TYPE(clazz, type)\
-    enum class clazz: type {};\
-    constexpr auto to_integer(const clazz entt) ENTT_NOEXCEPT {\
-        using traits_type = entt_traits<std::underlying_type_t<clazz>>;\
-        return typename traits_type::entity_type(entt);\
-    }
-
-
 }
 
 

+ 5 - 2
src/entt/entity/fwd.hpp

@@ -4,7 +4,7 @@
 
 #include <cstdint>
 #include "../config/config.h"
-#include "entity.hpp"
+#include "../core/type_traits.hpp"
 
 
 namespace entt {
@@ -50,7 +50,10 @@ template<typename>
 class basic_continuous_loader;
 
 /*! @brief Alias declaration for the most common use case. */
-ENTT_ENTITY_TYPE(entity, std::uint32_t)
+ENTT_OPAQUE_TYPE(entity, ENTT_ID_TYPE)
+
+/*! @brief Alias declaration for the most common use case. */
+ENTT_OPAQUE_TYPE(component, ENTT_ID_TYPE)
 
 /*! @brief Alias declaration for the most common use case. */
 using registry = basic_registry<entity>;

+ 1 - 2
src/entt/entity/prototype.hpp

@@ -40,7 +40,6 @@ namespace entt {
 template<typename Entity>
 class basic_prototype {
     using basic_fn_type = void(const basic_prototype &, basic_registry<Entity> &, const Entity);
-    using component_type = typename basic_registry<Entity>::component_type;
 
     template<typename Component>
     struct component_wrapper { Component component; };
@@ -471,7 +470,7 @@ public:
     }
 
 private:
-    std::unordered_map<component_type, component_handler> handlers;
+    std::unordered_map<component, component_handler> handlers;
     registry_type *reg;
     entity_type entity;
 };

+ 12 - 14
src/entt/entity/registry.hpp

@@ -211,7 +211,7 @@ class basic_registry {
     struct group_data {
         const std::size_t extent[3];
         std::unique_ptr<void, void(*)(void *)> group;
-        bool(* const is_same)(const ENTT_ID_TYPE *);
+        bool(* const is_same)(const component *);
     };
 
     struct ctx_variable {
@@ -240,7 +240,7 @@ class basic_registry {
 
     template<typename Component>
     const auto * pool() const ENTT_NOEXCEPT {
-        const auto ctype = type<Component>();
+        const auto ctype = to_integer(type<Component>());
 
         if constexpr(is_named_type_v<Component>) {
             const auto it = std::find_if(pools.begin()+skip_family_pools, pools.end(), [ctype](const auto &candidate) {
@@ -260,7 +260,7 @@ class basic_registry {
 
     template<typename Component>
     auto * assure() {
-        const auto ctype = type<Component>();
+        const auto ctype = to_integer(type<Component>());
         pool_data *pdata = nullptr;
 
         if constexpr(is_named_type_v<Component>) {
@@ -308,8 +308,6 @@ public:
     using version_type = typename traits_type::version_type;
     /*! @brief Unsigned integer type. */
     using size_type = typename sparse_set<Entity>::size_type;
-    /*! @brief Unsigned integer type. */
-    using component_type = ENTT_ID_TYPE;
 
     /*! @brief Default constructor. */
     basic_registry() ENTT_NOEXCEPT = default;
@@ -331,8 +329,8 @@ public:
      * @return Runtime numeric identifier of the given type of component.
      */
     template<typename Component>
-    static component_type type() ENTT_NOEXCEPT {
-        return runtime_type<Component, component_family>();
+    static component type() ENTT_NOEXCEPT {
+        return component{runtime_type<Component, component_family>()};
     }
 
     /**
@@ -1316,7 +1314,7 @@ public:
         using handler_type = group_handler<exclude_t<Exclude...>, get_t<Get...>, Owned...>;
 
         const std::size_t extent[] = { sizeof...(Owned), sizeof...(Get), sizeof...(Exclude) };
-        const ENTT_ID_TYPE types[] = { type<Owned>()..., type<Get>()..., type<Exclude>()... };
+        const component types[] = { type<Owned>()..., type<Get>()..., type<Exclude>()... };
         handler_type *curr = nullptr;
 
         if(auto it = std::find_if(groups.begin(), groups.end(), [&extent, &types](auto &&gdata) {
@@ -1330,8 +1328,8 @@ public:
             groups.push_back(group_data{
                 { sizeof...(Owned), sizeof...(Get), sizeof...(Exclude) },
                 decltype(group_data::group){new handler_type{}, [](void *gptr) { delete static_cast<handler_type *>(gptr); }},
-                [](const ENTT_ID_TYPE *other) {
-                    const std::size_t ctypes[] = { type<Owned>()..., type<Get>()..., type<Exclude>()... };
+                [](const component *other) {
+                    const component ctypes[] = { type<Owned>()..., type<Get>()..., type<Exclude>()... };
                     return std::equal(std::begin(ctypes), std::end(ctypes), other);
                 }
             });
@@ -1427,11 +1425,11 @@ public:
      */
     template<typename It>
     entt::basic_runtime_view<Entity> runtime_view(It first, It last) const {
-        static_assert(std::is_convertible_v<typename std::iterator_traits<It>::value_type, component_type>);
+        static_assert(std::is_same_v<typename std::iterator_traits<It>::value_type, component>);
         std::vector<const sparse_set<Entity> *> set(std::distance(first, last));
 
-        std::transform(first, last, set.begin(), [this](const component_type ctype) {
-            auto it = std::find_if(pools.begin(), pools.end(), [ctype](const auto &pdata) {
+        std::transform(first, last, set.begin(), [this](const component ctype) {
+            auto it = std::find_if(pools.begin(), pools.end(), [ctype = to_integer(ctype)](const auto &pdata) {
                 return pdata.pool && pdata.runtime_type == ctype;
             });
 
@@ -1477,7 +1475,7 @@ public:
         other.pools.resize(pools.size());
 
         for(auto pos = pools.size(); pos; --pos) {
-            if(auto &pdata = pools[pos-1]; pdata.pool && (!sizeof...(Component) || ... || (pdata.runtime_type == type<Component>()))) {
+            if(auto &pdata = pools[pos-1]; pdata.pool && (!sizeof...(Component) || ... || (pdata.runtime_type == to_integer(type<Component>())))) {
                 auto &curr = other.pools[pos-1];
                 curr.clone = pdata.clone;
                 curr.remove = pdata.remove;

+ 8 - 16
test/entt/entity/runtime_view.cpp

@@ -5,13 +5,12 @@
 
 TEST(RuntimeView, Functionalities) {
     entt::registry registry;
-    using component_type = typename decltype(registry)::component_type;
 
     // forces the creation of the pools
     registry.reserve<int>(0);
     registry.reserve<char>(0);
 
-    component_type types[] = { registry.type<int>(), registry.type<char>() };
+    entt::component types[] = { registry.type<int>(), registry.type<char>() };
     auto view = registry.runtime_view(std::begin(types), std::end(types));
 
     ASSERT_TRUE(view.empty());
@@ -49,13 +48,12 @@ TEST(RuntimeView, Functionalities) {
 
 TEST(RuntimeView, Iterator) {
     entt::registry registry;
-    using component_type = typename decltype(registry)::component_type;
 
     const auto entity = registry.create();
     registry.assign<int>(entity);
     registry.assign<char>(entity);
 
-    component_type types[] = { registry.type<int>(), registry.type<char>() };
+    entt::component types[] = { registry.type<int>(), registry.type<char>() };
     auto view = registry.runtime_view(std::begin(types), std::end(types));
     using iterator_type = typename decltype(view)::iterator_type;
 
@@ -74,7 +72,6 @@ TEST(RuntimeView, Iterator) {
 
 TEST(RuntimeView, Contains) {
     entt::registry registry;
-    using component_type = typename decltype(registry)::component_type;
 
     const auto e0 = registry.create();
     registry.assign<int>(e0);
@@ -86,7 +83,7 @@ TEST(RuntimeView, Contains) {
 
     registry.destroy(e0);
 
-    component_type types[] = { registry.type<int>(), registry.type<char>() };
+    entt::component types[] = { registry.type<int>(), registry.type<char>() };
     auto view = registry.runtime_view(std::begin(types), std::end(types));
 
     ASSERT_FALSE(view.contains(e0));
@@ -95,7 +92,6 @@ TEST(RuntimeView, Contains) {
 
 TEST(RuntimeView, Empty) {
     entt::registry registry;
-    using component_type = typename decltype(registry)::component_type;
 
     const auto e0 = registry.create();
     registry.assign<double>(e0);
@@ -106,7 +102,7 @@ TEST(RuntimeView, Empty) {
     registry.assign<char>(e1);
     registry.assign<float>(e1);
 
-    component_type types[] = { registry.type<char>(), registry.type<int>(), registry.type<float>() };
+    entt::component types[] = { registry.type<char>(), registry.type<int>(), registry.type<float>() };
     auto view = registry.runtime_view(std::begin(types), std::end(types));
 
     for(auto entity: view) {
@@ -117,7 +113,6 @@ TEST(RuntimeView, Empty) {
 
 TEST(RuntimeView, Each) {
     entt::registry registry;
-    using component_type = typename decltype(registry)::component_type;
 
     const auto e0 = registry.create();
     registry.assign<int>(e0);
@@ -127,7 +122,7 @@ TEST(RuntimeView, Each) {
     registry.assign<int>(e1);
     registry.assign<char>(e1);
 
-    component_type types[] = { registry.type<int>(), registry.type<char>() };
+    entt::component types[] = { registry.type<int>(), registry.type<char>() };
     auto view = registry.runtime_view(std::begin(types), std::end(types));
     std::size_t cnt = 0;
 
@@ -138,7 +133,6 @@ TEST(RuntimeView, Each) {
 
 TEST(RuntimeView, EachWithHoles) {
     entt::registry registry;
-    using component_type = typename decltype(registry)::component_type;
 
     const auto e0 = registry.create();
     const auto e1 = registry.create();
@@ -150,7 +144,7 @@ TEST(RuntimeView, EachWithHoles) {
     registry.assign<int>(e0, 0);
     registry.assign<int>(e2, 2);
 
-    component_type types[] = { registry.type<int>(), registry.type<char>() };
+    entt::component types[] = { registry.type<int>(), registry.type<char>() };
     auto view = registry.runtime_view(std::begin(types), std::end(types));
 
     view.each([e0](auto entity) {
@@ -160,12 +154,11 @@ TEST(RuntimeView, EachWithHoles) {
 
 TEST(RuntimeView, MissingPool) {
     entt::registry registry;
-    using component_type = typename decltype(registry)::component_type;
 
     const auto e0 = registry.create();
     registry.assign<int>(e0);
 
-    component_type types[] = { registry.type<int>(), registry.type<char>() };
+    entt::component types[] = { registry.type<int>(), registry.type<char>() };
     auto view = registry.runtime_view(std::begin(types), std::end(types));
 
     ASSERT_TRUE(view.empty());
@@ -187,12 +180,11 @@ TEST(RuntimeView, MissingPool) {
 
 TEST(RuntimeView, EmptyRange) {
     entt::registry registry;
-    using component_type = typename decltype(registry)::component_type;
 
     const auto e0 = registry.create();
     registry.assign<int>(e0);
 
-    const component_type *ptr = nullptr;
+    const entt::component *ptr = nullptr;
     auto view = registry.runtime_view(ptr, ptr);
 
     ASSERT_TRUE(view.empty());

+ 2 - 2
test/lib/a_module.cpp

@@ -18,7 +18,7 @@ ENTT_NAMED_TYPE(char)
 ENTT_NAMED_TYPE(double)
 ENTT_NAMED_TYPE(float)
 
-LIB_EXPORT typename entt::registry::component_type a_module_int_type() {
+LIB_EXPORT typename entt::component a_module_int_type() {
     entt::registry registry;
 
     (void)registry.type<double>();
@@ -27,7 +27,7 @@ LIB_EXPORT typename entt::registry::component_type a_module_int_type() {
     return registry.type<int>();
 }
 
-LIB_EXPORT typename entt::registry::component_type a_module_char_type() {
+LIB_EXPORT typename entt::component a_module_char_type() {
     entt::registry registry;
 
     (void)registry.type<double>();

+ 2 - 2
test/lib/another_module.cpp

@@ -18,7 +18,7 @@ ENTT_NAMED_TYPE(char)
 ENTT_NAMED_TYPE(double)
 ENTT_NAMED_TYPE(float)
 
-LIB_EXPORT typename entt::registry::component_type another_module_int_type() {
+LIB_EXPORT typename entt::component another_module_int_type() {
     entt::registry registry;
 
     (void)registry.type<char>();
@@ -30,7 +30,7 @@ LIB_EXPORT typename entt::registry::component_type another_module_int_type() {
     return registry.type<int>();
 }
 
-LIB_EXPORT typename entt::registry::component_type another_module_char_type() {
+LIB_EXPORT typename entt::component another_module_char_type() {
     entt::registry registry;
 
     (void)registry.type<int>();

+ 4 - 4
test/lib/lib.cpp

@@ -5,10 +5,10 @@
 #include <entt/signal/emitter.hpp>
 #include "types.h"
 
-extern typename entt::registry::component_type a_module_int_type();
-extern typename entt::registry::component_type a_module_char_type();
-extern typename entt::registry::component_type another_module_int_type();
-extern typename entt::registry::component_type another_module_char_type();
+extern typename entt::component a_module_int_type();
+extern typename entt::component a_module_char_type();
+extern typename entt::component another_module_int_type();
+extern typename entt::component another_module_char_type();
 
 extern void update_position(int delta, entt::registry &);
 extern void assign_velocity(int, entt::registry &);

+ 9 - 9
test/mod/mod.cpp

@@ -123,7 +123,7 @@ duk_ret_t get(duk_context *ctx, entt::registry &registry) {
 
 class duktape_registry {
     // I'm pretty sure I won't have more than 99 components in the example
-    static constexpr entt::registry::component_type udef = 100;
+    static constexpr ENTT_ID_TYPE udef = 100;
 
     struct func_map {
         using func_type = duk_ret_t(*)(duk_context *, entt::registry &);
@@ -136,7 +136,7 @@ class duktape_registry {
 
     template<typename... Comp>
     void reg() {
-        ((func[registry.type<Comp>()] = {
+        ((func[to_integer(registry.type<Comp>())] = {
                 &::set<Comp>,
                 &::unset<Comp>,
                 &::has<Comp>,
@@ -163,7 +163,7 @@ class duktape_registry {
         auto type = duk_require_uint(ctx, 1);
 
         if(type >= udef) {
-            type = registry.type<duktape_runtime>();
+            type = to_integer(registry.type<duktape_runtime>());
         }
 
         assert(func.find(type) != func.cend());
@@ -214,20 +214,20 @@ public:
 
         duk_push_array(ctx);
 
-        std::vector<typename entt::registry::component_type> components;
-        std::vector<typename entt::registry::component_type> runtime;
+        std::vector<entt::component> components;
+        std::vector<entt::component> runtime;
 
         for(duk_idx_t arg = 0; arg < nargs; arg++) {
             auto type = duk_require_uint(ctx, arg);
 
             if(type < udef) {
-                components.push_back(type);
+                components.push_back(entt::component{type});
             } else {
                 if(runtime.empty()) {
                     components.push_back(dreg.registry.type<duktape_runtime>());
                 }
 
-                runtime.push_back(type);
+                runtime.push_back(entt::component{type});
             }
         }
 
@@ -240,7 +240,7 @@ public:
             } else {
                 const auto &others = dreg.registry.get<duktape_runtime>(entity).components;
                 const auto match = std::all_of(runtime.cbegin(), runtime.cend(), [&others](const auto type) {
-                    return others.find(type) != others.cend();
+                    return others.find(to_integer(type)) != others.cend();
                 });
 
                 if(match) {
@@ -272,7 +272,7 @@ const duk_function_list_entry js_duktape_registry_methods[] = {
 void export_types(duk_context *context, entt::registry &registry) {
     auto export_type = [](auto *ctx, auto &reg, auto idx, auto type, const auto *name) {
         duk_push_string(ctx, name);
-        duk_push_uint(ctx, reg.template type<typename decltype(type)::type>());
+        duk_push_uint(ctx, to_integer(reg.template type<typename decltype(type)::type>()));
         duk_def_prop(ctx, idx, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_CLEAR_WRITABLE);
     };