Skip to content

Commit 54fe2f9

Browse files
authored
Merge pull request #1445 from dsnopek/classdb-enum-issue
Allow forwarding from `ClassDB` to `ClassDBSingleton` to support enumerations
2 parents 2cd3d39 + e1b3b32 commit 54fe2f9

File tree

2 files changed

+57
-11
lines changed

2 files changed

+57
-11
lines changed

binding_generator.py

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,10 @@ def generate_bindings(api_filepath, use_template_get_node, bits="64", precision=
309309
generate_utility_functions(api, target_dir)
310310

311311

312+
CLASS_ALIASES = {
313+
"ClassDB": "ClassDBSingleton",
314+
}
315+
312316
builtin_classes = []
313317

314318
# Key is class name, value is boolean where True means the class is refcounted.
@@ -1256,9 +1260,9 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
12561260
# First create map of classes and singletons.
12571261
for class_api in api["classes"]:
12581262
# Generate code for the ClassDB singleton under a different name.
1259-
if class_api["name"] == "ClassDB":
1260-
class_api["name"] = "ClassDBSingleton"
1261-
class_api["alias_for"] = "ClassDB"
1263+
if class_api["name"] in CLASS_ALIASES:
1264+
class_api["alias_for"] = class_api["name"]
1265+
class_api["name"] = CLASS_ALIASES[class_api["alias_for"]]
12621266
engine_classes[class_api["name"]] = class_api["is_refcounted"]
12631267
for native_struct in api["native_structures"]:
12641268
if native_struct["name"] == "ObjectID":
@@ -1268,9 +1272,9 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
12681272

12691273
for singleton in api["singletons"]:
12701274
# Generate code for the ClassDB singleton under a different name.
1271-
if singleton["name"] == "ClassDB":
1272-
singleton["name"] = "ClassDBSingleton"
1273-
singleton["alias_for"] = "ClassDB"
1275+
if singleton["name"] in CLASS_ALIASES:
1276+
singleton["alias_for"] = singleton["name"]
1277+
singleton["name"] = CLASS_ALIASES[singleton["name"]]
12741278
singletons.append(singleton["name"])
12751279

12761280
for class_api in api["classes"]:
@@ -1475,6 +1479,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
14751479
result.append("#include <type_traits>")
14761480
result.append("")
14771481

1482+
if class_name == "ClassDBSingleton":
1483+
result.append("#include <godot_cpp/core/binder_common.hpp>")
1484+
result.append("")
1485+
14781486
result.append("namespace godot {")
14791487
result.append("")
14801488

@@ -1633,6 +1641,19 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
16331641

16341642
if class_name == "ClassDBSingleton":
16351643
result.append("#define CLASSDB_SINGLETON_FORWARD_METHODS \\")
1644+
1645+
if "enums" in class_api:
1646+
for enum_api in class_api["enums"]:
1647+
if enum_api["is_bitfield"]:
1648+
result.append(f'\tenum {enum_api["name"]} : uint64_t {{ \\')
1649+
else:
1650+
result.append(f'\tenum {enum_api["name"]} {{ \\')
1651+
1652+
for value in enum_api["values"]:
1653+
result.append(f'\t\t{value["name"]} = {value["value"]}, \\')
1654+
result.append("\t}; \\")
1655+
result.append("\t \\")
1656+
16361657
for method in class_api["methods"]:
16371658
# ClassDBSingleton shouldn't have any static or vararg methods, but if some appear later, lets skip them.
16381659
if vararg:
@@ -1641,12 +1662,17 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
16411662
continue
16421663

16431664
method_signature = "\tstatic "
1665+
return_type = None
16441666
if "return_type" in method:
1645-
method_signature += f'{correct_type(method["return_type"])} '
1667+
return_type = correct_type(method["return_type"].replace("ClassDBSingleton", "ClassDB"), None, False)
16461668
elif "return_value" in method:
1647-
method_signature += (
1648-
correct_type(method["return_value"]["type"], method["return_value"].get("meta", None)) + " "
1669+
return_type = correct_type(
1670+
method["return_value"]["type"].replace("ClassDBSingleton", "ClassDB"),
1671+
method["return_value"].get("meta", None),
1672+
False,
16491673
)
1674+
if return_type is not None:
1675+
method_signature += return_type + " "
16501676
else:
16511677
method_signature += "void "
16521678

@@ -1665,8 +1691,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
16651691
result.append(method_signature)
16661692

16671693
method_body = "\t\t"
1668-
if "return_type" in method or "return_value" in method:
1694+
if return_type is not None:
16691695
method_body += "return "
1696+
if "alias_for" in class_api and return_type.startswith(class_api["alias_for"] + "::"):
1697+
method_body += f"({return_type})"
16701698
method_body += f'ClassDBSingleton::get_singleton()->{method["name"]}('
16711699
method_body += ", ".join(map(lambda x: escape_identifier(x["name"]), method_arguments))
16721700
method_body += "); \\"
@@ -1676,6 +1704,18 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
16761704
result.append("\t;")
16771705
result.append("")
16781706

1707+
result.append("#define CLASSDB_SINGLETON_VARIANT_CAST \\")
1708+
1709+
if "enums" in class_api:
1710+
for enum_api in class_api["enums"]:
1711+
if enum_api["is_bitfield"]:
1712+
result.append(f'\tVARIANT_BITFIELD_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\')
1713+
else:
1714+
result.append(f'\tVARIANT_ENUM_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\')
1715+
1716+
result.append("\t;")
1717+
result.append("")
1718+
16791719
result.append(f"#endif // ! {header_guard}")
16801720

16811721
return "\n".join(result)
@@ -2513,7 +2553,7 @@ def correct_typed_array(type_name):
25132553
return type_name
25142554

25152555

2516-
def correct_type(type_name, meta=None):
2556+
def correct_type(type_name, meta=None, use_alias=True):
25172557
type_conversion = {"float": "double", "int": "int64_t", "Nil": "Variant"}
25182558
if meta != None:
25192559
if "int" in meta:
@@ -2529,11 +2569,15 @@ def correct_type(type_name, meta=None):
25292569
if is_enum(type_name):
25302570
if is_bitfield(type_name):
25312571
base_class = get_enum_class(type_name)
2572+
if use_alias and base_class in CLASS_ALIASES:
2573+
base_class = CLASS_ALIASES[base_class]
25322574
if base_class == "GlobalConstants":
25332575
return f"BitField<{get_enum_name(type_name)}>"
25342576
return f"BitField<{base_class}::{get_enum_name(type_name)}>"
25352577
else:
25362578
base_class = get_enum_class(type_name)
2579+
if use_alias and base_class in CLASS_ALIASES:
2580+
base_class = CLASS_ALIASES[base_class]
25372581
if base_class == "GlobalConstants":
25382582
return f"{get_enum_name(type_name)}"
25392583
return f"{base_class}::{get_enum_name(type_name)}"

include/godot_cpp/core/class_db.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,4 +339,6 @@ MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p
339339

340340
} // namespace godot
341341

342+
CLASSDB_SINGLETON_VARIANT_CAST;
343+
342344
#endif // GODOT_CLASS_DB_HPP

0 commit comments

Comments
 (0)