-
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
47b686f
commit 9a05247
Showing
4 changed files
with
201 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
diff --git a/binding_generator.py b/binding_generator.py | ||
index d04c698..bb4a6a5 100644 | ||
--- a/binding_generator.py | ||
+++ b/binding_generator.py | ||
@@ -97,9 +97,9 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False): | ||
files.append(str(source_filename.as_posix())) | ||
|
||
for engine_class in api["classes"]: | ||
- # TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings. | ||
+ # Generate code for the ClassDB singleton under a different name. | ||
if engine_class["name"] == "ClassDB": | ||
- continue | ||
+ engine_class["name"] = "ClassDBSingleton" | ||
header_filename = include_gen_folder / "classes" / (camel_to_snake(engine_class["name"]) + ".hpp") | ||
source_filename = source_gen_folder / "classes" / (camel_to_snake(engine_class["name"]) + ".cpp") | ||
if headers: | ||
@@ -1036,21 +1036,21 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node): | ||
|
||
# First create map of classes and singletons. | ||
for class_api in api["classes"]: | ||
- # TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings. | ||
+ # Generate code for the ClassDB singleton under a different name. | ||
if class_api["name"] == "ClassDB": | ||
- continue | ||
+ class_api["name"] = "ClassDBSingleton" | ||
engine_classes[class_api["name"]] = class_api["is_refcounted"] | ||
for native_struct in api["native_structures"]: | ||
engine_classes[native_struct["name"]] = False | ||
native_structures.append(native_struct["name"]) | ||
|
||
for singleton in api["singletons"]: | ||
+ # Generate code for the ClassDB singleton under a different name. | ||
+ if singleton["name"] == "ClassDB": | ||
+ singleton["name"] = "ClassDBSingleton" | ||
singletons.append(singleton["name"]) | ||
|
||
for class_api in api["classes"]: | ||
- # TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings. | ||
- if class_api["name"] == "ClassDB": | ||
- continue | ||
# Check used classes for header include. | ||
used_classes = set() | ||
fully_used_classes = set() | ||
@@ -1242,7 +1242,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us | ||
if len(fully_used_classes) > 0: | ||
result.append("") | ||
|
||
- if class_name != "Object": | ||
+ if class_name != "Object" and class_name != "ClassDBSingleton": | ||
result.append("#include <godot_cpp/core/class_db.hpp>") | ||
result.append("") | ||
result.append("#include <type_traits>") | ||
@@ -1421,6 +1421,51 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us | ||
result.append(f'VARIANT_ENUM_CAST({class_name}::{enum_api["name"]});') | ||
result.append("") | ||
|
||
+ if class_name == "ClassDBSingleton": | ||
+ result.append("#define CLASSDB_SINGLETON_FORWARD_METHODS \\") | ||
+ for method in class_api["methods"]: | ||
+ # ClassDBSingleton shouldn't have any static or vararg methods, but if some appear later, lets skip them. | ||
+ if vararg: | ||
+ continue | ||
+ if "is_static" in method and method["is_static"]: | ||
+ continue | ||
+ | ||
+ method_signature = "\tstatic " | ||
+ if "return_type" in method: | ||
+ method_signature += f'{correct_type(method["return_type"])} ' | ||
+ elif "return_value" in method: | ||
+ method_signature += ( | ||
+ correct_type(method["return_value"]["type"], method["return_value"].get("meta", None)) + " " | ||
+ ) | ||
+ else: | ||
+ method_signature += "void " | ||
+ | ||
+ method_signature += f'{method["name"]}(' | ||
+ | ||
+ method_arguments = [] | ||
+ if "arguments" in method: | ||
+ method_arguments = method["arguments"] | ||
+ | ||
+ method_signature += make_function_parameters( | ||
+ method_arguments, include_default=True, for_builtin=True, is_vararg=False | ||
+ ) | ||
+ | ||
+ method_signature += ") { \\" | ||
+ | ||
+ result.append(method_signature) | ||
+ | ||
+ method_body = "\t\t" | ||
+ if "return_type" in method or "return_value" in method: | ||
+ method_body += "return " | ||
+ method_body += f'ClassDBSingleton::get_singleton()->{method["name"]}(' | ||
+ method_body += ", ".join(map(lambda x: escape_identifier(x["name"]), method_arguments)) | ||
+ method_body += "); \\" | ||
+ | ||
+ result.append(method_body) | ||
+ result.append("\t} \\") | ||
+ result.append("\t;") | ||
+ result.append("") | ||
+ | ||
result.append(f"#endif // ! {header_guard}") | ||
|
||
return "\n".join(result) | ||
@@ -1453,7 +1498,10 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us | ||
|
||
if is_singleton: | ||
result.append(f"{class_name} *{class_name}::get_singleton() {{") | ||
- result.append(f"\tconst StringName _gde_class_name = {class_name}::get_class_static();") | ||
+ if class_name != "ClassDBSingleton": | ||
+ result.append(f"\tconst StringName _gde_class_name = {class_name}::get_class_static();") | ||
+ else: | ||
+ result.append(f"\tstatic const StringName _gde_class_name = StringName(\"ClassDB\");") | ||
result.append( | ||
"\tstatic GDExtensionObjectPtr singleton_obj = internal::gdextension_interface_global_get_singleton(_gde_class_name._native_ptr());" | ||
) | ||
@@ -1480,7 +1528,10 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us | ||
result.append(method_signature + " {") | ||
|
||
# Method body. | ||
- result.append(f"\tconst StringName _gde_class_name = {class_name}::get_class_static();") | ||
+ if class_name != "ClassDBSingleton": | ||
+ result.append(f"\tconst StringName _gde_class_name = {class_name}::get_class_static();") | ||
+ else: | ||
+ result.append(f"\tstatic const StringName _gde_class_name = StringName(\"ClassDB\");") | ||
result.append(f'\tconst StringName _gde_method_name = "{method["name"]}";') | ||
result.append( | ||
f'\tstatic GDExtensionMethodBindPtr _gde_method_bind = internal::gdextension_interface_classdb_get_method_bind(_gde_class_name._native_ptr(), _gde_method_name._native_ptr(), {method["hash"]});' | ||
@@ -2285,6 +2336,7 @@ def escape_identifier(id): | ||
"operator": "_operator", | ||
"typeof": "type_of", | ||
"typename": "type_name", | ||
+ "enum": "_enum", | ||
} | ||
if id in cpp_keywords_map: | ||
return cpp_keywords_map[id] | ||
diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp | ||
index b1625bf..26dfb7e 100644 | ||
--- a/include/godot_cpp/core/class_db.hpp | ||
+++ b/include/godot_cpp/core/class_db.hpp | ||
@@ -38,6 +38,8 @@ | ||
#include <godot_cpp/core/method_bind.hpp> | ||
#include <godot_cpp/core/object.hpp> | ||
|
||
+#include <godot_cpp/classes/class_db_singleton.hpp> | ||
+ | ||
#include <list> | ||
#include <set> | ||
#include <string> | ||
@@ -146,6 +148,8 @@ public: | ||
|
||
static void initialize(GDExtensionInitializationLevel p_level); | ||
static void deinitialize(GDExtensionInitializationLevel p_level); | ||
+ | ||
+ CLASSDB_SINGLETON_FORWARD_METHODS; | ||
}; | ||
|
||
#define BIND_CONSTANT(m_constant) \ | ||
diff --git a/src/core/class_db.cpp b/src/core/class_db.cpp | ||
index e8bb40c..cfd065e 100644 | ||
--- a/src/core/class_db.cpp | ||
+++ b/src/core/class_db.cpp | ||
@@ -318,7 +318,18 @@ GDExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, GDExtens | ||
|
||
const GDExtensionInstanceBindingCallbacks *ClassDB::get_instance_binding_callbacks(const StringName &p_class) { | ||
std::unordered_map<StringName, const GDExtensionInstanceBindingCallbacks *>::iterator callbacks_it = instance_binding_callbacks.find(p_class); | ||
- ERR_FAIL_COND_V_MSG(callbacks_it == instance_binding_callbacks.end(), nullptr, String("Cannot find instance binding callbacks for class '{0}'.").format(Array::make(p_class))); | ||
+ if (likely(callbacks_it != instance_binding_callbacks.end())) { | ||
+ return callbacks_it->second; | ||
+ } | ||
+ | ||
+ // If we don't have an instance binding callback for the given class, find the closest parent where we do. | ||
+ StringName class_name = p_class; | ||
+ do { | ||
+ class_name = get_parent_class(class_name); | ||
+ ERR_FAIL_COND_V_MSG(class_name == StringName(), nullptr, String("Cannot find instance binding callbacks for class '{0}'.").format(Array::make(p_class))); | ||
+ callbacks_it = instance_binding_callbacks.find(class_name); | ||
+ } while (callbacks_it == instance_binding_callbacks.end()); | ||
+ | ||
return callbacks_it->second; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters