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.
This commit is contained in:
Marius Hanl 2024-04-04 00:14:49 +02:00
parent 29b3d9e9e5
commit dda06a8209

View file

@ -1561,10 +1561,42 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
}
void FileSystemDock::_update_resource_paths_after_move(const HashMap<String, String> &p_renames, const HashMap<String, ResourceUID::ID> &p_uids) const {
// Update the paths in ResourceUID, so that UIDs remain valid.
for (const KeyValue<String, ResourceUID::ID> &pair : p_uids) {
if (p_renames.has(pair.key)) {
ResourceUID::get_singleton()->set_id(pair.value, p_renames[pair.key]);
for (const KeyValue<String, String> &pair : p_renames) {
// Update UID path.
const String &old_path = pair.key;
const String &new_path = pair.value;
const HashMap<String, ResourceUID::ID>::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 HashMap<String, Str
if (p_renames.has(base_path)) {
base_path = p_renames[base_path];
r->set_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<String, String> &p_renames, const HashSet<String> &p_file_owners) const {
@ -1710,6 +1745,13 @@ void FileSystemDock::_make_scene_confirm() {
}
void FileSystemDock::_resource_removed(const Ref<Resource> &p_resource) {
const Ref<Script> &scr = p_resource;
if (scr.is_valid()) {
ScriptServer::remove_global_class_by_path(scr->get_path());
ScriptServer::save_global_classes();
EditorNode::get_editor_data().script_class_save_icon_paths();
EditorFileSystem::get_singleton()->emit_signal(SNAME("script_classes_updated"));
}
emit_signal(SNAME("resource_removed"), p_resource);
}