Ver Fonte

Correctly set instance bindings on reload

David Snopek há 10 meses atrás
pai
commit
cb543c192a

+ 4 - 9
include/godot_cpp/classes/wrapped.hpp

@@ -61,6 +61,10 @@ class Wrapped {
 	thread_local static const StringName *_constructing_extension_class_name;
 	thread_local static const GDExtensionInstanceBindingCallbacks *_constructing_class_binding_callbacks;
 
+#ifdef HOT_RELOAD_ENABLED
+	thread_local static GDExtensionObjectPtr _constructing_recreate_owner;
+#endif
+
 	template <typename T>
 	_ALWAYS_INLINE_ static void _set_construct_info() {
 		_constructing_extension_class_name = T::_get_extension_class_name();
@@ -71,15 +75,6 @@ protected:
 	virtual bool _is_extension_class() const { return false; }
 	static const StringName *_get_extension_class_name(); // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned.
 
-#ifdef HOT_RELOAD_ENABLED
-	struct RecreateInstance {
-		GDExtensionClassInstancePtr wrapper;
-		GDExtensionObjectPtr owner;
-		RecreateInstance *next;
-	};
-	inline static RecreateInstance *recreate_instance = nullptr;
-#endif
-
 	void _notification(int p_what) {}
 	bool _set(const StringName &p_name, const Variant &p_property) { return false; }
 	bool _get(const StringName &p_name, Variant &r_property) const { return false; }

+ 1 - 2
include/godot_cpp/core/class_db.hpp

@@ -129,9 +129,8 @@ private:
 	static GDExtensionClassInstancePtr _recreate_instance_func(void *data, GDExtensionObjectPtr obj) {
 		if constexpr (!std::is_abstract_v<T>) {
 #ifdef HOT_RELOAD_ENABLED
+			Wrapped::_constructing_recreate_owner = obj;
 			T *new_instance = (T *)memalloc(sizeof(T));
-			Wrapped::RecreateInstance recreate_data = { new_instance, obj, Wrapped::recreate_instance };
-			Wrapped::recreate_instance = &recreate_data;
 			memnew_placement(new_instance, T);
 			return new_instance;
 #else

+ 11 - 18
src/classes/wrapped.cpp

@@ -42,6 +42,10 @@ namespace godot {
 thread_local const StringName *Wrapped::_constructing_extension_class_name = nullptr;
 thread_local const GDExtensionInstanceBindingCallbacks *Wrapped::_constructing_class_binding_callbacks = nullptr;
 
+#ifdef HOT_RELOAD_ENABLED
+thread_local GDExtensionObjectPtr Wrapped::_constructing_recreate_owner = nullptr;
+#endif
+
 const StringName *Wrapped::_get_extension_class_name() {
 	return nullptr;
 }
@@ -55,25 +59,14 @@ void Wrapped::_postinitialize() {
 
 Wrapped::Wrapped(const StringName p_godot_class) {
 #ifdef HOT_RELOAD_ENABLED
-	if (unlikely(Wrapped::recreate_instance)) {
-		RecreateInstance *recreate_data = Wrapped::recreate_instance;
-		RecreateInstance *previous = nullptr;
-		while (recreate_data) {
-			if (recreate_data->wrapper == this) {
-				_owner = recreate_data->owner;
-				if (previous) {
-					previous->next = recreate_data->next;
-				} else {
-					Wrapped::recreate_instance = recreate_data->next;
-				}
-				return;
-			}
-			previous = recreate_data;
-			recreate_data = recreate_data->next;
-		}
-	}
+	if (unlikely(Wrapped::_constructing_recreate_owner)) {
+		_owner = Wrapped::_constructing_recreate_owner;
+		Wrapped::_constructing_recreate_owner = nullptr;
+	} else
 #endif
-	_owner = godot::internal::gdextension_interface_classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr()));
+	{
+		_owner = godot::internal::gdextension_interface_classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr()));
+	}
 
 	if (_constructing_extension_class_name) {
 		godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(_constructing_extension_class_name), this);