Correctly set instance bindings on reload
parent
4131b7f95f
commit
cb543c192a
|
@ -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; }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
||||
if (_constructing_extension_class_name) {
|
||||
godot::internal::gdextension_interface_object_set_instance(_owner, reinterpret_cast<GDExtensionConstStringNamePtr>(_constructing_extension_class_name), this);
|
||||
|
|
Loading…
Reference in New Issue