From dda06a82099b056058379d2423e0d5b16375b52d Mon Sep 17 00:00:00 2001 From: Marius Hanl Date: Thu, 4 Apr 2024 00:14:49 +0200 Subject: [PATCH] Fix errors when renaming/moving/deleting global scripts When renaming or moving global scripts, the following errors can appear: - Attempt to open script 'xxx' resulted in error 'File not found'. - Failed loading resource: xxx. Make sure resources have been imported by opening the project in the editor at least once. - Parser Error: Class 'xxx' hides a global script class. When deleting scripts, errors appear when opening the 'Create Node Dialog' as the script cache still contains the removed global scripts. The following errors can appear: - Attempt to open script 'xxx' resulted in error 'File not found'. - Failed loading resource: xxx. Make sure resources have been imported by opening the project in the editor at least once. editor/create_dialog.cpp:241 - Condition "scr.is_null()" is true. All this errors can be fixed by correctly handling the cases. They involves removing the old path and adding the new one (if not deleted) to the ScriptServer. This is somewhat similar if the file is moved or deleted outside Godot and detected by the file watcher, but more specialized for this particular usecase, since we know the old and the new path / correctly know what the user just did. --- editor/filesystem_dock.cpp | 54 +++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 4521f4d3ff2e..bb92cfb0b4c8 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1561,10 +1561,42 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin } void FileSystemDock::_update_resource_paths_after_move(const HashMap &p_renames, const HashMap &p_uids) const { - // Update the paths in ResourceUID, so that UIDs remain valid. - for (const KeyValue &pair : p_uids) { - if (p_renames.has(pair.key)) { - ResourceUID::get_singleton()->set_id(pair.value, p_renames[pair.key]); + for (const KeyValue &pair : p_renames) { + // Update UID path. + const String &old_path = pair.key; + const String &new_path = pair.value; + + const HashMap::ConstIterator I = p_uids.find(old_path); + if (I) { + ResourceUID::get_singleton()->set_id(I->value, new_path); + } + + ScriptServer::remove_global_class_by_path(old_path); + + int index = -1; + EditorFileSystemDirectory *efd = EditorFileSystem::get_singleton()->find_file(old_path, &index); + + if (!efd || index < 0) { + // The file was removed. + continue; + } + + // Update paths for global classes. + if (!efd->get_file_script_class_name(index).is_empty()) { + String lang; + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + if (ScriptServer::get_language(i)->handles_global_class_type(efd->get_file_type(index))) { + lang = ScriptServer::get_language(i)->get_name(); + break; + } + } + if (lang.is_empty()) { + continue; // No language found that can handle this global class. + } + + ScriptServer::add_global_class(efd->get_file_script_class_name(index), efd->get_file_script_class_extends(index), lang, new_path); + EditorNode::get_editor_data().script_class_set_icon_path(efd->get_file_script_class_name(index), efd->get_file_script_class_icon_path(index)); + EditorNode::get_editor_data().script_class_set_name(new_path, efd->get_file_script_class_name(index)); } } @@ -1583,10 +1615,13 @@ void FileSystemDock::_update_resource_paths_after_move(const HashMapset_path(base_path + extra_path); } - - r->set_path(base_path + extra_path); } + + ScriptServer::save_global_classes(); + EditorNode::get_editor_data().script_class_save_icon_paths(); + EditorFileSystem::get_singleton()->emit_signal(SNAME("script_classes_updated")); } void FileSystemDock::_update_dependencies_after_move(const HashMap &p_renames, const HashSet &p_file_owners) const { @@ -1710,6 +1745,13 @@ void FileSystemDock::_make_scene_confirm() { } void FileSystemDock::_resource_removed(const Ref &p_resource) { + const Ref