From 3ef69f0a79861c54ed283d9febca0c7729d7ec5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A3=8E=E9=9D=92=E5=B1=B1?= Date: Tue, 18 Mar 2025 10:30:15 +0800 Subject: [PATCH] Fix editor crash when inspecting 2 objects handled by the same plugin Already activated plugins do not need to be added again to `editor_plugins_over`. `fold_resource()` changes `active_plugins` and is unsafe to call while iterating over `active_plugins`. (cherry picked from commit 411f4763198b14d38db1afd296853996b2a5599a) --- editor/editor_node.cpp | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 7b4bceb1137..5a8c5619923 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2383,22 +2383,39 @@ void EditorNode::edit_item(Object *p_object, Object *p_editing_owner) { continue; } + bool need_to_add = true; + List to_fold; + // If plugin is already associated with another owner, remove it from there first. for (KeyValue> &kv : active_plugins) { - if (kv.key != owner_id) { - EditorPropertyResource *epres = Object::cast_to(ObjectDB::get_instance(kv.key)); - if (epres && kv.value.has(plugin)) { - // If it's resource property editing the same resource type, fold it. - epres->fold_resource(); - } - kv.value.erase(plugin); + if (kv.key == owner_id || !kv.value.has(plugin)) { + continue; } + EditorPropertyResource *epres = Object::cast_to(ObjectDB::get_instance(kv.key)); + if (epres) { + // If it's resource property editing the same resource type, fold it later to avoid premature modifications + // that may result in unsafe iteration of active_plugins. + to_fold.push_back(epres); + } else { + kv.value.erase(plugin); + need_to_add = false; + } + } + + if (!need_to_add && to_fold.is_empty()) { + plugin->make_visible(true); + plugin->edit(p_object); + } else { + for (EditorPropertyResource *epres : to_fold) { + epres->fold_resource(); + } + + // TODO: Call the function directly once a proper priority system is implemented. + to_over_edit.push_back(plugin); } // Activate previously inactive plugin and edit the object. active_plugins[owner_id].insert(plugin); - // TODO: Call the function directly once a proper priority system is implemented. - to_over_edit.push_back(plugin); } for (EditorPlugin *plugin : to_over_edit) {