mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 13:41:03 +00:00 
			
		
		
		
	Merge pull request #28234 from Paulb23/connection_info_on_script
Display connection information in the script editor
This commit is contained in:
		
						commit
						22457b907e
					
				
					 8 changed files with 335 additions and 16 deletions
				
			
		|  | @ -35,6 +35,78 @@ | |||
| #include "editor/editor_settings.h" | ||||
| #include "editor/script_editor_debugger.h" | ||||
| 
 | ||||
| void ConnectionInfoDialog::ok_pressed() { | ||||
| } | ||||
| 
 | ||||
| void ConnectionInfoDialog::popup_connections(String p_method, Vector<Node *> p_nodes) { | ||||
| 	method->set_text(p_method); | ||||
| 
 | ||||
| 	tree->clear(); | ||||
| 	TreeItem *root = tree->create_item(); | ||||
| 
 | ||||
| 	for (int i = 0; i < p_nodes.size(); i++) { | ||||
| 		List<Connection> all_connections; | ||||
| 		p_nodes[i]->get_signals_connected_to_this(&all_connections); | ||||
| 
 | ||||
| 		for (List<Connection>::Element *E = all_connections.front(); E; E = E->next()) { | ||||
| 			Connection connection = E->get(); | ||||
| 
 | ||||
| 			if (connection.method != p_method) { | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			TreeItem *node_item = tree->create_item(root); | ||||
| 
 | ||||
| 			node_item->set_text(0, Object::cast_to<Node>(connection.source)->get_name()); | ||||
| 			node_item->set_icon(0, EditorNode::get_singleton()->get_object_icon(connection.source, "Node")); | ||||
| 			node_item->set_selectable(0, false); | ||||
| 			node_item->set_editable(0, false); | ||||
| 
 | ||||
| 			node_item->set_text(1, connection.signal); | ||||
| 			node_item->set_icon(1, get_parent_control()->get_icon("Slot", "EditorIcons")); | ||||
| 			node_item->set_selectable(1, false); | ||||
| 			node_item->set_editable(1, false); | ||||
| 
 | ||||
| 			node_item->set_text(2, Object::cast_to<Node>(connection.target)->get_name()); | ||||
| 			node_item->set_icon(2, EditorNode::get_singleton()->get_object_icon(connection.target, "Node")); | ||||
| 			node_item->set_selectable(2, false); | ||||
| 			node_item->set_editable(2, false); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	popup_centered(Size2(400, 300) * EDSCALE); | ||||
| } | ||||
| 
 | ||||
| ConnectionInfoDialog::ConnectionInfoDialog() { | ||||
| 	set_title(TTR("Connections to method:")); | ||||
| 	set_resizable(true); | ||||
| 
 | ||||
| 	VBoxContainer *vbc = memnew(VBoxContainer); | ||||
| 	vbc->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 8 * EDSCALE); | ||||
| 	vbc->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 8 * EDSCALE); | ||||
| 	vbc->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -8 * EDSCALE); | ||||
| 	vbc->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -8 * EDSCALE); | ||||
| 	add_child(vbc); | ||||
| 
 | ||||
| 	method = memnew(Label); | ||||
| 	method->set_text(""); | ||||
| 	method->set_align(Label::ALIGN_CENTER); | ||||
| 	vbc->add_child(method); | ||||
| 
 | ||||
| 	tree = memnew(Tree); | ||||
| 	tree->set_columns(3); | ||||
| 	tree->set_hide_root(true); | ||||
| 	tree->set_column_titles_visible(true); | ||||
| 	tree->set_column_title(0, TTR("Source")); | ||||
| 	tree->set_column_title(1, TTR("Signal")); | ||||
| 	tree->set_column_title(2, TTR("Target")); | ||||
| 	vbc->add_child(tree); | ||||
| 	tree->set_v_size_flags(SIZE_EXPAND_FILL); | ||||
| 	tree->set_allow_rmb_select(true); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| Vector<String> ScriptTextEditor::get_functions() { | ||||
| 
 | ||||
| 	String errortxt; | ||||
|  | @ -470,9 +542,32 @@ void ScriptTextEditor::_validate_script() { | |||
| 			functions.push_back(E->get()); | ||||
| 		} | ||||
| 	} | ||||
| 	_update_connected_methods(); | ||||
| 
 | ||||
| 	code_editor->set_warning_nb(warnings.size()); | ||||
| 	code_editor->set_warning_nb(missing_connections.size() + warnings.size()); | ||||
| 	warnings_panel->clear(); | ||||
| 
 | ||||
| 	// add missing connections
 | ||||
| 	Node *base = get_tree()->get_edited_scene_root(); | ||||
| 	if (base && missing_connections.size() > 0) { | ||||
| 		warnings_panel->push_table(1); | ||||
| 		for (List<Connection>::Element *E = missing_connections.front(); E; E = E->next()) { | ||||
| 			Connection connection = E->get(); | ||||
| 
 | ||||
| 			String base_path = base->get_name(); | ||||
| 			String source_path = base == connection.source ? base_path : base_path + "/" + String(base->get_path_to(Object::cast_to<Node>(connection.source))); | ||||
| 			String target_path = base == connection.target ? base_path : base_path + "/" + String(base->get_path_to(Object::cast_to<Node>(connection.target))); | ||||
| 
 | ||||
| 			warnings_panel->push_cell(); | ||||
| 			warnings_panel->push_color(warnings_panel->get_color("warning_color", "Editor")); | ||||
| 			warnings_panel->add_text(vformat(TTR("Missing connected method '%s' for signal '%s' from node '%s' to node '%s'"), connection.method, connection.signal, source_path, target_path)); | ||||
| 			warnings_panel->pop(); // Color
 | ||||
| 			warnings_panel->pop(); // Cell
 | ||||
| 		} | ||||
| 		warnings_panel->pop(); // Table
 | ||||
| 	} | ||||
| 
 | ||||
| 	// add script warnings
 | ||||
| 	warnings_panel->push_table(3); | ||||
| 	for (List<ScriptLanguage::Warning>::Element *E = warnings.front(); E; E = E->next()) { | ||||
| 		ScriptLanguage::Warning w = E->get(); | ||||
|  | @ -526,6 +621,27 @@ void ScriptTextEditor::_validate_script() { | |||
| 	emit_signal("edited_script_changed"); | ||||
| } | ||||
| 
 | ||||
| static Vector<Node *> _find_all_node_for_script(Node *p_base, Node *p_current, const Ref<Script> &p_script) { | ||||
| 
 | ||||
| 	Vector<Node *> nodes; | ||||
| 
 | ||||
| 	if (p_current->get_owner() != p_base && p_base != p_current) { | ||||
| 		return nodes; | ||||
| 	} | ||||
| 
 | ||||
| 	Ref<Script> c = p_current->get_script(); | ||||
| 	if (c == p_script) { | ||||
| 		nodes.push_back(p_current); | ||||
| 	} | ||||
| 
 | ||||
| 	for (int i = 0; i < p_current->get_child_count(); i++) { | ||||
| 		Vector<Node *> found = _find_all_node_for_script(p_base, p_current->get_child(i), p_script); | ||||
| 		nodes.append_array(found); | ||||
| 	} | ||||
| 
 | ||||
| 	return nodes; | ||||
| } | ||||
| 
 | ||||
| static Node *_find_node_for_script(Node *p_base, Node *p_current, const Ref<Script> &p_script) { | ||||
| 
 | ||||
| 	if (p_current->get_owner() != p_base && p_base != p_current) | ||||
|  | @ -721,6 +837,47 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| void ScriptTextEditor::_update_connected_methods() { | ||||
| 	TextEdit *text_edit = code_editor->get_text_edit(); | ||||
| 	text_edit->clear_info_icons(); | ||||
| 	missing_connections.clear(); | ||||
| 
 | ||||
| 	Node *base = get_tree()->get_edited_scene_root(); | ||||
| 	if (!base) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	Vector<Node *> nodes = _find_all_node_for_script(base, base, script); | ||||
| 	for (int i = 0; i < nodes.size(); i++) { | ||||
| 		List<Connection> connections; | ||||
| 		nodes[i]->get_signals_connected_to_this(&connections); | ||||
| 
 | ||||
| 		for (List<Connection>::Element *E = connections.front(); E; E = E->next()) { | ||||
| 			Connection connection = E->get(); | ||||
| 			if (!(connection.flags & CONNECT_PERSIST)) { | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			int line = script->get_language()->find_function(connection.method, text_edit->get_text()); | ||||
| 			if (line < 0) { | ||||
| 				missing_connections.push_back(connection); | ||||
| 				continue; | ||||
| 			} | ||||
| 			text_edit->set_line_info_icon(line - 1, get_parent_control()->get_icon("Slot", "EditorIcons"), connection.method); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void ScriptTextEditor::_lookup_connections(int p_row, String p_method) { | ||||
| 	Node *base = get_tree()->get_edited_scene_root(); | ||||
| 	if (!base) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	Vector<Node *> nodes = _find_all_node_for_script(base, base, script); | ||||
| 	connection_info_dialog->popup_connections(p_method, nodes); | ||||
| } | ||||
| 
 | ||||
| void ScriptTextEditor::_edit_option(int p_op) { | ||||
| 
 | ||||
| 	TextEdit *tx = code_editor->get_text_edit(); | ||||
|  | @ -1040,6 +1197,8 @@ void ScriptTextEditor::_bind_methods() { | |||
| 	ClassDB::bind_method("_validate_script", &ScriptTextEditor::_validate_script); | ||||
| 	ClassDB::bind_method("_load_theme_settings", &ScriptTextEditor::_load_theme_settings); | ||||
| 	ClassDB::bind_method("_breakpoint_toggled", &ScriptTextEditor::_breakpoint_toggled); | ||||
| 	ClassDB::bind_method("_lookup_connections", &ScriptTextEditor::_lookup_connections); | ||||
| 	ClassDB::bind_method("_update_connected_methods", &ScriptTextEditor::_update_connected_methods); | ||||
| 	ClassDB::bind_method("_change_syntax_highlighter", &ScriptTextEditor::_change_syntax_highlighter); | ||||
| 	ClassDB::bind_method("_edit_option", &ScriptTextEditor::_edit_option); | ||||
| 	ClassDB::bind_method("_goto_line", &ScriptTextEditor::_goto_line); | ||||
|  | @ -1372,6 +1531,7 @@ ScriptTextEditor::ScriptTextEditor() { | |||
| 	code_editor->set_code_complete_func(_code_complete_scripts, this); | ||||
| 	code_editor->get_text_edit()->connect("breakpoint_toggled", this, "_breakpoint_toggled"); | ||||
| 	code_editor->get_text_edit()->connect("symbol_lookup", this, "_lookup_symbol"); | ||||
| 	code_editor->get_text_edit()->connect("info_clicked", this, "_lookup_connections"); | ||||
| 	code_editor->set_v_size_flags(SIZE_EXPAND_FILL); | ||||
| 
 | ||||
| 	warnings_panel = memnew(RichTextLabel); | ||||
|  | @ -1492,6 +1652,9 @@ ScriptTextEditor::ScriptTextEditor() { | |||
| 	goto_line_dialog = memnew(GotoLineDialog); | ||||
| 	add_child(goto_line_dialog); | ||||
| 
 | ||||
| 	connection_info_dialog = memnew(ConnectionInfoDialog); | ||||
| 	add_child(connection_info_dialog); | ||||
| 
 | ||||
| 	code_editor->get_text_edit()->set_drag_forwarding(this); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Rémi Verschelde
						Rémi Verschelde