Преглед изворни кода

Implement typed dictionaries

Thaddeus Crews пре 2 година
родитељ
комит
2ffff669f5

+ 72 - 0
binding_generator.py

@@ -672,6 +672,8 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
         for include in fully_used_classes:
             if include == "TypedArray":
                 includes.append("godot_cpp/variant/typed_array.hpp")
+            elif include == "TypedDictionary":
+                includes.append("godot_cpp/variant/typed_dictionary.hpp")
             else:
                 includes.append(f"godot_cpp/{get_include_path(include)}")
 
@@ -1022,6 +1024,9 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
     if class_name == "Dictionary":
         result.append("\tconst Variant &operator[](const Variant &p_key) const;")
         result.append("\tVariant &operator[](const Variant &p_key);")
+        result.append(
+            "\tvoid set_typed(uint32_t p_key_type, const StringName &p_key_class_name, const Variant &p_key_script, uint32_t p_value_type, const StringName &p_value_class_name, const Variant &p_value_script);"
+        )
 
     result.append("};")
 
@@ -1438,6 +1443,32 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
                                         fully_used_classes.add(array_type_name)
                                     else:
                                         used_classes.add(array_type_name)
+                            elif type_name.startswith("typeddictionary::"):
+                                fully_used_classes.add("TypedDictionary")
+                                dict_type_name = type_name.replace("typeddictionary::", "")
+                                if dict_type_name.startswith("const "):
+                                    dict_type_name = dict_type_name[6:]
+                                dict_type_names = dict_type_name.split(";")
+                                dict_type_name = dict_type_names[0]
+                                if dict_type_name.endswith("*"):
+                                    dict_type_name = dict_type_name[:-1]
+                                if is_included(dict_type_name, class_name):
+                                    if is_enum(dict_type_name):
+                                        fully_used_classes.add(get_enum_class(dict_type_name))
+                                    elif "default_value" in argument:
+                                        fully_used_classes.add(dict_type_name)
+                                    else:
+                                        used_classes.add(dict_type_name)
+                                dict_type_name = dict_type_names[2]
+                                if dict_type_name.endswith("*"):
+                                    dict_type_name = dict_type_name[:-1]
+                                if is_included(dict_type_name, class_name):
+                                    if is_enum(dict_type_name):
+                                        fully_used_classes.add(get_enum_class(dict_type_name))
+                                    elif "default_value" in argument:
+                                        fully_used_classes.add(dict_type_name)
+                                    else:
+                                        used_classes.add(dict_type_name)
                             elif is_enum(type_name):
                                 fully_used_classes.add(get_enum_class(type_name))
                             elif "default_value" in argument:
@@ -1467,6 +1498,32 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
                                     fully_used_classes.add(array_type_name)
                                 else:
                                     used_classes.add(array_type_name)
+                        elif type_name.startswith("typeddictionary::"):
+                            fully_used_classes.add("TypedDictionary")
+                            dict_type_name = type_name.replace("typeddictionary::", "")
+                            if dict_type_name.startswith("const "):
+                                dict_type_name = dict_type_name[6:]
+                            dict_type_names = dict_type_name.split(";")
+                            dict_type_name = dict_type_names[0]
+                            if dict_type_name.endswith("*"):
+                                dict_type_name = dict_type_name[:-1]
+                            if is_included(dict_type_name, class_name):
+                                if is_enum(dict_type_name):
+                                    fully_used_classes.add(get_enum_class(dict_type_name))
+                                elif is_variant(dict_type_name):
+                                    fully_used_classes.add(dict_type_name)
+                                else:
+                                    used_classes.add(dict_type_name)
+                            dict_type_name = dict_type_names[2]
+                            if dict_type_name.endswith("*"):
+                                dict_type_name = dict_type_name[:-1]
+                            if is_included(dict_type_name, class_name):
+                                if is_enum(dict_type_name):
+                                    fully_used_classes.add(get_enum_class(dict_type_name))
+                                elif is_variant(dict_type_name):
+                                    fully_used_classes.add(dict_type_name)
+                                else:
+                                    used_classes.add(dict_type_name)
                         elif is_enum(type_name):
                             fully_used_classes.add(get_enum_class(type_name))
                         elif is_variant(type_name):
@@ -1600,6 +1657,8 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
         for included in fully_used_classes:
             if included == "TypedArray":
                 includes.append("godot_cpp/variant/typed_array.hpp")
+            elif included == "TypedDictionary":
+                includes.append("godot_cpp/variant/typed_dictionary.hpp")
             else:
                 includes.append(f"godot_cpp/{get_include_path(included)}")
 
@@ -2688,6 +2747,7 @@ def is_variant(type_name):
         or type_name in builtin_classes
         or type_name == "Nil"
         or type_name.startswith("typedarray::")
+        or type_name.startswith("typeddictionary::")
     )
 
 
@@ -2727,6 +2787,8 @@ def is_included(type_name, current_type):
     """
     if type_name.startswith("typedarray::"):
         return True
+    if type_name.startswith("typeddictionary::"):
+        return True
     to_include = get_enum_class(type_name) if is_enum(type_name) else type_name
     if to_include == current_type or is_pod_type(to_include):
         return False
@@ -2765,6 +2827,12 @@ def correct_typed_array(type_name):
     return type_name
 
 
+def correct_typed_dictionary(type_name):
+    if type_name.startswith("typeddictionary::"):
+        return type_name.replace("typeddictionary::", "TypedDictionary<").replace(";", ", ") + ">"
+    return type_name
+
+
 def correct_type(type_name, meta=None, use_alias=True):
     type_conversion = {"float": "double", "int": "int64_t", "Nil": "Variant"}
     if meta is not None:
@@ -2778,6 +2846,8 @@ def correct_type(type_name, meta=None, use_alias=True):
         return type_conversion[type_name]
     if type_name.startswith("typedarray::"):
         return type_name.replace("typedarray::", "TypedArray<") + ">"
+    if type_name.startswith("typeddictionary::"):
+        return type_name.replace("typeddictionary::", "TypedDictionary<").replace(";", ", ") + ">"
     if is_enum(type_name):
         if is_bitfield(type_name):
             base_class = get_enum_class(type_name)
@@ -2924,6 +2994,8 @@ def get_default_value_for_type(type_name):
         return "false"
     if type_name.startswith("typedarray::"):
         return f"{correct_type(type_name)}()"
+    if type_name.startswith("typeddictionary::"):
+        return f"{correct_type(type_name)}()"
     if is_enum(type_name):
         return f"{correct_type(type_name)}(0)"
     if is_variant(type_name):

+ 201 - 0
include/godot_cpp/core/type_info.hpp

@@ -33,6 +33,7 @@
 
 #include <godot_cpp/core/object.hpp>
 #include <godot_cpp/variant/typed_array.hpp>
+#include <godot_cpp/variant/typed_dictionary.hpp>
 #include <godot_cpp/variant/variant.hpp>
 
 #include <gdextension_interface.h>
@@ -413,6 +414,206 @@ MAKE_TYPED_ARRAY_INFO(IPAddress, Variant::STRING)
 
 #undef MAKE_TYPED_ARRAY_INFO
 
+template <typename K, typename V>
+struct PtrToArg<TypedDictionary<K, V>> {
+	_FORCE_INLINE_ static TypedDictionary<K, V> convert(const void *p_ptr) {
+		return TypedDictionary<K, V>(*reinterpret_cast<const Dictionary *>(p_ptr));
+	}
+	typedef Dictionary EncodeT;
+	_FORCE_INLINE_ static void encode(TypedDictionary<K, V> p_val, void *p_ptr) {
+		*(Dictionary *)p_ptr = p_val;
+	}
+};
+
+template <typename K, typename V>
+struct PtrToArg<const TypedDictionary<K, V> &> {
+	typedef Dictionary EncodeT;
+	_FORCE_INLINE_ static TypedDictionary<K, V>
+	convert(const void *p_ptr) {
+		return TypedDictionary<K, V>(*reinterpret_cast<const Dictionary *>(p_ptr));
+	}
+};
+
+template <typename K, typename V>
+struct GetTypeInfo<TypedDictionary<K, V>> {
+	static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY;
+	static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
+	static inline PropertyInfo get_class_info() {
+		return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, vformat("%s;%s", K::get_class_static(), V::get_class_static()));
+	}
+};
+
+template <typename K, typename V>
+struct GetTypeInfo<const TypedDictionary<K, V> &> {
+	static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY;
+	static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
+	static inline PropertyInfo get_class_info() {
+		return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, vformat("%s;%s", K::get_class_static(), V::get_class_static()));
+	}
+};
+
+#define MAKE_TYPED_DICTIONARY_INFO_WITH_OBJECT(m_type, m_variant_type)                                                                                                     \
+	template <typename T>                                                                                                                                                  \
+	struct GetTypeInfo<TypedDictionary<T, m_type>> {                                                                                                                       \
+		static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY;                                                                        \
+		static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;                                                      \
+		static inline PropertyInfo get_class_info() {                                                                                                                      \
+			return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE,                                                                        \
+					vformat("%s;%s", T::get_class_static(), m_variant_type == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type).utf8().get_data())); \
+		}                                                                                                                                                                  \
+	};                                                                                                                                                                     \
+	template <typename T>                                                                                                                                                  \
+	struct GetTypeInfo<const TypedDictionary<T, m_type> &> {                                                                                                               \
+		static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY;                                                                        \
+		static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;                                                      \
+		static inline PropertyInfo get_class_info() {                                                                                                                      \
+			return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE,                                                                        \
+					vformat("%s;%s", T::get_class_static(), m_variant_type == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type).utf8().get_data())); \
+		}                                                                                                                                                                  \
+	};                                                                                                                                                                     \
+	template <typename T>                                                                                                                                                  \
+	struct GetTypeInfo<TypedDictionary<m_type, T>> {                                                                                                                       \
+		static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY;                                                                        \
+		static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;                                                      \
+		static inline PropertyInfo get_class_info() {                                                                                                                      \
+			return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE,                                                                        \
+					vformat("%s;%s", m_variant_type == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type).utf8().get_data(), T::get_class_static())); \
+		}                                                                                                                                                                  \
+	};                                                                                                                                                                     \
+	template <typename T>                                                                                                                                                  \
+	struct GetTypeInfo<const TypedDictionary<m_type, T> &> {                                                                                                               \
+		static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY;                                                                        \
+		static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;                                                      \
+		static inline PropertyInfo get_class_info() {                                                                                                                      \
+			return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE,                                                                        \
+					vformat("%s;%s", m_variant_type == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type).utf8().get_data(), T::get_class_static())); \
+		}                                                                                                                                                                  \
+	};
+
+#define MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type_key, m_variant_type_key, m_type_value, m_variant_type_value)                                           \
+	template <>                                                                                                                                           \
+	struct GetTypeInfo<TypedDictionary<m_type_key, m_type_value>> {                                                                                       \
+		static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY;                                                       \
+		static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;                                     \
+		static inline PropertyInfo get_class_info() {                                                                                                     \
+			return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE,                                                       \
+					vformat("%s;%s", m_variant_type_key == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type_key).utf8().get_data(), \
+							m_variant_type_value == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type_value).utf8().get_data()));    \
+		}                                                                                                                                                 \
+	};                                                                                                                                                    \
+	template <>                                                                                                                                           \
+	struct GetTypeInfo<const TypedDictionary<m_type_key, m_type_value> &> {                                                                               \
+		static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY;                                                       \
+		static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;                                     \
+		static inline PropertyInfo get_class_info() {                                                                                                     \
+			return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE,                                                       \
+					vformat("%s;%s", m_variant_type_key == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type_key).utf8().get_data(), \
+							m_variant_type_value == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type_value).utf8().get_data()));    \
+		}                                                                                                                                                 \
+	};
+
+#define MAKE_TYPED_DICTIONARY_INFO_NIL(m_type, m_variant_type)                                                     \
+	MAKE_TYPED_DICTIONARY_INFO_WITH_OBJECT(m_type, m_variant_type)                                                 \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, bool, Variant::BOOL)                               \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, uint8_t, Variant::INT)                             \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, int8_t, Variant::INT)                              \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, uint16_t, Variant::INT)                            \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, int16_t, Variant::INT)                             \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, uint32_t, Variant::INT)                            \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, int32_t, Variant::INT)                             \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, uint64_t, Variant::INT)                            \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, int64_t, Variant::INT)                             \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, float, Variant::FLOAT)                             \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, double, Variant::FLOAT)                            \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, String, Variant::STRING)                           \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Vector2, Variant::VECTOR2)                         \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Vector2i, Variant::VECTOR2I)                       \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Rect2, Variant::RECT2)                             \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Rect2i, Variant::RECT2I)                           \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Vector3, Variant::VECTOR3)                         \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Vector3i, Variant::VECTOR3I)                       \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Transform2D, Variant::TRANSFORM2D)                 \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Plane, Variant::PLANE)                             \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Quaternion, Variant::QUATERNION)                   \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, AABB, Variant::AABB)                               \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Basis, Variant::BASIS)                             \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Transform3D, Variant::TRANSFORM3D)                 \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Color, Variant::COLOR)                             \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, StringName, Variant::STRING_NAME)                  \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, NodePath, Variant::NODE_PATH)                      \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, RID, Variant::RID)                                 \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Callable, Variant::CALLABLE)                       \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Signal, Variant::SIGNAL)                           \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Dictionary, Variant::DICTIONARY)                   \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Array, Variant::ARRAY)                             \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedByteArray, Variant::PACKED_BYTE_ARRAY)       \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedInt32Array, Variant::PACKED_INT32_ARRAY)     \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedInt64Array, Variant::PACKED_INT64_ARRAY)     \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY) \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY) \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedStringArray, Variant::PACKED_STRING_ARRAY)   \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY) \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY) \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY) \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedColorArray, Variant::PACKED_COLOR_ARRAY)     \
+	/* MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, IPAddress, Variant::STRING) */
+
+#define MAKE_TYPED_DICTIONARY_INFO(m_type, m_variant_type)                             \
+	MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Variant, Variant::NIL) \
+	MAKE_TYPED_DICTIONARY_INFO_NIL(m_type, m_variant_type)
+
+MAKE_TYPED_DICTIONARY_INFO_NIL(Variant, Variant::NIL)
+MAKE_TYPED_DICTIONARY_INFO(bool, Variant::BOOL)
+MAKE_TYPED_DICTIONARY_INFO(uint8_t, Variant::INT)
+MAKE_TYPED_DICTIONARY_INFO(int8_t, Variant::INT)
+MAKE_TYPED_DICTIONARY_INFO(uint16_t, Variant::INT)
+MAKE_TYPED_DICTIONARY_INFO(int16_t, Variant::INT)
+MAKE_TYPED_DICTIONARY_INFO(uint32_t, Variant::INT)
+MAKE_TYPED_DICTIONARY_INFO(int32_t, Variant::INT)
+MAKE_TYPED_DICTIONARY_INFO(uint64_t, Variant::INT)
+MAKE_TYPED_DICTIONARY_INFO(int64_t, Variant::INT)
+MAKE_TYPED_DICTIONARY_INFO(float, Variant::FLOAT)
+MAKE_TYPED_DICTIONARY_INFO(double, Variant::FLOAT)
+MAKE_TYPED_DICTIONARY_INFO(String, Variant::STRING)
+MAKE_TYPED_DICTIONARY_INFO(Vector2, Variant::VECTOR2)
+MAKE_TYPED_DICTIONARY_INFO(Vector2i, Variant::VECTOR2I)
+MAKE_TYPED_DICTIONARY_INFO(Rect2, Variant::RECT2)
+MAKE_TYPED_DICTIONARY_INFO(Rect2i, Variant::RECT2I)
+MAKE_TYPED_DICTIONARY_INFO(Vector3, Variant::VECTOR3)
+MAKE_TYPED_DICTIONARY_INFO(Vector3i, Variant::VECTOR3I)
+MAKE_TYPED_DICTIONARY_INFO(Transform2D, Variant::TRANSFORM2D)
+MAKE_TYPED_DICTIONARY_INFO(Plane, Variant::PLANE)
+MAKE_TYPED_DICTIONARY_INFO(Quaternion, Variant::QUATERNION)
+MAKE_TYPED_DICTIONARY_INFO(AABB, Variant::AABB)
+MAKE_TYPED_DICTIONARY_INFO(Basis, Variant::BASIS)
+MAKE_TYPED_DICTIONARY_INFO(Transform3D, Variant::TRANSFORM3D)
+MAKE_TYPED_DICTIONARY_INFO(Color, Variant::COLOR)
+MAKE_TYPED_DICTIONARY_INFO(StringName, Variant::STRING_NAME)
+MAKE_TYPED_DICTIONARY_INFO(NodePath, Variant::NODE_PATH)
+MAKE_TYPED_DICTIONARY_INFO(RID, Variant::RID)
+MAKE_TYPED_DICTIONARY_INFO(Callable, Variant::CALLABLE)
+MAKE_TYPED_DICTIONARY_INFO(Signal, Variant::SIGNAL)
+MAKE_TYPED_DICTIONARY_INFO(Dictionary, Variant::DICTIONARY)
+MAKE_TYPED_DICTIONARY_INFO(Array, Variant::ARRAY)
+MAKE_TYPED_DICTIONARY_INFO(PackedByteArray, Variant::PACKED_BYTE_ARRAY)
+MAKE_TYPED_DICTIONARY_INFO(PackedInt32Array, Variant::PACKED_INT32_ARRAY)
+MAKE_TYPED_DICTIONARY_INFO(PackedInt64Array, Variant::PACKED_INT64_ARRAY)
+MAKE_TYPED_DICTIONARY_INFO(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY)
+MAKE_TYPED_DICTIONARY_INFO(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
+MAKE_TYPED_DICTIONARY_INFO(PackedStringArray, Variant::PACKED_STRING_ARRAY)
+MAKE_TYPED_DICTIONARY_INFO(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
+MAKE_TYPED_DICTIONARY_INFO(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
+MAKE_TYPED_DICTIONARY_INFO(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY)
+MAKE_TYPED_DICTIONARY_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
+/*
+MAKE_TYPED_DICTIONARY_INFO(IPAddress, Variant::STRING)
+*/
+
+#undef MAKE_TYPED_DICTIONARY_INFO
+#undef MAKE_TYPED_DICTIONARY_INFO_NIL
+#undef MAKE_TYPED_DICTIONARY_INFO_EXPANDED
+#undef MAKE_TYPED_DICTIONARY_INFO_WITH_OBJECT
+
 #define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
 
 } // namespace godot

+ 1 - 0
include/godot_cpp/godot.hpp

@@ -158,6 +158,7 @@ extern "C" GDExtensionInterfaceArrayRef gdextension_interface_array_ref;
 extern "C" GDExtensionInterfaceArraySetTyped gdextension_interface_array_set_typed;
 extern "C" GDExtensionInterfaceDictionaryOperatorIndex gdextension_interface_dictionary_operator_index;
 extern "C" GDExtensionInterfaceDictionaryOperatorIndexConst gdextension_interface_dictionary_operator_index_const;
+extern "C" GDExtensionInterfaceDictionarySetTyped gdextension_interface_dictionary_set_typed;
 extern "C" GDExtensionInterfaceObjectMethodBindCall gdextension_interface_object_method_bind_call;
 extern "C" GDExtensionInterfaceObjectMethodBindPtrcall gdextension_interface_object_method_bind_ptrcall;
 extern "C" GDExtensionInterfaceObjectDestroy gdextension_interface_object_destroy;

+ 238 - 0
include/godot_cpp/variant/typed_dictionary.hpp

@@ -0,0 +1,238 @@
+/**************************************************************************/
+/*  typed_dictionary.hpp                                                  */
+/**************************************************************************/
+/*                         This file is part of:                          */
+/*                             GODOT ENGINE                               */
+/*                        https://godotengine.org                         */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */
+/*                                                                        */
+/* Permission is hereby granted, free of charge, to any person obtaining  */
+/* a copy of this software and associated documentation files (the        */
+/* "Software"), to deal in the Software without restriction, including    */
+/* without limitation the rights to use, copy, modify, merge, publish,    */
+/* distribute, sublicense, and/or sell copies of the Software, and to     */
+/* permit persons to whom the Software is furnished to do so, subject to  */
+/* the following conditions:                                              */
+/*                                                                        */
+/* The above copyright notice and this permission notice shall be         */
+/* included in all copies or substantial portions of the Software.        */
+/*                                                                        */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
+/**************************************************************************/
+
+#ifndef GODOT_TYPED_DICTIONARY_HPP
+#define GODOT_TYPED_DICTIONARY_HPP
+
+#include <godot_cpp/variant/dictionary.hpp>
+#include <godot_cpp/variant/variant.hpp>
+
+namespace godot {
+
+template <typename K, typename V>
+class TypedDictionary : public Dictionary {
+public:
+	_FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) {
+		ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign a dictionary with a different element type.");
+		Dictionary::operator=(p_dictionary);
+	}
+	_FORCE_INLINE_ TypedDictionary(const Variant &p_variant) :
+			TypedDictionary(Dictionary(p_variant)) {
+	}
+	_FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) {
+		set_typed(Variant::OBJECT, K::get_class_static(), Variant(), Variant::OBJECT, V::get_class_static(), Variant());
+		if (is_same_typed(p_dictionary)) {
+			Dictionary::operator=(p_dictionary);
+		} else {
+			assign(p_dictionary);
+		}
+	}
+	_FORCE_INLINE_ TypedDictionary() {
+		set_typed(Variant::OBJECT, K::get_class_static(), Variant(), Variant::OBJECT, V::get_class_static(), Variant());
+	}
+};
+
+//specialization for the rest of variant types
+
+#define MAKE_TYPED_DICTIONARY_WITH_OBJECT(m_type, m_variant_type)                                                          \
+	template <typename T>                                                                                                  \
+	class TypedDictionary<T, m_type> : public Dictionary {                                                                 \
+	public:                                                                                                                \
+		_FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) {                                                    \
+			ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign an dictionary with a different element type."); \
+			Dictionary::operator=(p_dictionary);                                                                           \
+		}                                                                                                                  \
+		_FORCE_INLINE_ TypedDictionary(const Variant &p_variant) :                                                         \
+				TypedDictionary(Dictionary(p_variant)) {                                                                   \
+		}                                                                                                                  \
+		_FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) {                                                   \
+			set_typed(Variant::OBJECT, T::get_class_static(), Variant(), m_variant_type, StringName(), Variant());         \
+			if (is_same_typed(p_dictionary)) {                                                                             \
+				Dictionary::operator=(p_dictionary);                                                                       \
+			} else {                                                                                                       \
+				assign(p_dictionary);                                                                                      \
+			}                                                                                                              \
+		}                                                                                                                  \
+		_FORCE_INLINE_ TypedDictionary() {                                                                                 \
+			set_typed(Variant::OBJECT, T::get_class_static(), Variant(), m_variant_type, StringName(), Variant());         \
+		}                                                                                                                  \
+	};                                                                                                                     \
+	template <typename T>                                                                                                  \
+	class TypedDictionary<m_type, T> : public Dictionary {                                                                 \
+	public:                                                                                                                \
+		_FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) {                                                    \
+			ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign an dictionary with a different element type."); \
+			Dictionary::operator=(p_dictionary);                                                                           \
+		}                                                                                                                  \
+		_FORCE_INLINE_ TypedDictionary(const Variant &p_variant) :                                                         \
+				TypedDictionary(Dictionary(p_variant)) {                                                                   \
+		}                                                                                                                  \
+		_FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) {                                                   \
+			set_typed(m_variant_type, StringName(), Variant(), Variant::OBJECT, T::get_class_static(), Variant());         \
+			if (is_same_typed(p_dictionary)) {                                                                             \
+				Dictionary::operator=(p_dictionary);                                                                       \
+			} else {                                                                                                       \
+				assign(p_dictionary);                                                                                      \
+			}                                                                                                              \
+		}                                                                                                                  \
+		_FORCE_INLINE_ TypedDictionary() {                                                                                 \
+			set_typed(m_variant_type, StringName(), Variant(), Variant::OBJECT, T::get_class_static(), Variant());         \
+		}                                                                                                                  \
+	};
+
+#define MAKE_TYPED_DICTIONARY_EXPANDED(m_type_key, m_variant_type_key, m_type_value, m_variant_type_value)                 \
+	template <>                                                                                                            \
+	class TypedDictionary<m_type_key, m_type_value> : public Dictionary {                                                  \
+	public:                                                                                                                \
+		_FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) {                                                    \
+			ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign an dictionary with a different element type."); \
+			Dictionary::operator=(p_dictionary);                                                                           \
+		}                                                                                                                  \
+		_FORCE_INLINE_ TypedDictionary(const Variant &p_variant) :                                                         \
+				TypedDictionary(Dictionary(p_variant)) {                                                                   \
+		}                                                                                                                  \
+		_FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) {                                                   \
+			set_typed(m_variant_type_key, StringName(), Variant(), m_variant_type_value, StringName(), Variant());         \
+			if (is_same_typed(p_dictionary)) {                                                                             \
+				Dictionary::operator=(p_dictionary);                                                                       \
+			} else {                                                                                                       \
+				assign(p_dictionary);                                                                                      \
+			}                                                                                                              \
+		}                                                                                                                  \
+		_FORCE_INLINE_ TypedDictionary() {                                                                                 \
+			set_typed(m_variant_type_key, StringName(), Variant(), m_variant_type_value, StringName(), Variant());         \
+		}                                                                                                                  \
+	};
+
+#define MAKE_TYPED_DICTIONARY_NIL(m_type, m_variant_type)                                                     \
+	MAKE_TYPED_DICTIONARY_WITH_OBJECT(m_type, m_variant_type)                                                 \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, bool, Variant::BOOL)                               \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, uint8_t, Variant::INT)                             \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, int8_t, Variant::INT)                              \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, uint16_t, Variant::INT)                            \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, int16_t, Variant::INT)                             \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, uint32_t, Variant::INT)                            \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, int32_t, Variant::INT)                             \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, uint64_t, Variant::INT)                            \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, int64_t, Variant::INT)                             \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, float, Variant::FLOAT)                             \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, double, Variant::FLOAT)                            \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, String, Variant::STRING)                           \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Vector2, Variant::VECTOR2)                         \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Vector2i, Variant::VECTOR2I)                       \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Rect2, Variant::RECT2)                             \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Rect2i, Variant::RECT2I)                           \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Vector3, Variant::VECTOR3)                         \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Vector3i, Variant::VECTOR3I)                       \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Transform2D, Variant::TRANSFORM2D)                 \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Plane, Variant::PLANE)                             \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Quaternion, Variant::QUATERNION)                   \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, AABB, Variant::AABB)                               \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Basis, Variant::BASIS)                             \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Transform3D, Variant::TRANSFORM3D)                 \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Color, Variant::COLOR)                             \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, StringName, Variant::STRING_NAME)                  \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, NodePath, Variant::NODE_PATH)                      \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, RID, Variant::RID)                                 \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Callable, Variant::CALLABLE)                       \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Signal, Variant::SIGNAL)                           \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Dictionary, Variant::DICTIONARY)                   \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Array, Variant::ARRAY)                             \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedByteArray, Variant::PACKED_BYTE_ARRAY)       \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedInt32Array, Variant::PACKED_INT32_ARRAY)     \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedInt64Array, Variant::PACKED_INT64_ARRAY)     \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY) \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY) \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedStringArray, Variant::PACKED_STRING_ARRAY)   \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY) \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY) \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedColorArray, Variant::PACKED_COLOR_ARRAY)     \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY) \
+	/*MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, IPAddress, Variant::STRING)*/
+
+#define MAKE_TYPED_DICTIONARY(m_type, m_variant_type)                             \
+	MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Variant, Variant::NIL) \
+	MAKE_TYPED_DICTIONARY_NIL(m_type, m_variant_type)
+
+MAKE_TYPED_DICTIONARY_NIL(Variant, Variant::NIL)
+MAKE_TYPED_DICTIONARY(bool, Variant::BOOL)
+MAKE_TYPED_DICTIONARY(uint8_t, Variant::INT)
+MAKE_TYPED_DICTIONARY(int8_t, Variant::INT)
+MAKE_TYPED_DICTIONARY(uint16_t, Variant::INT)
+MAKE_TYPED_DICTIONARY(int16_t, Variant::INT)
+MAKE_TYPED_DICTIONARY(uint32_t, Variant::INT)
+MAKE_TYPED_DICTIONARY(int32_t, Variant::INT)
+MAKE_TYPED_DICTIONARY(uint64_t, Variant::INT)
+MAKE_TYPED_DICTIONARY(int64_t, Variant::INT)
+MAKE_TYPED_DICTIONARY(float, Variant::FLOAT)
+MAKE_TYPED_DICTIONARY(double, Variant::FLOAT)
+MAKE_TYPED_DICTIONARY(String, Variant::STRING)
+MAKE_TYPED_DICTIONARY(Vector2, Variant::VECTOR2)
+MAKE_TYPED_DICTIONARY(Vector2i, Variant::VECTOR2I)
+MAKE_TYPED_DICTIONARY(Rect2, Variant::RECT2)
+MAKE_TYPED_DICTIONARY(Rect2i, Variant::RECT2I)
+MAKE_TYPED_DICTIONARY(Vector3, Variant::VECTOR3)
+MAKE_TYPED_DICTIONARY(Vector3i, Variant::VECTOR3I)
+MAKE_TYPED_DICTIONARY(Transform2D, Variant::TRANSFORM2D)
+MAKE_TYPED_DICTIONARY(Plane, Variant::PLANE)
+MAKE_TYPED_DICTIONARY(Quaternion, Variant::QUATERNION)
+MAKE_TYPED_DICTIONARY(AABB, Variant::AABB)
+MAKE_TYPED_DICTIONARY(Basis, Variant::BASIS)
+MAKE_TYPED_DICTIONARY(Transform3D, Variant::TRANSFORM3D)
+MAKE_TYPED_DICTIONARY(Color, Variant::COLOR)
+MAKE_TYPED_DICTIONARY(StringName, Variant::STRING_NAME)
+MAKE_TYPED_DICTIONARY(NodePath, Variant::NODE_PATH)
+MAKE_TYPED_DICTIONARY(RID, Variant::RID)
+MAKE_TYPED_DICTIONARY(Callable, Variant::CALLABLE)
+MAKE_TYPED_DICTIONARY(Signal, Variant::SIGNAL)
+MAKE_TYPED_DICTIONARY(Dictionary, Variant::DICTIONARY)
+MAKE_TYPED_DICTIONARY(Array, Variant::ARRAY)
+MAKE_TYPED_DICTIONARY(PackedByteArray, Variant::PACKED_BYTE_ARRAY)
+MAKE_TYPED_DICTIONARY(PackedInt32Array, Variant::PACKED_INT32_ARRAY)
+MAKE_TYPED_DICTIONARY(PackedInt64Array, Variant::PACKED_INT64_ARRAY)
+MAKE_TYPED_DICTIONARY(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY)
+MAKE_TYPED_DICTIONARY(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
+MAKE_TYPED_DICTIONARY(PackedStringArray, Variant::PACKED_STRING_ARRAY)
+MAKE_TYPED_DICTIONARY(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
+MAKE_TYPED_DICTIONARY(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
+MAKE_TYPED_DICTIONARY(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
+MAKE_TYPED_DICTIONARY(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY)
+/*
+MAKE_TYPED_DICTIONARY(IPAddress, Variant::STRING)
+*/
+
+#undef MAKE_TYPED_DICTIONARY
+#undef MAKE_TYPED_DICTIONARY_NIL
+#undef MAKE_TYPED_DICTIONARY_EXPANDED
+#undef MAKE_TYPED_DICTIONARY_WITH_OBJECT
+
+} // namespace godot
+
+#endif // GODOT_TYPED_DICTIONARY_HPP

+ 2 - 0
src/godot.cpp

@@ -164,6 +164,7 @@ GDExtensionInterfaceArrayRef gdextension_interface_array_ref = nullptr;
 GDExtensionInterfaceArraySetTyped gdextension_interface_array_set_typed = nullptr;
 GDExtensionInterfaceDictionaryOperatorIndex gdextension_interface_dictionary_operator_index = nullptr;
 GDExtensionInterfaceDictionaryOperatorIndexConst gdextension_interface_dictionary_operator_index_const = nullptr;
+GDExtensionInterfaceDictionarySetTyped gdextension_interface_dictionary_set_typed = nullptr;
 GDExtensionInterfaceObjectMethodBindCall gdextension_interface_object_method_bind_call = nullptr;
 GDExtensionInterfaceObjectMethodBindPtrcall gdextension_interface_object_method_bind_ptrcall = nullptr;
 GDExtensionInterfaceObjectDestroy gdextension_interface_object_destroy = nullptr;
@@ -443,6 +444,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
 	LOAD_PROC_ADDRESS(array_set_typed, GDExtensionInterfaceArraySetTyped);
 	LOAD_PROC_ADDRESS(dictionary_operator_index, GDExtensionInterfaceDictionaryOperatorIndex);
 	LOAD_PROC_ADDRESS(dictionary_operator_index_const, GDExtensionInterfaceDictionaryOperatorIndexConst);
+	LOAD_PROC_ADDRESS(dictionary_set_typed, GDExtensionInterfaceDictionarySetTyped);
 	LOAD_PROC_ADDRESS(object_method_bind_call, GDExtensionInterfaceObjectMethodBindCall);
 	LOAD_PROC_ADDRESS(object_method_bind_ptrcall, GDExtensionInterfaceObjectMethodBindPtrcall);
 	LOAD_PROC_ADDRESS(object_destroy, GDExtensionInterfaceObjectDestroy);

+ 6 - 0
src/variant/packed_arrays.cpp

@@ -246,4 +246,10 @@ Variant &Dictionary::operator[](const Variant &p_key) {
 	return *var;
 }
 
+void Dictionary::set_typed(uint32_t p_key_type, const StringName &p_key_class_name, const Variant &p_key_script, uint32_t p_value_type, const StringName &p_value_class_name, const Variant &p_value_script) {
+	// p_key_type/p_value_type are not Variant::Type so that header doesn't depend on <variant.hpp>.
+	internal::gdextension_interface_dictionary_set_typed((GDExtensionTypePtr *)this, (GDExtensionVariantType)p_key_type, (GDExtensionConstStringNamePtr)&p_key_class_name, (GDExtensionConstVariantPtr)&p_key_script,
+			(GDExtensionVariantType)p_value_type, (GDExtensionConstStringNamePtr)&p_value_class_name, (GDExtensionConstVariantPtr)&p_value_script);
+}
+
 } // namespace godot

+ 5 - 2
test/project/main.gd

@@ -81,10 +81,13 @@ func _ready():
 
 	# Array and Dictionary
 	assert_equal(example.test_array(), [1, 2])
-	assert_equal(example.test_tarray(), [ Vector2(1, 2), Vector2(2, 3) ])
-	assert_equal(example.test_dictionary(), {"hello": "world", "foo": "bar"})
+	assert_equal(example.test_tarray(), [Vector2(1, 2), Vector2(2, 3)])
 	var array: Array[int] = [1, 2, 3]
 	assert_equal(example.test_tarray_arg(array), 6)
+	assert_equal(example.test_dictionary(), { "hello": "world", "foo": "bar" })
+	assert_equal(example.test_tdictionary(), { Vector2(1, 2): Vector2i(2, 3) })
+	var dictionary: Dictionary[String, int] = { "1": 1, "2": 2, "3": 3 }
+	assert_equal(example.test_tdictionary_arg(dictionary), 6)
 
 	example.callable_bind()
 	assert_equal(custom_signal_emitted, ["bound", 11])

+ 19 - 0
test/src/example.cpp

@@ -199,6 +199,8 @@ void Example::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("test_tarray_arg", "array"), &Example::test_tarray_arg);
 	ClassDB::bind_method(D_METHOD("test_tarray"), &Example::test_tarray);
 	ClassDB::bind_method(D_METHOD("test_dictionary"), &Example::test_dictionary);
+	ClassDB::bind_method(D_METHOD("test_tdictionary_arg", "dictionary"), &Example::test_tdictionary_arg);
+	ClassDB::bind_method(D_METHOD("test_tdictionary"), &Example::test_tdictionary);
 	ClassDB::bind_method(D_METHOD("test_node_argument"), &Example::test_node_argument);
 	ClassDB::bind_method(D_METHOD("test_string_ops"), &Example::test_string_ops);
 	ClassDB::bind_method(D_METHOD("test_str_utility"), &Example::test_str_utility);
@@ -551,6 +553,23 @@ Dictionary Example::test_dictionary() const {
 	return dict;
 }
 
+int Example::test_tdictionary_arg(const TypedDictionary<String, int64_t> &p_dictionary) {
+	int sum = 0;
+	TypedArray<int64_t> values = p_dictionary.values();
+	for (int i = 0; i < p_dictionary.size(); i++) {
+		sum += (int)values[i];
+	}
+	return sum;
+}
+
+TypedDictionary<Vector2, Vector2i> Example::test_tdictionary() const {
+	TypedDictionary<Vector2, Vector2i> dict;
+
+	dict[Vector2(1, 2)] = Vector2i(2, 3);
+
+	return dict;
+}
+
 Example *Example::test_node_argument(Example *p_node) const {
 	return p_node;
 }

+ 2 - 0
test/src/example.h

@@ -129,6 +129,8 @@ public:
 	int test_tarray_arg(const TypedArray<int64_t> &p_array);
 	TypedArray<Vector2> test_tarray() const;
 	Dictionary test_dictionary() const;
+	int test_tdictionary_arg(const TypedDictionary<String, int64_t> &p_dictionary);
+	TypedDictionary<Vector2, Vector2i> test_tdictionary() const;
 	Example *test_node_argument(Example *p_node) const;
 	String test_string_ops() const;
 	String test_str_utility() const;