diff --git a/binding_generator.py b/binding_generator.py index 4eb35404d..d3eedb041 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -2078,6 +2078,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us result = [] class_name = class_api["name"] + inherits = class_api["inherits"] if "inherits" in class_api else "Wrapped" snake_class_name = camel_to_snake(class_name) is_singleton = class_name in singletons @@ -2117,20 +2118,26 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us result.append("#ifdef DEBUG_ENABLED") result.append("\t\tERR_FAIL_NULL_V(singleton_obj, nullptr);") result.append("#endif // DEBUG_ENABLED") + # This will lead to the constructor which will set `singleton`. result.append( - f"\t\tsingleton = reinterpret_cast<{class_name} *>(::godot::gdextension_interface::object_get_instance_binding(singleton_obj, ::godot::gdextension_interface::token, &{class_name}::_gde_binding_callbacks));" + f"\t\t::godot::gdextension_interface::object_get_instance_binding(singleton_obj, ::godot::gdextension_interface::token, &{class_name}::_gde_binding_callbacks);" ) result.append("#ifdef DEBUG_ENABLED") result.append("\t\tERR_FAIL_NULL_V(singleton, nullptr);") result.append("#endif // DEBUG_ENABLED") - result.append("\t\tif (likely(singleton)) {") - result.append(f"\t\t\tClassDB::_register_engine_singleton({class_name}::get_class_static(), singleton);") - result.append("\t\t}") result.append("\t}") result.append("\treturn singleton;") result.append("}") result.append("") + result.append(f"{class_name}::{class_name}(GodotObject *p_godot_object) : {inherits}(p_godot_object) {{") + result.append("\tif (singleton == nullptr) {") + result.append("\t\tsingleton = this;") + result.append(f"\t\tClassDB::_register_engine_singleton({class_name}::get_class_static(), singleton);") + result.append("\t}") + result.append("}") + result.append("") + result.append(f"{class_name}::~{class_name}() {{") result.append("\tif (singleton == this) {") result.append(f"\t\tClassDB::_unregister_engine_singleton({class_name}::get_class_static());") @@ -2138,6 +2145,10 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us result.append("\t}") result.append("}") result.append("") + else: + result.append(f"{class_name}::{class_name}(GodotObject *p_godot_object) : {inherits}(p_godot_object) {{") + result.append("}") + result.append("") if "methods" in class_api: for method in class_api["methods"]: diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index 3e0bac84f..28ef5395a 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -434,7 +434,7 @@ private: \ \ protected: \ m_class(const char *p_godot_class) : m_inherits(p_godot_class) {} \ - m_class(GodotObject *p_godot_object) : m_inherits(p_godot_object) {} \ + m_class(GodotObject *p_godot_object); \ \ static void _bind_methods() {} \ \ diff --git a/test/build_profile.json b/test/build_profile.json index 54bd2d6a1..a17858639 100644 --- a/test/build_profile.json +++ b/test/build_profile.json @@ -11,6 +11,7 @@ "TileMap", "TileSet", "Tween", - "Viewport" + "Viewport", + "XRServer" ] } diff --git a/test/project/main.gd b/test/project/main.gd index d002bccc5..c4bcf6621 100644 --- a/test/project/main.gd +++ b/test/project/main.gd @@ -276,8 +276,9 @@ func _ready(): assert_equal(example.test_virtual_implemented_in_script("Virtual", 939), "Implemented") assert_equal(custom_signal_emitted, ["Virtual", 939]) - # Test that we can access an engine singleton. - assert_equal(example.test_use_engine_singleton(), OS.get_name()) + # Test that we can access an engine singletons. + assert_equal(example.test_use_engine_singleton1(), OS.get_name()) + assert_equal(example.test_use_engine_singleton2(), true) # Test that we can access the SceneTree singleton. assert_equal(example.test_use_scene_tree_singleton(), true) diff --git a/test/src/example.cpp b/test/src/example.cpp index 0f42bf176..c28a30764 100644 --- a/test/src/example.cpp +++ b/test/src/example.cpp @@ -7,12 +7,14 @@ #include +#include #include #include #include #include #include #include +#include #include using namespace godot; @@ -266,8 +268,9 @@ void Example::_bind_methods() { ClassDB::bind_method(D_METHOD("test_virtual_implemented_in_script"), &Example::test_virtual_implemented_in_script); GDVIRTUAL_BIND(_do_something_virtual_with_control, "control"); - ClassDB::bind_method(D_METHOD("test_use_engine_singleton"), &Example::test_use_engine_singleton); ClassDB::bind_method(D_METHOD("test_use_scene_tree_singleton"), &Example::test_use_scene_tree_singleton); + ClassDB::bind_method(D_METHOD("test_use_engine_singleton1"), &Example::test_use_engine_singleton1); + ClassDB::bind_method(D_METHOD("test_use_engine_singleton2"), &Example::test_use_engine_singleton2); ClassDB::bind_method(D_METHOD("test_get_internal_class"), &Example::test_get_internal_class); @@ -757,15 +760,20 @@ String Example::test_virtual_implemented_in_script(const String &p_name, int p_v return "Unimplemented"; } -String Example::test_use_engine_singleton() const { - return OS::get_singleton()->get_name(); -} - bool Example::test_use_scene_tree_singleton() const { SceneTree *scene_tree = SceneTree::get_singleton(); return scene_tree != nullptr && scene_tree == get_tree(); } +String Example::test_use_engine_singleton1() const { + return OS::get_singleton()->get_name(); +} + +bool Example::test_use_engine_singleton2() const { + XRServer *xr_server = Object::cast_to(Engine::get_singleton()->get_singleton("XRServer")); + return xr_server != nullptr; +} + String Example::test_library_path() { String library_path; ::godot::gdextension_interface::get_library_path(::godot::gdextension_interface::library, library_path._native_ptr()); diff --git a/test/src/example.h b/test/src/example.h index 82361fe7d..770ca0a19 100644 --- a/test/src/example.h +++ b/test/src/example.h @@ -216,6 +216,9 @@ class Example : public Control { String test_use_engine_singleton() const; bool test_use_scene_tree_singleton() const; + String test_use_engine_singleton1() const; + bool test_use_engine_singleton2() const; + static String test_library_path(); Ref test_get_internal_class() const;