Kaynağa Gözat

Visualscript editor graph unification & refactoring

Removes the need to have separate graphs per function for the VisualScript Nodes, and refactoring UI and other improvements such as fuzzy search, right click search boxes and in-graph editable nodes
Swarnim Arun 5 yıl önce
ebeveyn
işleme
59738e3fa3

+ 15 - 0
modules/visual_script/doc_classes/VisualScriptComposeArray.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualScriptComposeArray" inherits="VisualScriptLists" category="Core" version="3.2">
+	<brief_description>
+		A Visual Script Node used to create array from a list of items.
+	</brief_description>
+	<description>
+		A Visual Script Node used to compose array from the list of elements provided with custom in-graph UI hard coded in the VisualScript Editor.
+	</description>
+	<tutorials>
+	</tutorials>
+	<methods>
+	</methods>
+	<constants>
+	</constants>
+</class>

+ 95 - 0
modules/visual_script/doc_classes/VisualScriptLists.xml

@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualScriptLists" inherits="VisualScriptNode" category="Core" version="3.2">
+	<brief_description>
+		A Visual Script virtual class for in-graph editable nodes.
+	</brief_description>
+	<description>
+		A Visual Script virtual class that defines the shape and the default behaviour of the nodes that have to be in-graph editable nodes.
+	</description>
+	<tutorials>
+	</tutorials>
+	<methods>
+		<method name="add_input_data_port">
+			<return type="void">
+			</return>
+			<argument index="0" name="p_type" type="int" enum="Variant.Type">
+			</argument>
+			<argument index="1" name="p_name" type="String">
+			</argument>
+			<argument index="2" name="p_index" type="int">
+			</argument>
+			<description>
+			</description>
+		</method>
+		<method name="add_output_data_port">
+			<return type="void">
+			</return>
+			<argument index="0" name="p_type" type="int" enum="Variant.Type">
+			</argument>
+			<argument index="1" name="p_name" type="String">
+			</argument>
+			<argument index="2" name="p_index" type="int">
+			</argument>
+			<description>
+			</description>
+		</method>
+		<method name="remove_input_data_port">
+			<return type="void">
+			</return>
+			<argument index="0" name="p_index" type="int">
+			</argument>
+			<description>
+			</description>
+		</method>
+		<method name="remove_output_data_port">
+			<return type="void">
+			</return>
+			<argument index="0" name="p_index" type="int">
+			</argument>
+			<description>
+			</description>
+		</method>
+		<method name="set_input_data_port_name">
+			<return type="void">
+			</return>
+			<argument index="0" name="p_index" type="int">
+			</argument>
+			<argument index="1" name="p_name" type="String">
+			</argument>
+			<description>
+			</description>
+		</method>
+		<method name="set_input_data_port_type">
+			<return type="void">
+			</return>
+			<argument index="0" name="p_index" type="int">
+			</argument>
+			<argument index="1" name="p_type" type="int" enum="Variant.Type">
+			</argument>
+			<description>
+			</description>
+		</method>
+		<method name="set_output_data_port_name">
+			<return type="void">
+			</return>
+			<argument index="0" name="p_index" type="int">
+			</argument>
+			<argument index="1" name="p_name" type="String">
+			</argument>
+			<description>
+			</description>
+		</method>
+		<method name="set_output_data_port_type">
+			<return type="void">
+			</return>
+			<argument index="0" name="p_index" type="int">
+			</argument>
+			<argument index="1" name="p_type" type="int" enum="Variant.Type">
+			</argument>
+			<description>
+			</description>
+		</method>
+	</methods>
+	<constants>
+	</constants>
+</class>

+ 2 - 0
modules/visual_script/register_types.cpp

@@ -56,6 +56,8 @@ void register_visual_script_types() {
 	ClassDB::register_virtual_class<VisualScriptNode>();
 	ClassDB::register_class<VisualScriptFunctionState>();
 	ClassDB::register_class<VisualScriptFunction>();
+	ClassDB::register_virtual_class<VisualScriptLists>();
+	ClassDB::register_class<VisualScriptComposeArray>();
 	ClassDB::register_class<VisualScriptOperator>();
 	ClassDB::register_class<VisualScriptVariableSet>();
 	ClassDB::register_class<VisualScriptVariableGet>();

+ 59 - 10
modules/visual_script/visual_script.cpp

@@ -1014,17 +1014,16 @@ void VisualScript::get_script_method_list(List<MethodInfo> *p_list) const {
 
 			Ref<VisualScriptFunction> func = E->get().nodes[E->get().function_id].node;
 			if (func.is_valid()) {
-
 				for (int i = 0; i < func->get_argument_count(); i++) {
 					PropertyInfo arg;
 					arg.name = func->get_argument_name(i);
 					arg.type = func->get_argument_type(i);
 					mi.arguments.push_back(arg);
 				}
+
+				p_list->push_back(mi);
 			}
 		}
-
-		p_list->push_back(mi);
 	}
 }
 
@@ -1137,6 +1136,9 @@ void VisualScript::_set_data(const Dictionary &p_data) {
 	Array funcs = d["functions"];
 	functions.clear();
 
+	Vector2 last_pos = Vector2(-100 * funcs.size(), -100 * funcs.size()); // this is the center of the last fn box
+	Vector2 last_size = Vector2(0.0, 0.0);
+
 	for (int i = 0; i < funcs.size(); i++) {
 
 		Dictionary func = funcs[i];
@@ -1149,11 +1151,42 @@ void VisualScript::_set_data(const Dictionary &p_data) {
 
 		Array nodes = func["nodes"];
 
-		for (int j = 0; j < nodes.size(); j += 3) {
+		if (!d.has("vs_unify") && nodes.size() > 0) {
+			Vector2 top_left = nodes[1];
+			Vector2 bottom_right = nodes[1];
 
-			add_node(name, nodes[j], nodes[j + 2], nodes[j + 1]);
-		}
+			for (int j = 0; j < nodes.size(); j += 3) {
+				Point2 pos = nodes[j + 1];
+				if (pos.y > top_left.y) {
+					top_left.y = pos.y;
+				}
+				if (pos.y < bottom_right.y) {
+					bottom_right.y = pos.y;
+				}
+				if (pos.x > bottom_right.x) {
+					bottom_right.x = pos.x;
+				}
+				if (pos.x < top_left.x) {
+					top_left.x = pos.x;
+				}
+			}
+
+			Vector2 size = Vector2(bottom_right.x - top_left.x, top_left.y - bottom_right.y);
+
+			Vector2 offset = last_pos + (last_size / 2.0) + (size / 2.0); // dunno I might just keep it in one axis but diagonal feels better....
 
+			last_pos = offset;
+			last_size = size;
+
+			for (int j = 0; j < nodes.size(); j += 3) {
+				add_node(name, nodes[j], nodes[j + 2], offset + nodes[j + 1]); // also add an additional buffer if you want to
+			}
+
+		} else {
+			for (int j = 0; j < nodes.size(); j += 3) {
+				add_node(name, nodes[j], nodes[j + 2], nodes[j + 1]);
+			}
+		}
 		Array sequence_connections = func["sequence_connections"];
 
 		for (int j = 0; j < sequence_connections.size(); j += 3) {
@@ -1254,8 +1287,8 @@ Dictionary VisualScript::_get_data() const {
 	}
 
 	d["functions"] = funcs;
-
 	d["is_tool_script"] = is_tool_script;
+	d["vs_unify"] = true;
 
 	return d;
 }
@@ -1330,6 +1363,10 @@ VisualScript::VisualScript() {
 	base_type = "Object";
 }
 
+StringName VisualScript::get_default_func() const {
+	return StringName("f_312843592");
+}
+
 Set<int> VisualScript::get_output_sequence_ports_connected(const String &edited_func, int from_node) {
 	List<VisualScript::SequenceConnection> *sc = memnew(List<VisualScript::SequenceConnection>);
 	get_sequence_connection_list(edited_func, sc);
@@ -1403,6 +1440,10 @@ void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
 
 	for (const Map<StringName, VisualScript::Function>::Element *E = script->functions.front(); E; E = E->next()) {
 
+		if (E->key() == script->get_default_func()) {
+			continue;
+		}
+
 		MethodInfo mi;
 		mi.name = E->key();
 		if (E->get().function_id >= 0 && E->get().nodes.has(E->get().function_id)) {
@@ -1421,8 +1462,6 @@ void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
 				if (!vsf->is_sequenced()) { //assumed constant if not sequenced
 					mi.flags |= METHOD_FLAG_CONST;
 				}
-
-				//vsf->Get_ for now at least it does not return..
 			}
 		}
 
@@ -1431,6 +1470,9 @@ void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
 }
 bool VisualScriptInstance::has_method(const StringName &p_method) const {
 
+	if (p_method == script->get_default_func())
+		return false;
+
 	return script->functions.has(p_method);
 }
 
@@ -2002,6 +2044,9 @@ Ref<Script> VisualScriptInstance::get_script() const {
 
 MultiplayerAPI::RPCMode VisualScriptInstance::get_rpc_mode(const StringName &p_method) const {
 
+	if (p_method == script->get_default_func())
+		return MultiplayerAPI::RPC_MODE_DISABLED;
+
 	const Map<StringName, VisualScript::Function>::Element *E = script->functions.find(p_method);
 	if (!E) {
 		return MultiplayerAPI::RPC_MODE_DISABLED;
@@ -2050,11 +2095,14 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
 
 	for (const Map<StringName, VisualScript::Variable>::Element *E = script->variables.front(); E; E = E->next()) {
 		variables[E->key()] = E->get().default_value;
-		//no hacer que todo exporte, solo las que queres!
 	}
 
 	for (const Map<StringName, VisualScript::Function>::Element *E = script->functions.front(); E; E = E->next()) {
 
+		if (E->key() == script->get_default_func()) {
+			continue;
+		}
+
 		Function function;
 		function.node = E->get().function_id;
 		function.max_stack = 0;
@@ -2091,6 +2139,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
 		for (const Map<int, VisualScript::Function::NodeData>::Element *F = E->get().nodes.front(); F; F = F->next()) {
 
 			Ref<VisualScriptNode> node = F->get().node;
+
 			VisualScriptNodeInstance *instance = node->instance(this); //create instance
 			ERR_FAIL_COND(!instance);
 

+ 3 - 0
modules/visual_script/visual_script.h

@@ -239,6 +239,7 @@ private:
 		PropertyInfo info;
 		Variant default_value;
 		bool _export;
+		// add getter & setter options here
 	};
 
 	Map<StringName, Function> functions;
@@ -267,6 +268,8 @@ protected:
 	static void _bind_methods();
 
 public:
+	// TODO: Remove it in future when breaking changes are acceptable
+	StringName get_default_func() const;
 	void add_function(const StringName &p_name);
 	bool has_function(const StringName &p_name) const;
 	void remove_function(const StringName &p_name);

Dosya farkı çok büyük olduğundan ihmal edildi
+ 640 - 308
modules/visual_script/visual_script_editor.cpp


+ 52 - 14
modules/visual_script/visual_script_editor.h

@@ -59,6 +59,8 @@ class VisualScriptEditor : public ScriptEditorBase {
 		EDIT_COPY_NODES,
 		EDIT_CUT_NODES,
 		EDIT_PASTE_NODES,
+		EDIT_CREATE_FUNCTION,
+		REFRESH_GRAPH
 	};
 
 	enum PortAction {
@@ -86,10 +88,11 @@ class VisualScriptEditor : public ScriptEditorBase {
 
 	Button *base_type_select;
 
-	GraphEdit *graph;
+	LineEdit *func_name_box;
+	VBoxContainer *func_input_vbox;
+	ConfirmationDialog *function_create_dialog;
 
-	LineEdit *node_filter;
-	TextureRect *node_filter_icon;
+	GraphEdit *graph;
 
 	VisualScriptEditorSignalEdit *signal_editor;
 
@@ -110,7 +113,8 @@ class VisualScriptEditor : public ScriptEditorBase {
 	UndoRedo *undo_redo;
 
 	Tree *members;
-	Tree *nodes;
+	PopupDialog *function_name_edit;
+	LineEdit *function_name_box;
 
 	Label *hint_text;
 	Timer *hint_text_timer;
@@ -133,6 +137,7 @@ class VisualScriptEditor : public ScriptEditorBase {
 
 	HashMap<StringName, Ref<StyleBox> > node_styles;
 	StringName edited_func;
+	StringName default_func;
 
 	void _update_graph_connections();
 	void _update_graph(int p_only_id = -1);
@@ -165,9 +170,13 @@ class VisualScriptEditor : public ScriptEditorBase {
 	int port_action_output;
 	Vector2 port_action_pos;
 	int port_action_new_node;
-	void _port_action_menu(int p_option);
 
-	void new_node(Ref<VisualScriptNode> vnode, Vector2 ofs);
+	bool saved_pos_dirty;
+	Vector2 saved_position;
+
+	Vector2 mouse_up_position;
+
+	void _port_action_menu(int p_option, const StringName &p_func);
 
 	void connect_data(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode, int new_id);
 
@@ -175,13 +184,13 @@ class VisualScriptEditor : public ScriptEditorBase {
 	void connect_seq(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode_new, int new_id);
 
 	void _cancel_connect_node();
-	void _create_new_node(const String &p_text, const String &p_category, const Vector2 &p_point);
+	int _create_new_node_from_name(const String &p_text, const Vector2 &p_point, const StringName &p_func = StringName());
 	void _selected_new_virtual_method(const String &p_text, const String &p_category, const bool p_connecting);
 
 	int error_line;
 
 	void _node_selected(Node *p_node);
-	void _center_on_node(int p_id);
+	void _center_on_node(const StringName &p_func, int p_id);
 
 	void _node_filter_changed(const String &p_text);
 	void _change_base_type_callback();
@@ -192,7 +201,9 @@ class VisualScriptEditor : public ScriptEditorBase {
 
 	void _begin_node_move();
 	void _end_node_move();
-	void _move_node(String func, int p_id, const Vector2 &p_to);
+	void _move_node(const StringName &p_func, int p_id, const Vector2 &p_to);
+
+	void _get_ends(int p_node, const List<VisualScript::SequenceConnection> &p_seqs, const Set<int> &p_selected, Set<int> &r_end_nodes);
 
 	void _node_moved(Vector2 p_from, Vector2 p_to, int p_id);
 	void _remove_node(int p_id);
@@ -201,21 +212,44 @@ class VisualScriptEditor : public ScriptEditorBase {
 	void _graph_connect_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_pos);
 
 	void _node_ports_changed(const String &p_func, int p_id);
-	void _available_node_doubleclicked();
+	void _node_create();
 
 	void _update_available_nodes();
 
 	void _member_button(Object *p_item, int p_column, int p_button);
 
 	void _expression_text_changed(const String &p_text, int p_id);
+	void _add_input_port(int p_id);
+	void _add_output_port(int p_id);
+	void _remove_input_port(int p_id, int p_port);
+	void _remove_output_port(int p_id, int p_port);
+	void _change_port_type(int p_select, int p_id, int p_port, bool is_input);
+	void _update_node_size(int p_id);
+	void _port_name_focus_out(const Node *p_name_box, int p_id, int p_port, bool is_input);
 
-	String revert_on_drag;
+	Vector2 _get_available_pos(bool centered = true, Vector2 pos = Vector2()) const;
+	StringName _get_function_of_node(int p_id) const;
 
-	void _input(const Ref<InputEvent> &p_event);
+	void _move_nodes_with_rescan(const StringName &p_func_from, const StringName &p_func_to, int p_id);
+	bool node_has_sequence_connections(const StringName &p_func, int p_id);
 
-	void _generic_search(String p_base_type = "");
+	void _generic_search(String p_base_type = "", Vector2 pos = Vector2(), bool node_centered = false);
 
+	void _input(const Ref<InputEvent> &p_event);
+	void _graph_gui_input(const Ref<InputEvent> &p_event);
 	void _members_gui_input(const Ref<InputEvent> &p_event);
+	void _fn_name_box_input(const Ref<InputEvent> &p_event);
+	void _rename_function(const String &p_name, const String &p_new_name);
+
+	void _create_function_dialog();
+	void _create_function();
+	void _add_func_input();
+	void _remove_func_input(Node *p_node);
+	void _deselect_input_names();
+	void _add_node_dialog();
+	void _node_item_selected();
+	void _node_item_unselected();
+
 	void _on_nodes_delete();
 	void _on_nodes_duplicate();
 
@@ -226,6 +260,10 @@ class VisualScriptEditor : public ScriptEditorBase {
 	int editing_id;
 	int editing_input;
 
+	bool can_swap;
+	int data_disconnect_node;
+	int data_disconnect_port;
+
 	void _default_value_changed();
 	void _default_value_edited(Node *p_button, int p_id, int p_input_port);
 
@@ -240,7 +278,7 @@ class VisualScriptEditor : public ScriptEditorBase {
 	void _draw_color_over_button(Object *obj, Color p_color);
 	void _button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, Variant p_ud);
 
-	VisualScriptNode::TypeGuess _guess_output_type(int p_port_action_node, int p_port_action_output, Set<int> &visited_nodes);
+	VisualScriptNode::TypeGuess _guess_output_type(int p_port_action_node, int p_port_action_output, Set<int> &p_visited_nodes);
 
 	void _member_rmb_selected(const Vector2 &p_pos);
 	void _member_option(int p_option);

+ 4 - 9
modules/visual_script/visual_script_func_nodes.cpp

@@ -133,10 +133,12 @@ int VisualScriptFunctionCall::get_input_value_port_count() const {
 
 		MethodBind *mb = ClassDB::get_method(_get_base_type(), function);
 		if (mb) {
-			return mb->get_argument_count() + (call_mode == CALL_MODE_INSTANCE ? 1 : 0) + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) - use_default_args;
+			int defaulted_args = mb->get_argument_count() < use_default_args ? mb->get_argument_count() : use_default_args;
+			return mb->get_argument_count() + (call_mode == CALL_MODE_INSTANCE ? 1 : 0) + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) - defaulted_args;
 		}
 
-		return method_cache.arguments.size() + (call_mode == CALL_MODE_INSTANCE ? 1 : 0) + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) - use_default_args;
+		int defaulted_args = method_cache.arguments.size() < use_default_args ? method_cache.arguments.size() : use_default_args;
+		return method_cache.arguments.size() + (call_mode == CALL_MODE_INSTANCE ? 1 : 0) + (rpc_call_mode >= RPC_RELIABLE_TO_ID ? 1 : 0) - defaulted_args;
 	}
 }
 int VisualScriptFunctionCall::get_output_value_port_count() const {
@@ -1056,13 +1058,6 @@ PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) cons
 	if (call_mode == CALL_MODE_BASIC_TYPE) {
 		return PropertyInfo(basic_type, "out");
 	} else if (call_mode == CALL_MODE_INSTANCE) {
-		List<PropertyInfo> props;
-		ClassDB::get_property_list(_get_base_type(), &props, true);
-		for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
-			if (E->get().name == property) {
-				return PropertyInfo(E->get().type, "pass", PROPERTY_HINT_TYPE_STRING, E->get().hint_string);
-			}
-		}
 		return PropertyInfo(Variant::OBJECT, "pass", PROPERTY_HINT_TYPE_STRING, get_base_type());
 	} else {
 		return PropertyInfo();

+ 436 - 0
modules/visual_script/visual_script_nodes.cpp

@@ -355,6 +355,441 @@ int VisualScriptFunction::get_stack_size() const {
 	return stack_size;
 }
 
+//////////////////////////////////////////
+/////////////////LISTS////////////////////
+//////////////////////////////////////////
+
+int VisualScriptLists::get_output_sequence_port_count() const {
+	if (sequenced)
+		return 1;
+	return 0;
+}
+bool VisualScriptLists::has_input_sequence_port() const {
+	return sequenced;
+}
+
+String VisualScriptLists::get_output_sequence_port_text(int p_port) const {
+	return "";
+}
+
+int VisualScriptLists::get_input_value_port_count() const {
+	return inputports.size();
+}
+int VisualScriptLists::get_output_value_port_count() const {
+	return outputports.size();
+}
+
+PropertyInfo VisualScriptLists::get_input_value_port_info(int p_idx) const {
+	ERR_FAIL_INDEX_V(p_idx, inputports.size(), PropertyInfo());
+
+	PropertyInfo pi;
+	pi.name = inputports[p_idx].name;
+	pi.type = inputports[p_idx].type;
+	return pi;
+}
+PropertyInfo VisualScriptLists::get_output_value_port_info(int p_idx) const {
+	ERR_FAIL_INDEX_V(p_idx, outputports.size(), PropertyInfo());
+
+	PropertyInfo pi;
+	pi.name = outputports[p_idx].name;
+	pi.type = outputports[p_idx].type;
+	return pi;
+}
+
+bool VisualScriptLists::is_input_port_editable() const {
+	return ((flags & INPUT_EDITABLE) == INPUT_EDITABLE);
+}
+bool VisualScriptLists::is_input_port_name_editable() const {
+	return ((flags & INPUT_NAME_EDITABLE) == INPUT_NAME_EDITABLE);
+}
+bool VisualScriptLists::is_input_port_type_editable() const {
+	return ((flags & INPUT_TYPE_EDITABLE) == INPUT_TYPE_EDITABLE);
+}
+
+bool VisualScriptLists::is_output_port_editable() const {
+	return ((flags & OUTPUT_EDITABLE) == OUTPUT_EDITABLE);
+}
+bool VisualScriptLists::is_output_port_name_editable() const {
+	return ((flags & INPUT_NAME_EDITABLE) == INPUT_NAME_EDITABLE);
+}
+bool VisualScriptLists::is_output_port_type_editable() const {
+	return ((flags & INPUT_TYPE_EDITABLE) == INPUT_TYPE_EDITABLE);
+}
+
+// for the inspector
+bool VisualScriptLists::_set(const StringName &p_name, const Variant &p_value) {
+
+	if (p_name == "input_count" && is_input_port_editable()) {
+
+		int new_argc = p_value;
+		int argc = inputports.size();
+		if (argc == new_argc)
+			return true;
+
+		inputports.resize(new_argc);
+
+		for (int i = argc; i < new_argc; i++) {
+			inputports.write[i].name = "arg" + itos(i + 1);
+			inputports.write[i].type = Variant::NIL;
+		}
+		ports_changed_notify();
+		_change_notify();
+		return true;
+	}
+	if (String(p_name).begins_with("input_") && is_input_port_editable()) {
+		int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1;
+		ERR_FAIL_INDEX_V(idx, inputports.size(), false);
+		String what = String(p_name).get_slice("/", 1);
+		if (what == "type") {
+
+			Variant::Type new_type = Variant::Type(int(p_value));
+			inputports.write[idx].type = new_type;
+			ports_changed_notify();
+
+			return true;
+		}
+
+		if (what == "name") {
+
+			inputports.write[idx].name = p_value;
+			ports_changed_notify();
+			return true;
+		}
+	}
+
+	if (p_name == "output_count" && is_output_port_editable()) {
+
+		int new_argc = p_value;
+		int argc = outputports.size();
+		if (argc == new_argc)
+			return true;
+
+		outputports.resize(new_argc);
+
+		for (int i = argc; i < new_argc; i++) {
+			outputports.write[i].name = "arg" + itos(i + 1);
+			outputports.write[i].type = Variant::NIL;
+		}
+		ports_changed_notify();
+		_change_notify();
+		return true;
+	}
+	if (String(p_name).begins_with("output_") && is_output_port_editable()) {
+		int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1;
+		ERR_FAIL_INDEX_V(idx, outputports.size(), false);
+		String what = String(p_name).get_slice("/", 1);
+		if (what == "type") {
+
+			Variant::Type new_type = Variant::Type(int(p_value));
+			outputports.write[idx].type = new_type;
+			ports_changed_notify();
+
+			return true;
+		}
+
+		if (what == "name") {
+
+			outputports.write[idx].name = p_value;
+			ports_changed_notify();
+			return true;
+		}
+	}
+
+	if (p_name == "sequenced/sequenced") {
+		sequenced = p_value;
+		ports_changed_notify();
+		return true;
+	}
+
+	return false;
+}
+bool VisualScriptLists::_get(const StringName &p_name, Variant &r_ret) const {
+
+	if (p_name == "input_count" && is_input_port_editable()) {
+		r_ret = inputports.size();
+		return true;
+	}
+	if (String(p_name).begins_with("input_") && is_input_port_editable()) {
+		int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1;
+		ERR_FAIL_INDEX_V(idx, inputports.size(), false);
+		String what = String(p_name).get_slice("/", 1);
+		if (what == "type") {
+			r_ret = inputports[idx].type;
+			return true;
+		}
+		if (what == "name") {
+			r_ret = inputports[idx].name;
+			return true;
+		}
+	}
+
+	if (p_name == "output_count" && is_output_port_editable()) {
+		r_ret = outputports.size();
+		return true;
+	}
+	if (String(p_name).begins_with("output_") && is_output_port_editable()) {
+		int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1;
+		ERR_FAIL_INDEX_V(idx, outputports.size(), false);
+		String what = String(p_name).get_slice("/", 1);
+		if (what == "type") {
+			r_ret = outputports[idx].type;
+			return true;
+		}
+		if (what == "name") {
+			r_ret = outputports[idx].name;
+			return true;
+		}
+	}
+
+	if (p_name == "sequenced/sequenced") {
+		r_ret = sequenced;
+		return true;
+	}
+
+	return false;
+}
+void VisualScriptLists::_get_property_list(List<PropertyInfo> *p_list) const {
+
+	if (is_input_port_editable()) {
+		p_list->push_back(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_RANGE, "0,256"));
+		String argt = "Any";
+		for (int i = 1; i < Variant::VARIANT_MAX; i++) {
+			argt += "," + Variant::get_type_name(Variant::Type(i));
+		}
+
+		for (int i = 0; i < inputports.size(); i++) {
+			p_list->push_back(PropertyInfo(Variant::INT, "input_" + itos(i + 1) + "/type", PROPERTY_HINT_ENUM, argt));
+			p_list->push_back(PropertyInfo(Variant::STRING, "input_" + itos(i + 1) + "/name"));
+		}
+	}
+
+	if (is_output_port_editable()) {
+		p_list->push_back(PropertyInfo(Variant::INT, "output_count", PROPERTY_HINT_RANGE, "0,256"));
+		String argt = "Any";
+		for (int i = 1; i < Variant::VARIANT_MAX; i++) {
+			argt += "," + Variant::get_type_name(Variant::Type(i));
+		}
+
+		for (int i = 0; i < outputports.size(); i++) {
+			p_list->push_back(PropertyInfo(Variant::INT, "output_" + itos(i + 1) + "/type", PROPERTY_HINT_ENUM, argt));
+			p_list->push_back(PropertyInfo(Variant::STRING, "output_" + itos(i + 1) + "/name"));
+		}
+	}
+	p_list->push_back(PropertyInfo(Variant::BOOL, "sequenced/sequenced"));
+}
+
+// input data port interaction
+void VisualScriptLists::add_input_data_port(Variant::Type p_type, const String &p_name, int p_index) {
+
+	if (!is_input_port_editable())
+		return;
+
+	Port inp;
+	inp.name = p_name;
+	inp.type = p_type;
+	if (p_index >= 0)
+		inputports.insert(p_index, inp);
+	else
+		inputports.push_back(inp);
+
+	ports_changed_notify();
+	_change_notify();
+}
+void VisualScriptLists::set_input_data_port_type(int p_idx, Variant::Type p_type) {
+
+	if (!is_input_port_type_editable())
+		return;
+
+	ERR_FAIL_INDEX(p_idx, inputports.size());
+
+	inputports.write[p_idx].type = p_type;
+	ports_changed_notify();
+	_change_notify();
+}
+void VisualScriptLists::set_input_data_port_name(int p_idx, const String &p_name) {
+
+	if (!is_input_port_name_editable())
+		return;
+
+	ERR_FAIL_INDEX(p_idx, inputports.size());
+
+	inputports.write[p_idx].name = p_name;
+	ports_changed_notify();
+	_change_notify();
+}
+void VisualScriptLists::remove_input_data_port(int p_argidx) {
+
+	if (!is_input_port_editable())
+		return;
+
+	ERR_FAIL_INDEX(p_argidx, inputports.size());
+
+	inputports.remove(p_argidx);
+
+	ports_changed_notify();
+	_change_notify();
+}
+
+// output data port interaction
+void VisualScriptLists::add_output_data_port(Variant::Type p_type, const String &p_name, int p_index) {
+
+	if (!is_output_port_editable())
+		return;
+
+	Port out;
+	out.name = p_name;
+	out.type = p_type;
+	if (p_index >= 0)
+		outputports.insert(p_index, out);
+	else
+		outputports.push_back(out);
+
+	ports_changed_notify();
+	_change_notify();
+}
+void VisualScriptLists::set_output_data_port_type(int p_idx, Variant::Type p_type) {
+
+	if (!is_output_port_type_editable())
+		return;
+
+	ERR_FAIL_INDEX(p_idx, outputports.size());
+
+	outputports.write[p_idx].type = p_type;
+	ports_changed_notify();
+	_change_notify();
+}
+void VisualScriptLists::set_output_data_port_name(int p_idx, const String &p_name) {
+
+	if (!is_output_port_name_editable())
+		return;
+
+	ERR_FAIL_INDEX(p_idx, outputports.size());
+
+	outputports.write[p_idx].name = p_name;
+	ports_changed_notify();
+	_change_notify();
+}
+void VisualScriptLists::remove_output_data_port(int p_argidx) {
+
+	if (!is_output_port_editable())
+		return;
+
+	ERR_FAIL_INDEX(p_argidx, outputports.size());
+
+	outputports.remove(p_argidx);
+
+	ports_changed_notify();
+	_change_notify();
+}
+
+// sequences
+void VisualScriptLists::set_sequenced(bool p_enable) {
+	if (sequenced == p_enable)
+		return;
+	sequenced = p_enable;
+	ports_changed_notify();
+}
+bool VisualScriptLists::is_sequenced() const {
+	return sequenced;
+}
+
+VisualScriptLists::VisualScriptLists() {
+	// initialize
+	sequenced = false;
+	flags = 0;
+}
+
+void VisualScriptLists::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("add_input_data_port"), &VisualScriptLists::add_input_data_port);
+	ClassDB::bind_method(D_METHOD("set_input_data_port_name"), &VisualScriptLists::set_input_data_port_name);
+	ClassDB::bind_method(D_METHOD("set_input_data_port_type"), &VisualScriptLists::set_input_data_port_type);
+	ClassDB::bind_method(D_METHOD("remove_input_data_port"), &VisualScriptLists::remove_input_data_port);
+
+	ClassDB::bind_method(D_METHOD("add_output_data_port"), &VisualScriptLists::add_output_data_port);
+	ClassDB::bind_method(D_METHOD("set_output_data_port_name"), &VisualScriptLists::set_output_data_port_name);
+	ClassDB::bind_method(D_METHOD("set_output_data_port_type"), &VisualScriptLists::set_output_data_port_type);
+	ClassDB::bind_method(D_METHOD("remove_output_data_port"), &VisualScriptLists::remove_output_data_port);
+}
+
+//////////////////////////////////////////
+//////////////COMPOSEARRAY////////////////
+//////////////////////////////////////////
+
+int VisualScriptComposeArray::get_output_sequence_port_count() const {
+	if (sequenced)
+		return 1;
+	return 0;
+}
+bool VisualScriptComposeArray::has_input_sequence_port() const {
+	return sequenced;
+}
+
+String VisualScriptComposeArray::get_output_sequence_port_text(int p_port) const {
+	return "";
+}
+
+int VisualScriptComposeArray::get_input_value_port_count() const {
+	return inputports.size();
+}
+int VisualScriptComposeArray::get_output_value_port_count() const {
+	return 1;
+}
+
+PropertyInfo VisualScriptComposeArray::get_input_value_port_info(int p_idx) const {
+	ERR_FAIL_INDEX_V(p_idx, inputports.size(), PropertyInfo());
+
+	PropertyInfo pi;
+	pi.name = inputports[p_idx].name;
+	pi.type = inputports[p_idx].type;
+	return pi;
+}
+PropertyInfo VisualScriptComposeArray::get_output_value_port_info(int p_idx) const {
+	PropertyInfo pi;
+	pi.name = "out";
+	pi.type = Variant::ARRAY;
+	return pi;
+}
+
+String VisualScriptComposeArray::get_caption() const {
+	return "Compose Array";
+}
+String VisualScriptComposeArray::get_text() const {
+	return "";
+}
+
+class VisualScriptComposeArrayNode : public VisualScriptNodeInstance {
+public:
+	int input_count = 0;
+	virtual int get_working_memory_size() const { return 0; }
+
+	virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) {
+
+		if (input_count > 0) {
+			Array arr;
+			for (int i = 0; i < input_count; i++)
+				arr.push_back((*p_inputs[i]));
+			Variant va = Variant(arr);
+
+			*p_outputs[0] = va;
+		}
+
+		return 0;
+	}
+};
+
+VisualScriptNodeInstance *VisualScriptComposeArray::instance(VisualScriptInstance *p_instance) {
+
+	VisualScriptComposeArrayNode *instance = memnew(VisualScriptComposeArrayNode);
+	instance->input_count = inputports.size();
+	return instance;
+}
+
+VisualScriptComposeArray::VisualScriptComposeArray() {
+	// initialize stuff here
+	sequenced = false;
+	flags = INPUT_EDITABLE;
+}
+
 //////////////////////////////////////////
 ////////////////OPERATOR//////////////////
 //////////////////////////////////////////
@@ -3698,6 +4133,7 @@ void register_visual_script_nodes() {
 	VisualScriptLanguage::singleton->add_register_func("operators/logic/select", create_node_generic<VisualScriptSelect>);
 
 	VisualScriptLanguage::singleton->add_register_func("functions/deconstruct", create_node_generic<VisualScriptDeconstruct>);
+	VisualScriptLanguage::singleton->add_register_func("functions/compose_array", create_node_generic<VisualScriptComposeArray>);
 
 	for (int i = 1; i < Variant::VARIANT_MAX; i++) {
 

+ 97 - 0
modules/visual_script/visual_script_nodes.h

@@ -103,6 +103,103 @@ public:
 	VisualScriptFunction();
 };
 
+class VisualScriptLists : public VisualScriptNode {
+
+	GDCLASS(VisualScriptLists, VisualScriptNode)
+
+	struct Port {
+		String name;
+		Variant::Type type;
+	};
+
+protected:
+	Vector<Port> inputports;
+	Vector<Port> outputports;
+
+	enum {
+		OUTPUT_EDITABLE = 0x0001,
+		OUTPUT_NAME_EDITABLE = 0x0002,
+		OUTPUT_TYPE_EDITABLE = 0x0004,
+		INPUT_EDITABLE = 0x0008,
+		INPUT_NAME_EDITABLE = 0x000F,
+		INPUT_TYPE_EDITABLE = 0x0010,
+	};
+
+	int flags;
+
+	bool sequenced;
+
+	bool _set(const StringName &p_name, const Variant &p_value);
+	bool _get(const StringName &p_name, Variant &r_ret) const;
+	void _get_property_list(List<PropertyInfo> *p_list) const;
+
+	static void _bind_methods();
+
+public:
+	virtual bool is_output_port_editable() const;
+	virtual bool is_output_port_name_editable() const;
+	virtual bool is_output_port_type_editable() const;
+
+	virtual bool is_input_port_editable() const;
+	virtual bool is_input_port_name_editable() const;
+	virtual bool is_input_port_type_editable() const;
+
+	virtual int get_output_sequence_port_count() const;
+	virtual bool has_input_sequence_port() const;
+
+	virtual String get_output_sequence_port_text(int p_port) const;
+
+	virtual int get_input_value_port_count() const;
+	virtual int get_output_value_port_count() const;
+
+	virtual PropertyInfo get_input_value_port_info(int p_idx) const;
+	virtual PropertyInfo get_output_value_port_info(int p_idx) const;
+
+	virtual String get_caption() const = 0;
+	virtual String get_text() const = 0;
+	virtual String get_category() const = 0;
+
+	void add_input_data_port(Variant::Type p_type, const String &p_name, int p_index = -1);
+	void set_input_data_port_type(int p_idx, Variant::Type p_type);
+	void set_input_data_port_name(int p_idx, const String &p_name);
+	void remove_input_data_port(int p_argidx);
+
+	void add_output_data_port(Variant::Type p_type, const String &p_name, int p_index = -1);
+	void set_output_data_port_type(int p_idx, Variant::Type p_type);
+	void set_output_data_port_name(int p_idx, const String &p_name);
+	void remove_output_data_port(int p_argidx);
+
+	void set_sequenced(bool p_enable);
+	bool is_sequenced() const;
+
+	VisualScriptLists();
+};
+
+class VisualScriptComposeArray : public VisualScriptLists {
+
+	GDCLASS(VisualScriptComposeArray, VisualScriptLists)
+
+public:
+	virtual int get_output_sequence_port_count() const;
+	virtual bool has_input_sequence_port() const;
+
+	virtual String get_output_sequence_port_text(int p_port) const;
+
+	virtual int get_input_value_port_count() const;
+	virtual int get_output_value_port_count() const;
+
+	virtual PropertyInfo get_input_value_port_info(int p_idx) const;
+	virtual PropertyInfo get_output_value_port_info(int p_idx) const;
+
+	virtual String get_caption() const;
+	virtual String get_text() const;
+	virtual String get_category() const { return "functions"; }
+
+	virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance);
+
+	VisualScriptComposeArray();
+};
+
 class VisualScriptOperator : public VisualScriptNode {
 
 	GDCLASS(VisualScriptOperator, VisualScriptNode);

+ 57 - 28
modules/visual_script/visual_script_property_selector.cpp

@@ -200,13 +200,10 @@ void VisualScriptPropertySelector::_update_search() {
 
 				Object *obj = ObjectDB::get_instance(script);
 				if (Object::cast_to<Script>(obj)) {
-					methods.push_back(MethodInfo("*Script Methods"));
 					Object::cast_to<Script>(obj)->get_script_method_list(&methods);
-
-				} else {
-					methods.push_back(MethodInfo("*" + String(E->get())));
-					ClassDB::get_method_list(E->get(), &methods, true, true);
 				}
+
+				ClassDB::get_method_list(E->get(), &methods, true, true);
 			}
 		}
 		for (List<MethodInfo>::Element *M = methods.front(); M; M = M->next()) {
@@ -349,26 +346,37 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt
 			continue;
 		}
 
-		if (search_box->get_text() != String() && E->get().findn(search_box->get_text()) == -1) {
+		Vector<String> tx_filters = search_box->get_text().split(" ");
+		for (int i = 0; i < tx_filters.size(); i++) {
+			if (tx_filters[i] != String() && E->get().findn(tx_filters[i]) == -1) {
+				is_filter = true;
+				break;
+			}
+		}
+		if (is_filter) {
 			continue;
 		}
 		TreeItem *item = search_options->create_item(root);
-		VisualScriptOperator *vnode_operator = Object::cast_to<VisualScriptOperator>(*VisualScriptLanguage::singleton->create_node_from_name(E->get()));
+		Ref<VisualScriptNode> vnode = VisualScriptLanguage::singleton->create_node_from_name(E->get());
+		Ref<VisualScriptOperator> vnode_operator = vnode;
 		String type_name;
-		if (vnode_operator != NULL) {
+		if (vnode_operator.is_valid()) {
 			String type;
 			if (path.size() >= 2) {
 				type = path[1];
 			}
 			type_name = type.capitalize() + " ";
 		}
-		VisualScriptFunctionCall *vnode_function_call = Object::cast_to<VisualScriptFunctionCall>(*VisualScriptLanguage::singleton->create_node_from_name(E->get()));
-		if (vnode_function_call != NULL) {
+		Ref<VisualScriptFunctionCall> vnode_function_call = vnode;
+		if (vnode_function_call.is_valid()) {
 			String basic_type = Variant::get_type_name(vnode_function_call->get_basic_type());
 			type_name = basic_type.capitalize() + " ";
 		}
-
-		Vector<String> desc = path[path.size() - 1].replace("(", "( ").replace(")", " )").replace(",", ", ").split(" ");
+		Ref<VisualScriptConstructor> vnode_constructor = vnode;
+		if (vnode_constructor.is_valid()) {
+			type_name = "Construct ";
+		}
+		Vector<String> desc = path[path.size() - 1].replace("(", " ").replace(")", " ").replace(",", " ").split(" ");
 		for (int i = 0; i < desc.size(); i++) {
 			desc.write[i] = desc[i].capitalize();
 			if (desc[i].ends_with(",")) {
@@ -504,7 +512,7 @@ void VisualScriptPropertySelector::_notification(int p_what) {
 	}
 }
 
-void VisualScriptPropertySelector::select_method_from_base_type(const String &p_base, const String &p_current, const bool p_virtuals_only, const bool p_connecting) {
+void VisualScriptPropertySelector::select_method_from_base_type(const String &p_base, const String &p_current, const bool p_virtuals_only, const bool p_connecting, bool clear_text) {
 
 	base_type = p_base;
 	selected = p_current;
@@ -515,7 +523,10 @@ void VisualScriptPropertySelector::select_method_from_base_type(const String &p_
 	virtuals_only = p_virtuals_only;
 
 	show_window(.5f);
-	search_box->set_text("");
+	if (clear_text)
+		search_box->set_text("");
+	else
+		search_box->select_all();
 	search_box->grab_focus();
 	connecting = p_connecting;
 
@@ -526,7 +537,7 @@ void VisualScriptPropertySelector::set_type_filter(const Vector<Variant::Type> &
 	type_filter = p_type_filter;
 }
 
-void VisualScriptPropertySelector::select_from_base_type(const String &p_base, const String &p_current, bool p_virtuals_only, bool p_seq_connect, const bool p_connecting) {
+void VisualScriptPropertySelector::select_from_base_type(const String &p_base, const String &p_current, bool p_virtuals_only, bool p_seq_connect, const bool p_connecting, bool clear_text) {
 
 	base_type = p_base;
 	selected = p_current;
@@ -538,7 +549,10 @@ void VisualScriptPropertySelector::select_from_base_type(const String &p_base, c
 	virtuals_only = p_virtuals_only;
 
 	show_window(.5f);
-	search_box->set_text("");
+	if (clear_text)
+		search_box->set_text("");
+	else
+		search_box->select_all();
 	search_box->grab_focus();
 	seq_connect = p_seq_connect;
 	connecting = p_connecting;
@@ -546,7 +560,7 @@ void VisualScriptPropertySelector::select_from_base_type(const String &p_base, c
 	_update_search();
 }
 
-void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_script, const String &p_current, const bool p_connecting) {
+void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_script, const String &p_current, const bool p_connecting, bool clear_text) {
 	ERR_FAIL_COND(p_script.is_null());
 
 	base_type = p_script->get_instance_base_type();
@@ -559,7 +573,10 @@ void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_scrip
 	virtuals_only = false;
 
 	show_window(.5f);
-	search_box->set_text("");
+	if (clear_text)
+		search_box->set_text("");
+	else
+		search_box->select_all();
 	search_box->grab_focus();
 	seq_connect = false;
 	connecting = p_connecting;
@@ -567,7 +584,7 @@ void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_scrip
 	_update_search();
 }
 
-void VisualScriptPropertySelector::select_from_basic_type(Variant::Type p_type, const String &p_current, const bool p_connecting) {
+void VisualScriptPropertySelector::select_from_basic_type(Variant::Type p_type, const String &p_current, const bool p_connecting, bool clear_text) {
 	ERR_FAIL_COND(p_type == Variant::NIL);
 	base_type = "";
 	selected = p_current;
@@ -579,7 +596,10 @@ void VisualScriptPropertySelector::select_from_basic_type(Variant::Type p_type,
 	virtuals_only = false;
 
 	show_window(.5f);
-	search_box->set_text("");
+	if (clear_text)
+		search_box->set_text("");
+	else
+		search_box->select_all();
 	search_box->grab_focus();
 	seq_connect = false;
 	connecting = p_connecting;
@@ -587,7 +607,7 @@ void VisualScriptPropertySelector::select_from_basic_type(Variant::Type p_type,
 	_update_search();
 }
 
-void VisualScriptPropertySelector::select_from_action(const String &p_type, const String &p_current, const bool p_connecting) {
+void VisualScriptPropertySelector::select_from_action(const String &p_type, const String &p_current, const bool p_connecting, bool clear_text) {
 	base_type = p_type;
 	selected = p_current;
 	type = Variant::NIL;
@@ -598,7 +618,10 @@ void VisualScriptPropertySelector::select_from_action(const String &p_type, cons
 	virtuals_only = false;
 
 	show_window(.5f);
-	search_box->set_text("");
+	if (clear_text)
+		search_box->set_text("");
+	else
+		search_box->select_all();
 	search_box->grab_focus();
 	seq_connect = true;
 	connecting = p_connecting;
@@ -606,8 +629,8 @@ void VisualScriptPropertySelector::select_from_action(const String &p_type, cons
 	_update_search();
 }
 
-void VisualScriptPropertySelector::select_from_instance(Object *p_instance, const String &p_current, const bool p_connecting) {
-	base_type = "";
+void VisualScriptPropertySelector::select_from_instance(Object *p_instance, const String &p_current, const bool p_connecting, const String &p_basetype, bool clear_text) {
+	base_type = p_basetype;
 	selected = p_current;
 	type = Variant::NIL;
 	script = 0;
@@ -617,7 +640,10 @@ void VisualScriptPropertySelector::select_from_instance(Object *p_instance, cons
 	virtuals_only = false;
 
 	show_window(.5f);
-	search_box->set_text("");
+	if (clear_text)
+		search_box->set_text("");
+	else
+		search_box->select_all();
 	search_box->grab_focus();
 	seq_connect = false;
 	connecting = p_connecting;
@@ -625,7 +651,7 @@ void VisualScriptPropertySelector::select_from_instance(Object *p_instance, cons
 	_update_search();
 }
 
-void VisualScriptPropertySelector::select_from_visual_script(const String &p_base, const bool p_connecting) {
+void VisualScriptPropertySelector::select_from_visual_script(const String &p_base, const bool p_connecting, bool clear_text) {
 	base_type = p_base;
 	selected = "";
 	type = Variant::NIL;
@@ -635,7 +661,10 @@ void VisualScriptPropertySelector::select_from_visual_script(const String &p_bas
 	instance = NULL;
 	virtuals_only = false;
 	show_window(.5f);
-	search_box->set_text("");
+	if (clear_text)
+		search_box->set_text("");
+	else
+		search_box->select_all();
 	search_box->grab_focus();
 	connecting = p_connecting;
 
@@ -646,7 +675,7 @@ void VisualScriptPropertySelector::show_window(float p_screen_ratio) {
 	Rect2 rect;
 	Point2 window_size = get_viewport_rect().size;
 	rect.size = (window_size * p_screen_ratio).floor();
-	rect.size.x = rect.size.x / 1.25f;
+	rect.size.x = rect.size.x / 2.2f;
 	rect.position = ((window_size - rect.size) / 2.0f).floor();
 	popup(rect);
 }

+ 7 - 7
modules/visual_script/visual_script_property_selector.h

@@ -74,13 +74,13 @@ protected:
 	static void _bind_methods();
 
 public:
-	void select_method_from_base_type(const String &p_base, const String &p_current = "", const bool p_virtuals_only = false, const bool p_connecting = true);
-	void select_from_base_type(const String &p_base, const String &p_current = "", bool p_virtuals_only = false, bool p_seq_connect = false, const bool p_connecting = true);
-	void select_from_script(const Ref<Script> &p_script, const String &p_current = "", const bool p_connecting = true);
-	void select_from_basic_type(Variant::Type p_type, const String &p_current = "", const bool p_connecting = true);
-	void select_from_action(const String &p_type, const String &p_current = "", const bool p_connecting = true);
-	void select_from_instance(Object *p_instance, const String &p_current = "", const bool p_connecting = true);
-	void select_from_visual_script(const String &p_base, const bool p_connecting = true);
+	void select_method_from_base_type(const String &p_base, const String &p_current = "", const bool p_virtuals_only = false, const bool p_connecting = true, bool clear_text = true);
+	void select_from_base_type(const String &p_base, const String &p_current = "", bool p_virtuals_only = false, bool p_seq_connect = false, const bool p_connecting = true, bool clear_text = true);
+	void select_from_script(const Ref<Script> &p_script, const String &p_current = "", const bool p_connecting = true, bool clear_text = true);
+	void select_from_basic_type(Variant::Type p_type, const String &p_current = "", const bool p_connecting = true, bool clear_text = true);
+	void select_from_action(const String &p_type, const String &p_current = "", const bool p_connecting = true, bool clear_text = true);
+	void select_from_instance(Object *p_instance, const String &p_current = "", const bool p_connecting = true, const String &p_basetype = "", bool clear_text = true);
+	void select_from_visual_script(const String &p_base, const bool p_connecting = true, bool clear_text = true);
 
 	void show_window(float p_screen_ratio);
 

+ 3 - 1
scene/gui/tree.cpp

@@ -2546,7 +2546,9 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
 					} else {
 						Rect2 rect = get_selected()->get_meta("__focus_rect");
 						if (rect.has_point(Point2(b->get_position().x, b->get_position().y))) {
-							edit_selected();
+							if (!edit_selected()) {
+								emit_signal("item_double_clicked");
+							}
 						} else {
 							emit_signal("item_double_clicked");
 						}

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor