Browse Source

meta: factory seek functions for meta data and meta functions

skypjack 1 year ago
parent
commit
1ddc887ac4
3 changed files with 61 additions and 11 deletions
  1. 31 11
      src/entt/meta/factory.hpp
  2. 15 0
      test/entt/meta/meta_data.cpp
  3. 15 0
      test/entt/meta/meta_func.cpp

+ 31 - 11
src/entt/meta/factory.hpp

@@ -28,14 +28,8 @@ namespace internal {
 
 class basic_meta_factory {
 protected:
-    [[nodiscard]] inline decltype(auto) owner() {
-        auto &&context = internal::meta_context::from(*ctx);
-        ENTT_ASSERT(context.value.contains(parent), "Type not available");
-        return context.value[parent];
-    }
-
     void track(const id_type id) noexcept {
-        auto &&elem = owner();
+        auto &&elem = internal::meta_context::from(*ctx).value[parent];
         ENTT_ASSERT(elem.id == id || !resolve(*ctx, id), "Duplicate identifier");
         bucket = parent;
         elem.id = id;
@@ -57,7 +51,7 @@ protected:
     }
 
     void extend(meta_dtor_node node) {
-        owner().dtor = std::move(node);
+        internal::meta_context::from(*ctx).value[parent].dtor = std::move(node);
         bucket = parent;
     }
 
@@ -87,14 +81,18 @@ protected:
         details->func.insert_or_assign(id, std::move(node));
     }
 
+    void seek(const id_type id, const bool data) {
+        ENTT_ASSERT((data && (details->data.find(id) != details->data.cend())) || (!data && (details->func.find(id) != details->func.cend())), "Invalid id");
+        is_data = data;
+        bucket = id;
+    }
+
     void property(const id_type key, internal::meta_prop_node value) {
         if(bucket == parent) {
             details->prop[key] = std::move(value);
         } else if(is_data) {
-            ENTT_ASSERT(details->data.find(bucket) != details->data.cend(), "Invalid bucket");
             details->data[bucket].prop[key] = std::move(value);
         } else {
-            ENTT_ASSERT(details->func.find(bucket) != details->func.cend(), "Invalid bucket");
             details->func[bucket].prop[key] = std::move(value);
         }
     }
@@ -106,7 +104,7 @@ public:
           parent{info.hash()},
           bucket{parent},
           is_data{} {
-        auto &&elem = owner();
+        auto &&elem = internal::meta_context::from(*ctx).value[parent];
 
         if(!elem.details) {
             elem.details = std::make_shared<internal::meta_type_descriptor>();
@@ -294,6 +292,17 @@ public:
         return *this;
     }
 
+    /**
+     * @brief Seeks an arbitrary meta data in a meta type.
+     * @param id Unique identifier.
+     * @return A meta factory for the parent type.
+     */
+    auto data(const id_type id) noexcept {
+        constexpr auto is_data = true;
+        this->seek(id, is_data);
+        return *this;
+    }
+
     /**
      * @brief Assigns a meta data to a meta type.
      *
@@ -423,6 +432,17 @@ public:
         return *this;
     }
 
+    /**
+     * @brief Seeks an arbitrary meta function in a meta type.
+     * @param id Unique identifier.
+     * @return A meta factory for the parent type.
+     */
+    auto func(const id_type id) noexcept {
+        constexpr auto is_data = false;
+        this->seek(id, is_data);
+        return *this;
+    }
+
     /**
      * @brief Assigns a meta function to a meta type.
      *

+ 15 - 0
test/entt/meta/meta_data.cpp

@@ -640,6 +640,21 @@ TEST_F(MetaData, SetGetFromBase) {
     ASSERT_EQ(instance.value, 1);
 }
 
+TEST_F(MetaData, Seek) {
+    using namespace entt::literals;
+
+    auto data = entt::resolve<clazz>().data("i"_hs);
+
+    ASSERT_TRUE(data);
+    ASSERT_FALSE(data.prop('c'));
+
+    entt::meta<clazz>()
+        .data("i"_hs)
+        .prop('c');
+
+    ASSERT_TRUE(data.prop('c'));
+}
+
 TEST_F(MetaData, ReRegistration) {
     using namespace entt::literals;
 

+ 15 - 0
test/entt/meta/meta_func.cpp

@@ -605,6 +605,21 @@ TEST_F(MetaFunc, ExternalMemberFunction) {
     ASSERT_TRUE(registry.all_of<function>(entity));
 }
 
+TEST_F(MetaFunc, Seek) {
+    using namespace entt::literals;
+
+    auto func = entt::resolve<function>().func("f2"_hs);
+
+    ASSERT_TRUE(func);
+    ASSERT_FALSE(func.prop('c'));
+
+    entt::meta<function>()
+        .func("f2"_hs)
+        .prop('c');
+
+    ASSERT_TRUE(func.prop('c'));
+}
+
 TEST_F(MetaFunc, ReRegistration) {
     using namespace entt::literals;