Skip to content

Commit f5b340a

Browse files
committed
Implement typed dictionaries
1 parent bf2f9e2 commit f5b340a

File tree

10 files changed

+1954
-2
lines changed

10 files changed

+1954
-2
lines changed

binding_generator.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,8 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
421421
for include in fully_used_classes:
422422
if include == "TypedArray":
423423
result.append("#include <godot_cpp/variant/typed_array.hpp>")
424+
elif include == "TypedDictionary":
425+
result.append("#include <godot_cpp/variant/typed_dictionary.hpp>")
424426
else:
425427
result.append(f"#include <godot_cpp/{get_include_path(include)}>")
426428

@@ -743,6 +745,9 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
743745
if class_name == "Dictionary":
744746
result.append("\tconst Variant &operator[](const Variant &p_key) const;")
745747
result.append("\tVariant &operator[](const Variant &p_key);")
748+
result.append(
749+
"\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);"
750+
)
746751

747752
result.append("};")
748753

@@ -1126,6 +1131,32 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
11261131
fully_used_classes.add(array_type_name)
11271132
else:
11281133
used_classes.add(array_type_name)
1134+
elif type_name.startswith("typeddictionary::"):
1135+
fully_used_classes.add("TypedDictionary")
1136+
dict_type_name = type_name.replace("typeddictionary::", "")
1137+
if dict_type_name.startswith("const "):
1138+
dict_type_name = dict_type_name[6:]
1139+
dict_type_names = dict_type_name.split(",")
1140+
dict_type_name = dict_type_names[0]
1141+
if dict_type_name.endswith("*"):
1142+
dict_type_name = dict_type_name[:-1]
1143+
if is_included(dict_type_name, class_name):
1144+
if is_enum(dict_type_name):
1145+
fully_used_classes.add(get_enum_class(dict_type_name))
1146+
elif "default_value" in argument:
1147+
fully_used_classes.add(dict_type_name)
1148+
else:
1149+
used_classes.add(dict_type_name)
1150+
dict_type_name = dict_type_names[2]
1151+
if dict_type_name.endswith("*"):
1152+
dict_type_name = dict_type_name[:-1]
1153+
if is_included(dict_type_name, class_name):
1154+
if is_enum(dict_type_name):
1155+
fully_used_classes.add(get_enum_class(dict_type_name))
1156+
elif "default_value" in argument:
1157+
fully_used_classes.add(dict_type_name)
1158+
else:
1159+
used_classes.add(dict_type_name)
11291160
elif is_enum(type_name):
11301161
fully_used_classes.add(get_enum_class(type_name))
11311162
elif "default_value" in argument:
@@ -1155,6 +1186,32 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
11551186
fully_used_classes.add(array_type_name)
11561187
else:
11571188
used_classes.add(array_type_name)
1189+
elif type_name.startswith("typeddictionary::"):
1190+
fully_used_classes.add("TypedDictionary")
1191+
dict_type_name = type_name.replace("typeddictionary::", "")
1192+
if dict_type_name.startswith("const "):
1193+
dict_type_name = dict_type_name[6:]
1194+
dict_type_names = dict_type_name.split(",")
1195+
dict_type_name = dict_type_names[0]
1196+
if dict_type_name.endswith("*"):
1197+
dict_type_name = dict_type_name[:-1]
1198+
if is_included(dict_type_name, class_name):
1199+
if is_enum(dict_type_name):
1200+
fully_used_classes.add(get_enum_class(dict_type_name))
1201+
elif is_variant(dict_type_name):
1202+
fully_used_classes.add(dict_type_name)
1203+
else:
1204+
used_classes.add(dict_type_name)
1205+
dict_type_name = dict_type_names[2]
1206+
if dict_type_name.endswith("*"):
1207+
dict_type_name = dict_type_name[:-1]
1208+
if is_included(dict_type_name, class_name):
1209+
if is_enum(dict_type_name):
1210+
fully_used_classes.add(get_enum_class(dict_type_name))
1211+
elif is_variant(dict_type_name):
1212+
fully_used_classes.add(dict_type_name)
1213+
else:
1214+
used_classes.add(dict_type_name)
11581215
elif is_enum(type_name):
11591216
fully_used_classes.add(get_enum_class(type_name))
11601217
elif is_variant(type_name):
@@ -1281,6 +1338,8 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
12811338
for included in fully_used_classes:
12821339
if included == "TypedArray":
12831340
result.append("#include <godot_cpp/variant/typed_array.hpp>")
1341+
elif included == "TypedDictionary":
1342+
result.append("#include <godot_cpp/variant/typed_dictionary.hpp>")
12841343
else:
12851344
result.append(f"#include <godot_cpp/{get_include_path(included)}>")
12861345

@@ -2322,6 +2381,7 @@ def is_variant(type_name):
23222381
or type_name in builtin_classes
23232382
or type_name == "Nil"
23242383
or type_name.startswith("typedarray::")
2384+
or type_name.startswith("typeddictionary::")
23252385
)
23262386

23272387

@@ -2347,6 +2407,8 @@ def is_included(type_name, current_type):
23472407
"""
23482408
if type_name.startswith("typedarray::"):
23492409
return True
2410+
if type_name.startswith("typeddictionary::"):
2411+
return True
23502412
to_include = get_enum_class(type_name) if is_enum(type_name) else type_name
23512413
if to_include == current_type or is_pod_type(to_include):
23522414
return False
@@ -2380,6 +2442,12 @@ def correct_typed_array(type_name):
23802442
return type_name
23812443

23822444

2445+
def correct_typed_dictionary(type_name):
2446+
if type_name.startswith("typeddictionary::"):
2447+
return type_name.replace("typeddictionary::", "TypedDictionary<").replace(",", ", ") + ">"
2448+
return type_name
2449+
2450+
23832451
def correct_type(type_name, meta=None):
23842452
type_conversion = {"float": "double", "int": "int64_t", "Nil": "Variant"}
23852453
if meta != None:
@@ -2393,6 +2461,8 @@ def correct_type(type_name, meta=None):
23932461
return type_conversion[type_name]
23942462
if type_name.startswith("typedarray::"):
23952463
return type_name.replace("typedarray::", "TypedArray<") + ">"
2464+
if type_name.startswith("typeddictionary::"):
2465+
return type_name.replace("typeddictionary::", "TypedDictionary<").replace(",", ", ") + ">"
23962466
if is_enum(type_name):
23972467
if is_bitfield(type_name):
23982468
base_class = get_enum_class(type_name)
@@ -2497,6 +2567,8 @@ def get_default_value_for_type(type_name):
24972567
return "false"
24982568
if type_name.startswith("typedarray::"):
24992569
return f"{correct_type(type_name)}()"
2570+
if type_name.startswith("typeddictionary::"):
2571+
return f"{correct_type(type_name)}()"
25002572
if is_enum(type_name):
25012573
return f"{correct_type(type_name)}(0)"
25022574
if is_variant(type_name):

gdextension/gdextension_interface.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2065,6 +2065,33 @@ typedef GDExtensionVariantPtr (*GDExtensionInterfaceDictionaryOperatorIndex)(GDE
20652065
*/
20662066
typedef GDExtensionVariantPtr (*GDExtensionInterfaceDictionaryOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionConstVariantPtr p_key);
20672067

2068+
/**
2069+
* @name dictionary_ref
2070+
* @since 4.2
2071+
*
2072+
* Sets a Dictionary to be a reference to another Dictionary object.
2073+
*
2074+
* @param p_self A pointer to the Dictionary object to update.
2075+
* @param p_from A pointer to the Dictionary object to reference.
2076+
*/
2077+
typedef void (*GDExtensionInterfaceDictionaryRef)(GDExtensionTypePtr p_self, GDExtensionConstTypePtr p_from);
2078+
2079+
/**
2080+
* @name dictionary_set_typed
2081+
* @since 4.2
2082+
*
2083+
* Makes a Dictionary into a typed Dictionary.
2084+
*
2085+
* @param p_self A pointer to the Dictionary.
2086+
* @param p_key_type The type of Variant the Dictionary key will store.
2087+
* @param p_key_class_name A pointer to a StringName with the name of the object (if p_key_type is GDEXTENSION_VARIANT_TYPE_OBJECT).
2088+
* @param p_key_script A pointer to a Script object (if p_key_type is GDEXTENSION_VARIANT_TYPE_OBJECT and the base class is extended by a script).
2089+
* @param p_value_type The type of Variant the Dictionary value will store.
2090+
* @param p_value_class_name A pointer to a StringName with the name of the object (if p_value_type is GDEXTENSION_VARIANT_TYPE_OBJECT).
2091+
* @param p_value_script A pointer to a Script object (if p_value_type is GDEXTENSION_VARIANT_TYPE_OBJECT and the base class is extended by a script).
2092+
*/
2093+
typedef void (*GDExtensionInterfaceDictionarySetTyped)(GDExtensionTypePtr p_self, 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);
2094+
20682095
/* INTERFACE: Object */
20692096

20702097
/**

0 commit comments

Comments
 (0)