From 1627287586a0d4a034cc3645475fb4f57e18ab52 Mon Sep 17 00:00:00 2001 From: Paul Joannon Date: Thu, 18 Apr 2024 09:38:10 +0200 Subject: [PATCH] Change order of operation for C# types reloading We now deserialize callables before reloading property states, in case a property is doing anything with the callable in its getter and/or setter. --- modules/mono/csharp_script.cpp | 51 +++++++++++++++++----------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index a3464ccfc25c..dcc18ebdd73f 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -941,6 +941,31 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { to_reload_state.push_back(scr); } + // Deserialize managed callables. + // This is done before reloading script's internal state, so potential callables invoked in properties work. + { + MutexLock lock(ManagedCallable::instances_mutex); + + for (const KeyValue &elem : ManagedCallable::instances_pending_reload) { + ManagedCallable *managed_callable = elem.key; + const Array &serialized_data = elem.value; + + GCHandleIntPtr delegate = { nullptr }; + + bool success = GDMonoCache::managed_callbacks.DelegateUtils_TryDeserializeDelegateWithGCHandle( + &serialized_data, &delegate); + + if (success) { + ERR_CONTINUE(delegate.value == nullptr); + managed_callable->delegate_handle = delegate; + } else if (OS::get_singleton()->is_stdout_verbose()) { + OS::get_singleton()->print("Failed to deserialize delegate\n"); + } + } + + ManagedCallable::instances_pending_reload.clear(); + } + for (Ref &scr : to_reload_state) { for (const ObjectID &obj_id : scr->pending_reload_instances) { Object *obj = ObjectDB::get_instance(obj_id); @@ -963,7 +988,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { properties[G.first] = G.second; } - // Restore serialized state and call OnAfterDeserialization + // Restore serialized state and call OnAfterDeserialize. GDMonoCache::managed_callbacks.CSharpInstanceBridge_DeserializeState( csi->get_gchandle_intptr(), &properties, &state_backup.event_signals); } @@ -973,30 +998,6 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { scr->pending_reload_state.clear(); } - // Deserialize managed callables - { - MutexLock lock(ManagedCallable::instances_mutex); - - for (const KeyValue &elem : ManagedCallable::instances_pending_reload) { - ManagedCallable *managed_callable = elem.key; - const Array &serialized_data = elem.value; - - GCHandleIntPtr delegate = { nullptr }; - - bool success = GDMonoCache::managed_callbacks.DelegateUtils_TryDeserializeDelegateWithGCHandle( - &serialized_data, &delegate); - - if (success) { - ERR_CONTINUE(delegate.value == nullptr); - managed_callable->delegate_handle = delegate; - } else if (OS::get_singleton()->is_stdout_verbose()) { - OS::get_singleton()->print("Failed to deserialize delegate\n"); - } - } - - ManagedCallable::instances_pending_reload.clear(); - } - #ifdef TOOLS_ENABLED // FIXME: Hack to refresh editor in order to display new properties and signals. See if there is a better alternative. if (Engine::get_singleton()->is_editor_hint()) {