瀏覽代碼

Fix reloading scripts already in use

Hilderin 11 月之前
父節點
當前提交
9638220473

+ 11 - 1
core/object/script_language.cpp

@@ -191,7 +191,17 @@ void Script::reload_from_file() {
 	set_source_code(rel->get_source_code());
 	set_source_code(rel->get_source_code());
 	set_last_modified_time(rel->get_last_modified_time());
 	set_last_modified_time(rel->get_last_modified_time());
 
 
-	reload();
+	// Only reload the script when there are no compilation errors to prevent printing the error messages twice.
+	if (rel->is_valid()) {
+		if (Engine::get_singleton()->is_editor_hint() && is_tool()) {
+			get_language()->reload_tool_script(this, true);
+		} else {
+			// It's important to set p_keep_state to true in order to manage reloading scripts
+			// that are currently instantiated.
+			reload(true);
+		}
+	}
+
 #else
 #else
 	Resource::reload_from_file();
 	Resource::reload_from_file();
 #endif
 #endif

+ 4 - 1
core/object/script_language.h

@@ -112,7 +112,10 @@ class Script : public Resource {
 	OBJ_SAVE_TYPE(Script);
 	OBJ_SAVE_TYPE(Script);
 
 
 protected:
 protected:
-	virtual bool editor_can_reload_from_file() override { return false; } // this is handled by editor better
+	// Scripts are reloaded via the Script Editor when edited in Godot,
+	// the LSP server when edited in a connected external editor, or
+	// through EditorFileSystem::_update_script_documentation when updated directly on disk.
+	virtual bool editor_can_reload_from_file() override { return false; }
 	void _notification(int p_what);
 	void _notification(int p_what);
 	static void _bind_methods();
 	static void _bind_methods();
 
 

+ 25 - 8
editor/editor_file_system.cpp

@@ -1973,18 +1973,16 @@ void EditorFileSystem::_update_script_documentation() {
 		for (int i = 0; i < ScriptServer::get_language_count(); i++) {
 		for (int i = 0; i < ScriptServer::get_language_count(); i++) {
 			ScriptLanguage *lang = ScriptServer::get_language(i);
 			ScriptLanguage *lang = ScriptServer::get_language(i);
 			if (lang->supports_documentation() && efd->files[index]->type == lang->get_type()) {
 			if (lang->supports_documentation() && efd->files[index]->type == lang->get_type()) {
-				// Reloading the script from disk if resource already in memory. Otherwise, the
-				// ResourceLoader::load will return the last loaded version of the script (without the modifications).
-				// The only have the script already loaded here is to edit the script outside the
-				// editor without being connected to the LSP server.
-				Ref<Resource> res = ResourceCache::get_ref(path);
-				if (res.is_valid()) {
-					res->reload_from_file();
-				}
+				bool should_reload_script = _should_reload_script(path);
 				Ref<Script> scr = ResourceLoader::load(path);
 				Ref<Script> scr = ResourceLoader::load(path);
 				if (scr.is_null()) {
 				if (scr.is_null()) {
 					continue;
 					continue;
 				}
 				}
+				if (should_reload_script) {
+					// Reloading the script from disk. Otherwise, the ResourceLoader::load will
+					// return the last loaded version of the script (without the modifications).
+					scr->reload_from_file();
+				}
 				Vector<DocData::ClassDoc> docs = scr->get_documentation();
 				Vector<DocData::ClassDoc> docs = scr->get_documentation();
 				for (int j = 0; j < docs.size(); j++) {
 				for (int j = 0; j < docs.size(); j++) {
 					EditorHelp::get_doc_data()->add_doc(docs[j]);
 					EditorHelp::get_doc_data()->add_doc(docs[j]);
@@ -2006,6 +2004,25 @@ void EditorFileSystem::_update_script_documentation() {
 	update_script_paths_documentation.clear();
 	update_script_paths_documentation.clear();
 }
 }
 
 
+bool EditorFileSystem::_should_reload_script(const String &p_path) {
+	if (first_scan) {
+		return false;
+	}
+
+	Ref<Script> scr = ResourceCache::get_ref(p_path);
+	if (scr.is_null()) {
+		// Not a script or not already loaded.
+		return false;
+	}
+
+	// Scripts are reloaded via the script editor if they are currently opened.
+	if (ScriptEditor::get_singleton()->get_open_scripts().has(scr)) {
+		return false;
+	}
+
+	return true;
+}
+
 void EditorFileSystem::_process_update_pending() {
 void EditorFileSystem::_process_update_pending() {
 	_update_script_classes();
 	_update_script_classes();
 	// Parse documentation second, as it requires the class names to be loaded
 	// Parse documentation second, as it requires the class names to be loaded

+ 1 - 0
editor/editor_file_system.h

@@ -295,6 +295,7 @@ class EditorFileSystem : public Node {
 	void _update_script_documentation();
 	void _update_script_documentation();
 	void _process_update_pending();
 	void _process_update_pending();
 	void _process_removed_files(const HashSet<String> &p_processed_files);
 	void _process_removed_files(const HashSet<String> &p_processed_files);
+	bool _should_reload_script(const String &p_path);
 
 
 	Mutex update_scene_mutex;
 	Mutex update_scene_mutex;
 	HashSet<String> update_scene_paths;
 	HashSet<String> update_scene_paths;

+ 1 - 5
editor/editor_node.cpp

@@ -926,11 +926,7 @@ void EditorNode::_resources_changed(const Vector<String> &p_resources) {
 		}
 		}
 
 
 		if (!res->editor_can_reload_from_file()) {
 		if (!res->editor_can_reload_from_file()) {
-			Ref<Script> scr = res;
-			// Scripts are reloaded via the script editor.
-			if (scr.is_null() || ScriptEditor::get_singleton()->get_open_scripts().has(scr)) {
-				continue;
-			}
+			continue;
 		}
 		}
 		if (!res->get_path().is_resource_file() && !res->get_path().is_absolute_path()) {
 		if (!res->get_path().is_resource_file() && !res->get_path().is_absolute_path()) {
 			continue;
 			continue;

+ 1 - 1
editor/plugins/script_editor_plugin.cpp

@@ -1483,7 +1483,7 @@ void ScriptEditor::_menu_option(int p_option) {
 
 
 				current->apply_code();
 				current->apply_code();
 
 
-				Error err = scr->reload(false); // Always hard reload the script before running.
+				Error err = scr->reload(true); // Always hard reload the script before running.
 				if (err != OK || !scr->is_valid()) {
 				if (err != OK || !scr->is_valid()) {
 					EditorToaster::get_singleton()->popup_str(TTR("Cannot run the script because it contains errors, check the output log."), EditorToaster::SEVERITY_WARNING);
 					EditorToaster::get_singleton()->popup_str(TTR("Cannot run the script because it contains errors, check the output log."), EditorToaster::SEVERITY_WARNING);
 					return;
 					return;