Skip to content

Commit 2b6eb68

Browse files
authored
Merge pull request #1465 from dsnopek/4.2-cherrypicks-4
Cherry-picks for the godot-cpp 4.2 branch - 4th batch
2 parents b28098e + a246aaa commit 2b6eb68

35 files changed

+321
-28
lines changed

binding_generator.py

Lines changed: 78 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ def generate_bindings(api_filepath, use_template_get_node, bits="64", precision=
181181
generate_utility_functions(api, target_dir)
182182

183183

184+
CLASS_ALIASES = {
185+
"ClassDB": "ClassDBSingleton",
186+
}
187+
184188
builtin_classes = []
185189

186190
# Key is class name, value is boolean where True means the class is refcounted.
@@ -1127,9 +1131,9 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
11271131
# First create map of classes and singletons.
11281132
for class_api in api["classes"]:
11291133
# Generate code for the ClassDB singleton under a different name.
1130-
if class_api["name"] == "ClassDB":
1131-
class_api["name"] = "ClassDBSingleton"
1132-
class_api["alias_for"] = "ClassDB"
1134+
if class_api["name"] in CLASS_ALIASES:
1135+
class_api["alias_for"] = class_api["name"]
1136+
class_api["name"] = CLASS_ALIASES[class_api["alias_for"]]
11331137
engine_classes[class_api["name"]] = class_api["is_refcounted"]
11341138
for native_struct in api["native_structures"]:
11351139
if native_struct["name"] == "ObjectID":
@@ -1139,9 +1143,9 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
11391143

11401144
for singleton in api["singletons"]:
11411145
# Generate code for the ClassDB singleton under a different name.
1142-
if singleton["name"] == "ClassDB":
1143-
singleton["name"] = "ClassDBSingleton"
1144-
singleton["alias_for"] = "ClassDB"
1146+
if singleton["name"] in CLASS_ALIASES:
1147+
singleton["alias_for"] = singleton["name"]
1148+
singleton["name"] = CLASS_ALIASES[singleton["name"]]
11451149
singletons.append(singleton["name"])
11461150

11471151
for class_api in api["classes"]:
@@ -1346,6 +1350,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
13461350
result.append("#include <type_traits>")
13471351
result.append("")
13481352

1353+
if class_name == "ClassDBSingleton":
1354+
result.append("#include <godot_cpp/core/binder_common.hpp>")
1355+
result.append("")
1356+
13491357
result.append("namespace godot {")
13501358
result.append("")
13511359

@@ -1367,6 +1375,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
13671375
result.append(f"\tGDEXTENSION_CLASS({class_name}, {inherits})")
13681376
result.append("")
13691377

1378+
if is_singleton:
1379+
result.append(f"\tstatic {class_name} *singleton;")
1380+
result.append("")
1381+
13701382
result.append("public:")
13711383
result.append("")
13721384

@@ -1447,6 +1459,11 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
14471459

14481460
result.append("\t}")
14491461
result.append("")
1462+
1463+
if is_singleton:
1464+
result.append(f"\t~{class_name}();")
1465+
result.append("")
1466+
14501467
result.append("public:")
14511468

14521469
# Special cases.
@@ -1504,6 +1521,19 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
15041521

15051522
if class_name == "ClassDBSingleton":
15061523
result.append("#define CLASSDB_SINGLETON_FORWARD_METHODS \\")
1524+
1525+
if "enums" in class_api:
1526+
for enum_api in class_api["enums"]:
1527+
if enum_api["is_bitfield"]:
1528+
result.append(f'\tenum {enum_api["name"]} : uint64_t {{ \\')
1529+
else:
1530+
result.append(f'\tenum {enum_api["name"]} {{ \\')
1531+
1532+
for value in enum_api["values"]:
1533+
result.append(f'\t\t{value["name"]} = {value["value"]}, \\')
1534+
result.append("\t}; \\")
1535+
result.append("\t \\")
1536+
15071537
for method in class_api["methods"]:
15081538
# ClassDBSingleton shouldn't have any static or vararg methods, but if some appear later, lets skip them.
15091539
if vararg:
@@ -1512,12 +1542,17 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
15121542
continue
15131543

15141544
method_signature = "\tstatic "
1545+
return_type = None
15151546
if "return_type" in method:
1516-
method_signature += f'{correct_type(method["return_type"])} '
1547+
return_type = correct_type(method["return_type"].replace("ClassDBSingleton", "ClassDB"), None, False)
15171548
elif "return_value" in method:
1518-
method_signature += (
1519-
correct_type(method["return_value"]["type"], method["return_value"].get("meta", None)) + " "
1549+
return_type = correct_type(
1550+
method["return_value"]["type"].replace("ClassDBSingleton", "ClassDB"),
1551+
method["return_value"].get("meta", None),
1552+
False,
15201553
)
1554+
if return_type is not None:
1555+
method_signature += return_type + " "
15211556
else:
15221557
method_signature += "void "
15231558

@@ -1536,8 +1571,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
15361571
result.append(method_signature)
15371572

15381573
method_body = "\t\t"
1539-
if "return_type" in method or "return_value" in method:
1574+
if return_type is not None:
15401575
method_body += "return "
1576+
if "alias_for" in class_api and return_type.startswith(class_api["alias_for"] + "::"):
1577+
method_body += f"({return_type})"
15411578
method_body += f'ClassDBSingleton::get_singleton()->{method["name"]}('
15421579
method_body += ", ".join(map(lambda x: escape_identifier(x["name"]), method_arguments))
15431580
method_body += "); \\"
@@ -1547,6 +1584,18 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
15471584
result.append("\t;")
15481585
result.append("")
15491586

1587+
result.append("#define CLASSDB_SINGLETON_VARIANT_CAST \\")
1588+
1589+
if "enums" in class_api:
1590+
for enum_api in class_api["enums"]:
1591+
if enum_api["is_bitfield"]:
1592+
result.append(f'\tVARIANT_BITFIELD_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\')
1593+
else:
1594+
result.append(f'\tVARIANT_ENUM_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\')
1595+
1596+
result.append("\t;")
1597+
result.append("")
1598+
15501599
result.append(f"#endif // ! {header_guard}")
15511600

15521601
return "\n".join(result)
@@ -1564,6 +1613,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
15641613

15651614
result.append(f"#include <godot_cpp/classes/{snake_class_name}.hpp>")
15661615
result.append("")
1616+
result.append("#include <godot_cpp/core/class_db.hpp>")
15671617
result.append("#include <godot_cpp/core/engine_ptrcall.hpp>")
15681618
result.append("#include <godot_cpp/core/error_macros.hpp>")
15691619
result.append("")
@@ -1578,9 +1628,10 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
15781628
result.append("")
15791629

15801630
if is_singleton:
1631+
result.append(f"{class_name} *{class_name}::singleton = nullptr;")
1632+
result.append("")
15811633
result.append(f"{class_name} *{class_name}::get_singleton() {{")
15821634
# We assume multi-threaded access is OK because each assignment will assign the same value every time
1583-
result.append(f"\tstatic {class_name} *singleton = nullptr;")
15841635
result.append("\tif (unlikely(singleton == nullptr)) {")
15851636
result.append(
15861637
f"\t\tGDExtensionObjectPtr singleton_obj = internal::gdextension_interface_global_get_singleton({class_name}::get_class_static()._native_ptr());"
@@ -1594,11 +1645,22 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
15941645
result.append("#ifdef DEBUG_ENABLED")
15951646
result.append("\t\tERR_FAIL_NULL_V(singleton, nullptr);")
15961647
result.append("#endif // DEBUG_ENABLED")
1648+
result.append("\t\tif (likely(singleton)) {")
1649+
result.append(f"\t\t\tClassDB::_register_engine_singleton({class_name}::get_class_static(), singleton);")
1650+
result.append("\t\t}")
15971651
result.append("\t}")
15981652
result.append("\treturn singleton;")
15991653
result.append("}")
16001654
result.append("")
16011655

1656+
result.append(f"{class_name}::~{class_name}() {{")
1657+
result.append("\tif (singleton == this) {")
1658+
result.append(f"\t\tClassDB::_unregister_engine_singleton({class_name}::get_class_static());")
1659+
result.append("\t\tsingleton = nullptr;")
1660+
result.append("\t}")
1661+
result.append("}")
1662+
result.append("")
1663+
16021664
if "methods" in class_api:
16031665
for method in class_api["methods"]:
16041666
if method["is_virtual"]:
@@ -2384,7 +2446,7 @@ def correct_typed_array(type_name):
23842446
return type_name
23852447

23862448

2387-
def correct_type(type_name, meta=None):
2449+
def correct_type(type_name, meta=None, use_alias=True):
23882450
type_conversion = {"float": "double", "int": "int64_t", "Nil": "Variant"}
23892451
if meta != None:
23902452
if "int" in meta:
@@ -2400,11 +2462,15 @@ def correct_type(type_name, meta=None):
24002462
if is_enum(type_name):
24012463
if is_bitfield(type_name):
24022464
base_class = get_enum_class(type_name)
2465+
if use_alias and base_class in CLASS_ALIASES:
2466+
base_class = CLASS_ALIASES[base_class]
24032467
if base_class == "GlobalConstants":
24042468
return f"BitField<{get_enum_name(type_name)}>"
24052469
return f"BitField<{base_class}::{get_enum_name(type_name)}>"
24062470
else:
24072471
base_class = get_enum_class(type_name)
2472+
if use_alias and base_class in CLASS_ALIASES:
2473+
base_class = CLASS_ALIASES[base_class]
24082474
if base_class == "GlobalConstants":
24092475
return f"{get_enum_name(type_name)}"
24102476
return f"{base_class}::{get_enum_name(type_name)}"

0 commit comments

Comments
 (0)