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 411f476319)
This commit is contained in:
风青山 2025-03-18 10:30:15 +08:00 committed by Rémi Verschelde
parent 00baf18d6e
commit 3ef69f0a79
No known key found for this signature in database
GPG key ID: C3336907360768E1

View file

@ -2383,22 +2383,39 @@ void EditorNode::edit_item(Object *p_object, Object *p_editing_owner) {
continue;
}
bool need_to_add = true;
List<EditorPropertyResource *> to_fold;
// If plugin is already associated with another owner, remove it from there first.
for (KeyValue<ObjectID, HashSet<EditorPlugin *>> &kv : active_plugins) {
if (kv.key != owner_id) {
EditorPropertyResource *epres = Object::cast_to<EditorPropertyResource>(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<EditorPropertyResource>(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) {