Skip to content

Commit ba9900f

Browse files
committed
Apply singleton instance binding clean-up fix no matter how it is created
1 parent eb006b6 commit ba9900f

6 files changed

Lines changed: 38 additions & 12 deletions

File tree

‎binding_generator.py‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2078,6 +2078,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
20782078
result = []
20792079

20802080
class_name = class_api["name"]
2081+
inherits = class_api["inherits"] if "inherits" in class_api else "Wrapped"
20812082
snake_class_name = camel_to_snake(class_name)
20822083
is_singleton = class_name in singletons
20832084

@@ -2117,27 +2118,37 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
21172118
result.append("#ifdef DEBUG_ENABLED")
21182119
result.append("\t\tERR_FAIL_NULL_V(singleton_obj, nullptr);")
21192120
result.append("#endif // DEBUG_ENABLED")
2121+
# This will lead to the constructor which will set `singleton`.
21202122
result.append(
2121-
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));"
2123+
f"\t\t::godot::gdextension_interface::object_get_instance_binding(singleton_obj, ::godot::gdextension_interface::token, &{class_name}::_gde_binding_callbacks);"
21222124
)
21232125
result.append("#ifdef DEBUG_ENABLED")
21242126
result.append("\t\tERR_FAIL_NULL_V(singleton, nullptr);")
21252127
result.append("#endif // DEBUG_ENABLED")
2126-
result.append("\t\tif (likely(singleton)) {")
2127-
result.append(f"\t\t\tClassDB::_register_engine_singleton({class_name}::get_class_static(), singleton);")
2128-
result.append("\t\t}")
21292128
result.append("\t}")
21302129
result.append("\treturn singleton;")
21312130
result.append("}")
21322131
result.append("")
21332132

2133+
result.append(f"{class_name}::{class_name}(GodotObject *p_godot_object) : {inherits}(p_godot_object) {{")
2134+
result.append("\tif (singleton == nullptr) {")
2135+
result.append("\t\tsingleton = this;")
2136+
result.append(f"\t\tClassDB::_register_engine_singleton({class_name}::get_class_static(), singleton);")
2137+
result.append("\t}")
2138+
result.append("}")
2139+
result.append("")
2140+
21342141
result.append(f"{class_name}::~{class_name}() {{")
21352142
result.append("\tif (singleton == this) {")
21362143
result.append(f"\t\tClassDB::_unregister_engine_singleton({class_name}::get_class_static());")
21372144
result.append("\t\tsingleton = nullptr;")
21382145
result.append("\t}")
21392146
result.append("}")
21402147
result.append("")
2148+
else:
2149+
result.append(f"{class_name}::{class_name}(GodotObject *p_godot_object) : {inherits}(p_godot_object) {{")
2150+
result.append("}")
2151+
result.append("")
21412152

21422153
if "methods" in class_api:
21432154
for method in class_api["methods"]:

‎include/godot_cpp/classes/wrapped.hpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ private: \
434434
\
435435
protected: \
436436
m_class(const char *p_godot_class) : m_inherits(p_godot_class) {} \
437-
m_class(GodotObject *p_godot_object) : m_inherits(p_godot_object) {} \
437+
m_class(GodotObject *p_godot_object); \
438438
\
439439
static void _bind_methods() {} \
440440
\

‎test/build_profile.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"TileMap",
1212
"TileSet",
1313
"Tween",
14-
"Viewport"
14+
"Viewport",
15+
"XRServer"
1516
]
1617
}

‎test/project/main.gd‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,9 @@ func _ready():
276276
assert_equal(example.test_virtual_implemented_in_script("Virtual", 939), "Implemented")
277277
assert_equal(custom_signal_emitted, ["Virtual", 939])
278278

279-
# Test that we can access an engine singleton.
280-
assert_equal(example.test_use_engine_singleton(), OS.get_name())
279+
# Test that we can access an engine singletons.
280+
assert_equal(example.test_use_engine_singleton1(), OS.get_name())
281+
assert_equal(example.test_use_engine_singleton2(), true)
281282

282283
# Test that we can access the SceneTree singleton.
283284
assert_equal(example.test_use_scene_tree_singleton(), true)

‎test/src/example.cpp‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77

88
#include <godot_cpp/core/class_db.hpp>
99

10+
#include <godot_cpp/classes/engine.hpp>
1011
#include <godot_cpp/classes/global_constants.hpp>
1112
#include <godot_cpp/classes/label.hpp>
1213
#include <godot_cpp/classes/multiplayer_api.hpp>
1314
#include <godot_cpp/classes/multiplayer_peer.hpp>
1415
#include <godot_cpp/classes/os.hpp>
1516
#include <godot_cpp/classes/scene_tree.hpp>
17+
#include <godot_cpp/classes/xr_server.hpp>
1618
#include <godot_cpp/variant/utility_functions.hpp>
1719

1820
using namespace godot;
@@ -269,6 +271,9 @@ void Example::_bind_methods() {
269271
ClassDB::bind_method(D_METHOD("test_use_engine_singleton"), &Example::test_use_engine_singleton);
270272
ClassDB::bind_method(D_METHOD("test_use_scene_tree_singleton"), &Example::test_use_scene_tree_singleton);
271273

274+
ClassDB::bind_method(D_METHOD("test_use_engine_singleton1"), &Example::test_use_engine_singleton1);
275+
ClassDB::bind_method(D_METHOD("test_use_engine_singleton2"), &Example::test_use_engine_singleton2);
276+
272277
ClassDB::bind_method(D_METHOD("test_get_internal_class"), &Example::test_get_internal_class);
273278

274279
ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static);
@@ -757,15 +762,20 @@ String Example::test_virtual_implemented_in_script(const String &p_name, int p_v
757762
return "Unimplemented";
758763
}
759764

760-
String Example::test_use_engine_singleton() const {
761-
return OS::get_singleton()->get_name();
762-
}
763-
764765
bool Example::test_use_scene_tree_singleton() const {
765766
SceneTree *scene_tree = SceneTree::get_singleton();
766767
return scene_tree != nullptr && scene_tree == get_tree();
767768
}
768769

770+
String Example::test_use_engine_singleton1() const {
771+
return OS::get_singleton()->get_name();
772+
}
773+
774+
bool Example::test_use_engine_singleton2() const {
775+
XRServer *xr_server = Object::cast_to<XRServer>(Engine::get_singleton()->get_singleton("XRServer"));
776+
return xr_server != nullptr;
777+
}
778+
769779
String Example::test_library_path() {
770780
String library_path;
771781
::godot::gdextension_interface::get_library_path(::godot::gdextension_interface::library, library_path._native_ptr());

‎test/src/example.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ class Example : public Control {
216216
String test_use_engine_singleton() const;
217217
bool test_use_scene_tree_singleton() const;
218218

219+
String test_use_engine_singleton1() const;
220+
bool test_use_engine_singleton2() const;
221+
219222
static String test_library_path();
220223

221224
Ref<RefCounted> test_get_internal_class() const;

0 commit comments

Comments
 (0)