Browse Source

Editor: Fix documentation for built-in scripts

Danil Alexeev 2 months ago
parent
commit
0a07ae7bf1

+ 1 - 1
editor/connections_dialog.cpp

@@ -924,7 +924,7 @@ ConnectDialog::~ConnectDialog() {
 
 Control *ConnectionsDockTree::make_custom_tooltip(const String &p_text) const {
 	// If it's not a doc tooltip, fallback to the default one.
-	if (p_text.is_empty() || p_text.contains("::")) {
+	if (p_text.is_empty() || p_text.contains(" :: ")) {
 		return nullptr;
 	}
 

+ 24 - 1
editor/editor_file_system.cpp

@@ -1385,7 +1385,7 @@ void EditorFileSystem::_process_file_system(const ScannedDirectory *p_scan_dir,
 void EditorFileSystem::_process_removed_files(const HashSet<String> &p_processed_files) {
 	for (const KeyValue<String, EditorFileSystem::FileCache> &kv : file_cache) {
 		if (!p_processed_files.has(kv.key)) {
-			if (ClassDB::is_parent_class(kv.value.type, SNAME("Script"))) {
+			if (ClassDB::is_parent_class(kv.value.type, SNAME("Script")) || ClassDB::is_parent_class(kv.value.type, SNAME("PackedScene"))) {
 				// A script has been removed from disk since the last startup. The documentation needs to be updated.
 				// There's no need to add the path in update_script_paths since that is exclusively for updating global class names,
 				// which is handled in _first_scan_filesystem before the full scan to ensure plugins and autoloads can be created.
@@ -2195,6 +2195,29 @@ void EditorFileSystem::_update_script_documentation() {
 			continue;
 		}
 
+		if (path.ends_with(".tscn")) {
+			Ref<PackedScene> packed_scene = ResourceLoader::load(path);
+			if (packed_scene.is_valid()) {
+				Ref<SceneState> state = packed_scene->get_state();
+				if (state.is_valid()) {
+					Vector<Ref<Resource>> sub_resources = state->get_sub_resources();
+					for (Ref<Resource> sub_resource : sub_resources) {
+						Ref<Script> scr = sub_resource;
+						if (scr.is_valid()) {
+							for (const DocData::ClassDoc &cd : scr->get_documentation()) {
+								EditorHelp::add_doc(cd);
+								if (!first_scan) {
+									// Update the documentation in the Script Editor if it is open.
+									ScriptEditor::get_singleton()->update_doc(cd.name);
+								}
+							}
+						}
+					}
+				}
+			}
+			continue;
+		}
+
 		for (int i = 0; i < ScriptServer::get_language_count(); i++) {
 			ScriptLanguage *lang = ScriptServer::get_language(i);
 			if (lang->supports_documentation() && efd->files[index]->type == lang->get_type()) {

+ 24 - 5
editor/editor_help.cpp

@@ -2316,13 +2316,32 @@ void EditorHelp::_request_help(const String &p_string) {
 }
 
 void EditorHelp::_help_callback(const String &p_topic) {
-	String what = p_topic.get_slicec(':', 0);
-	String clss = p_topic.get_slicec(':', 1);
-	String name;
-	if (p_topic.get_slice_count(":") == 3) {
-		name = p_topic.get_slicec(':', 2);
+	Vector<String> parts;
+	{
+		int from = 0;
+		int buffer_start = 0;
+		while (true) {
+			const int pos = p_topic.find_char(':', from);
+			if (pos < 0) {
+				parts.push_back(p_topic.substr(buffer_start));
+				break;
+			}
+
+			if (pos + 1 < p_topic.length() && p_topic[pos + 1] == ':') {
+				// `::` used in built-in scripts.
+				from = pos + 2;
+			} else {
+				parts.push_back(p_topic.substr(buffer_start, pos - buffer_start));
+				from = pos + 1;
+				buffer_start = from;
+			}
+		}
 	}
 
+	const String what = parts[0]; // `parts` is always non-empty.
+	const String clss = (parts.size() > 1) ? parts[1] : String();
+	const String name = (parts.size() > 2) ? parts[2] : String();
+
 	_request_help(clss); // First go to class.
 
 	int line = 0;

+ 17 - 17
editor/plugins/script_editor_plugin.cpp

@@ -1009,7 +1009,7 @@ void ScriptEditor::_resave_scripts(const String &p_str) {
 		Ref<Resource> scr = se->get_edited_resource();
 
 		if (scr->is_built_in()) {
-			continue; //internal script, who cares
+			continue; // Internal script, who cares.
 		}
 
 		if (trim_trailing_whitespace_on_save) {
@@ -1089,10 +1089,9 @@ void ScriptEditor::_mark_built_in_scripts_as_saved(const String &p_parent_path)
 		Ref<Script> scr = edited_res;
 		if (scr.is_valid()) {
 			trigger_live_script_reload(scr->get_path());
-
-			if (scr->is_tool()) {
-				scr->reload(true);
-			}
+			clear_docs_from_script(scr);
+			scr->reload(true);
+			update_docs_from_script(scr);
 		}
 	}
 }
@@ -1143,7 +1142,7 @@ bool ScriptEditor::_test_script_times_on_disk(Ref<Resource> p_for_script) {
 			}
 
 			if (edited_res->is_built_in()) {
-				continue; //internal script, who cares
+				continue; // Internal script, who cares.
 			}
 
 			uint64_t last_date = se->edited_file_data.last_modified_time;
@@ -2722,24 +2721,21 @@ void ScriptEditor::save_all_scripts() {
 			se->apply_code();
 		}
 
+		Ref<Script> scr = edited_res;
+
+		if (scr.is_valid()) {
+			clear_docs_from_script(scr);
+		}
+
 		if (!edited_res->is_built_in()) {
 			Ref<TextFile> text_file = edited_res;
-			Ref<Script> scr = edited_res;
-
 			if (text_file.is_valid()) {
 				_save_text_file(text_file, text_file->get_path());
 				continue;
 			}
 
-			if (scr.is_valid()) {
-				clear_docs_from_script(scr);
-			}
-
-			EditorNode::get_singleton()->save_resource(edited_res); //external script, save it
-
-			if (scr.is_valid()) {
-				update_docs_from_script(scr);
-			}
+			// External script, save it.
+			EditorNode::get_singleton()->save_resource(edited_res);
 		} else {
 			// For built-in scripts, save their scenes instead.
 			const String scene_path = edited_res->get_path().get_slice("::", 0);
@@ -2747,6 +2743,10 @@ void ScriptEditor::save_all_scripts() {
 				scenes_to_save.insert(scene_path);
 			}
 		}
+
+		if (scr.is_valid()) {
+			update_docs_from_script(scr);
+		}
 	}
 
 	if (!scenes_to_save.is_empty()) {

+ 12 - 0
scene/resources/packed_scene.cpp

@@ -1963,6 +1963,18 @@ Ref<Resource> SceneState::get_sub_resource(const String &p_path) {
 	return Ref<Resource>();
 }
 
+Vector<Ref<Resource>> SceneState::get_sub_resources() {
+	const String path_prefix = get_path() + "::";
+	Vector<Ref<Resource>> sub_resources;
+	for (const Variant &v : variants) {
+		const Ref<Resource> &res = v;
+		if (res.is_valid() && res->get_path().begins_with(path_prefix)) {
+			sub_resources.push_back(res);
+		}
+	}
+	return sub_resources;
+}
+
 //add
 
 int SceneState::add_name(const StringName &p_name) {

+ 1 - 0
scene/resources/packed_scene.h

@@ -196,6 +196,7 @@ public:
 
 	Vector<NodePath> get_editable_instances() const;
 	Ref<Resource> get_sub_resource(const String &p_path);
+	Vector<Ref<Resource>> get_sub_resources();
 
 	//build API