diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 3adff84e40bd..37e00bf04287 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -1714,105 +1714,112 @@ HashSet EditorFileSystem::_get_scene_groups(const String &p_path) { void EditorFileSystem::update_file(const String &p_file) { ERR_FAIL_COND(p_file.is_empty()); - EditorFileSystemDirectory *fs = nullptr; - int cpos = -1; + update_files({ p_file }); +} - if (!_find_file(p_file, &fs, cpos)) { - if (!fs) { - return; +void EditorFileSystem::update_files(const Vector &p_script_paths) { + for (const String &file : p_script_paths) { + ERR_CONTINUE(file.is_empty()); + EditorFileSystemDirectory *fs = nullptr; + int cpos = -1; + + if (!_find_file(file, &fs, cpos)) { + if (!fs) { + return; + } } - } - if (!FileAccess::exists(p_file)) { - //was removed - _delete_internal_files(p_file); - if (cpos != -1) { // Might've never been part of the editor file system (*.* files deleted in Open dialog). - if (fs->files[cpos]->uid != ResourceUID::INVALID_ID) { - if (ResourceUID::get_singleton()->has_id(fs->files[cpos]->uid)) { - ResourceUID::get_singleton()->remove_id(fs->files[cpos]->uid); + if (!FileAccess::exists(file)) { + //was removed + _delete_internal_files(file); + if (cpos != -1) { // Might've never been part of the editor file system (*.* files deleted in Open dialog). + if (fs->files[cpos]->uid != ResourceUID::INVALID_ID) { + if (ResourceUID::get_singleton()->has_id(fs->files[cpos]->uid)) { + ResourceUID::get_singleton()->remove_id(fs->files[cpos]->uid); + } } - } - if (ClassDB::is_parent_class(fs->files[cpos]->type, SNAME("Script"))) { - _queue_update_script_class(p_file); - } - if (fs->files[cpos]->type == SNAME("PackedScene")) { - _queue_update_scene_groups(p_file); + if (ClassDB::is_parent_class(fs->files[cpos]->type, SNAME("Script"))) { + _queue_update_script_class(file); + } + if (fs->files[cpos]->type == SNAME("PackedScene")) { + _queue_update_scene_groups(file); + } + + memdelete(fs->files[cpos]); + fs->files.remove_at(cpos); } - memdelete(fs->files[cpos]); - fs->files.remove_at(cpos); + _update_pending_script_classes(); + _update_pending_scene_groups(); + call_deferred(SNAME("emit_signal"), "filesystem_changed"); //update later + return; } - _update_pending_script_classes(); - _update_pending_scene_groups(); - call_deferred(SNAME("emit_signal"), "filesystem_changed"); //update later - return; - } - - String type = ResourceLoader::get_resource_type(p_file); - if (type.is_empty() && textfile_extensions.has(p_file.get_extension())) { - type = "TextFile"; - } - String script_class = ResourceLoader::get_resource_script_class(p_file); + String type = ResourceLoader::get_resource_type(file); + if (type.is_empty() && textfile_extensions.has(file.get_extension())) { + type = "TextFile"; + } + String script_class = ResourceLoader::get_resource_script_class(file); - ResourceUID::ID uid = ResourceLoader::get_resource_uid(p_file); + ResourceUID::ID uid = ResourceLoader::get_resource_uid(file); - if (cpos == -1) { - // The file did not exist, it was added. - int idx = 0; - String file_name = p_file.get_file(); + if (cpos == -1) { + // The file did not exist, it was added. + int idx = 0; + String file_name = file.get_file(); - for (int i = 0; i < fs->files.size(); i++) { - if (p_file.filenocasecmp_to(fs->files[i]->file) < 0) { - break; + for (int i = 0; i < fs->files.size(); i++) { + if (file.filenocasecmp_to(fs->files[i]->file) < 0) { + break; + } + idx++; } - idx++; - } - EditorFileSystemDirectory::FileInfo *fi = memnew(EditorFileSystemDirectory::FileInfo); - fi->file = file_name; - fi->import_modified_time = 0; - fi->import_valid = type == "TextFile" ? true : ResourceLoader::is_import_valid(p_file); + EditorFileSystemDirectory::FileInfo *fi = memnew(EditorFileSystemDirectory::FileInfo); + fi->file = file_name; + fi->import_modified_time = 0; + fi->import_valid = type == "TextFile" ? true : ResourceLoader::is_import_valid(file); - if (idx == fs->files.size()) { - fs->files.push_back(fi); + if (idx == fs->files.size()) { + fs->files.push_back(fi); + } else { + fs->files.insert(idx, fi); + } + cpos = idx; } else { - fs->files.insert(idx, fi); + //the file exists and it was updated, and was not added in this step. + //this means we must force upon next restart to scan it again, to get proper type and dependencies + late_update_files.insert(file); + _save_late_updated_files(); //files need to be updated in the re-scan } - cpos = idx; - } else { - //the file exists and it was updated, and was not added in this step. - //this means we must force upon next restart to scan it again, to get proper type and dependencies - late_update_files.insert(p_file); - _save_late_updated_files(); //files need to be updated in the re-scan - } - fs->files[cpos]->type = type; - fs->files[cpos]->resource_script_class = script_class; - fs->files[cpos]->uid = uid; - fs->files[cpos]->script_class_name = _get_global_script_class(type, p_file, &fs->files[cpos]->script_class_extends, &fs->files[cpos]->script_class_icon_path); - fs->files[cpos]->import_group_file = ResourceLoader::get_import_group_file(p_file); - fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file); - fs->files[cpos]->deps = _get_dependencies(p_file); - fs->files[cpos]->import_valid = type == "TextFile" ? true : ResourceLoader::is_import_valid(p_file); + fs->files[cpos]->type = type; + fs->files[cpos]->resource_script_class = script_class; + fs->files[cpos]->uid = uid; + fs->files[cpos]->script_class_name = _get_global_script_class(type, file, &fs->files[cpos]->script_class_extends, &fs->files[cpos]->script_class_icon_path); + fs->files[cpos]->import_group_file = ResourceLoader::get_import_group_file(file); + fs->files[cpos]->modified_time = FileAccess::get_modified_time(file); + fs->files[cpos]->deps = _get_dependencies(file); + fs->files[cpos]->import_valid = type == "TextFile" ? true : ResourceLoader::is_import_valid(file); - if (uid != ResourceUID::INVALID_ID) { - if (ResourceUID::get_singleton()->has_id(uid)) { - ResourceUID::get_singleton()->set_id(uid, p_file); - } else { - ResourceUID::get_singleton()->add_id(uid, p_file); - } + if (uid != ResourceUID::INVALID_ID) { + if (ResourceUID::get_singleton()->has_id(uid)) { + ResourceUID::get_singleton()->set_id(uid, file); + } else { + ResourceUID::get_singleton()->add_id(uid, file); + } - ResourceUID::get_singleton()->update_cache(); - } - // Update preview - EditorResourcePreview::get_singleton()->check_for_invalidation(p_file); + ResourceUID::get_singleton()->update_cache(); + } + // Update preview + EditorResourcePreview::get_singleton()->check_for_invalidation(file); - if (ClassDB::is_parent_class(fs->files[cpos]->type, SNAME("Script"))) { - _queue_update_script_class(p_file); - } - if (fs->files[cpos]->type == SNAME("PackedScene")) { - _queue_update_scene_groups(p_file); + if (ClassDB::is_parent_class(fs->files[cpos]->type, SNAME("Script"))) { + _queue_update_script_class(file); + } + if (fs->files[cpos]->type == SNAME("PackedScene")) { + _queue_update_scene_groups(file); + } } _update_pending_script_classes(); diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index 84ae1e182c83..cd95d5fb9511 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -310,6 +310,7 @@ class EditorFileSystem : public Node { void scan(); void scan_changes(); void update_file(const String &p_file); + void update_files(const Vector &p_script_paths); HashSet get_valid_extensions() const; void register_global_class_script(const String &p_search_path, const String &p_target_path); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs index eef26cdd4e1b..5cc2a8026ebd 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs @@ -427,10 +427,11 @@ static void LookupScriptForClass(Type type) // This method may be called before initialization. if (NativeFuncs.godotsharp_dotnet_module_is_initialized().ToBool() && Engine.IsEditorHint()) { - foreach (var scriptPath in _pathTypeBiMap.Paths) + if (_pathTypeBiMap.Paths.Count > 0) { - using godot_string nativeScriptPath = Marshaling.ConvertStringToNative(scriptPath); - NativeFuncs.godotsharp_internal_editor_file_system_update_file(nativeScriptPath); + string[] scriptPaths = _pathTypeBiMap.Paths.ToArray(); + using godot_packed_string_array scriptPathsNative = Marshaling.ConvertSystemArrayToNativePackedStringArray(scriptPaths); + NativeFuncs.godotsharp_internal_editor_file_system_update_files(scriptPathsNative); } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.types.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.types.cs index 1ec1a7551626..29fa13d62599 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.types.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.types.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; @@ -64,7 +65,7 @@ private class PathScriptTypeBiMap private System.Collections.Generic.Dictionary _pathTypeMap = new(); private System.Collections.Generic.Dictionary _typePathMap = new(); - public System.Collections.Generic.IEnumerable Paths => _pathTypeMap.Keys; + public IReadOnlyCollection Paths => _pathTypeMap.Keys; public void Add(string scriptPath, Type scriptType) { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs index c4fd639ccedd..cfd9ed7acc2b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs @@ -59,7 +59,7 @@ internal static partial Error godotsharp_stack_info_vector_resize( internal static partial void godotsharp_stack_info_vector_destroy( ref DebuggingUtils.godot_stack_info_vector p_stack_info_vector); - internal static partial void godotsharp_internal_editor_file_system_update_file(in godot_string p_script_path); + internal static partial void godotsharp_internal_editor_file_system_update_files(in godot_packed_string_array p_script_paths); internal static partial void godotsharp_internal_script_debugger_send_error(in godot_string p_func, in godot_string p_file, int p_line, in godot_string p_err, in godot_string p_descr, diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp index 1af462dafd2e..80e9fdf77f5d 100644 --- a/modules/mono/glue/runtime_interop.cpp +++ b/modules/mono/glue/runtime_interop.cpp @@ -315,13 +315,13 @@ void godotsharp_internal_new_csharp_script(Ref *r_dest) { memnew_placement(r_dest, Ref(memnew(CSharpScript))); } -void godotsharp_internal_editor_file_system_update_file(const String *p_script_path) { +void godotsharp_internal_editor_file_system_update_files(const PackedStringArray &p_script_paths) { #ifdef TOOLS_ENABLED // If the EditorFileSystem singleton is available, update the file; // otherwise, the file will be updated when the singleton becomes available. EditorFileSystem *efs = EditorFileSystem::get_singleton(); if (efs) { - efs->update_file(*p_script_path); + efs->update_files(p_script_paths); } #else // EditorFileSystem is only available when running in the Godot editor. @@ -1450,7 +1450,7 @@ static const void *unmanaged_callbacks[]{ (void *)godotsharp_engine_get_singleton, (void *)godotsharp_stack_info_vector_resize, (void *)godotsharp_stack_info_vector_destroy, - (void *)godotsharp_internal_editor_file_system_update_file, + (void *)godotsharp_internal_editor_file_system_update_files, (void *)godotsharp_internal_script_debugger_send_error, (void *)godotsharp_internal_script_debugger_is_active, (void *)godotsharp_internal_object_get_associated_gchandle,