Shows menu when dragging connection on empty space in visual shader graph
This commit is contained in:
parent
2c96942df9
commit
0aec3c3113
6 changed files with 88 additions and 7 deletions
|
@ -211,6 +211,17 @@
|
||||||
Signal sent to the GraphEdit when the connection between 'from_slot' slot of 'from' GraphNode and 'to_slot' slot of 'to' GraphNode is attempted to be created.
|
Signal sent to the GraphEdit when the connection between 'from_slot' slot of 'from' GraphNode and 'to_slot' slot of 'to' GraphNode is attempted to be created.
|
||||||
</description>
|
</description>
|
||||||
</signal>
|
</signal>
|
||||||
|
<signal name="connection_from_empty">
|
||||||
|
<argument index="0" name="to" type="String">
|
||||||
|
</argument>
|
||||||
|
<argument index="1" name="to_slot" type="int">
|
||||||
|
</argument>
|
||||||
|
<argument index="2" name="release_position" type="Vector2">
|
||||||
|
</argument>
|
||||||
|
<description>
|
||||||
|
Signal sent when user dragging connection from input port into empty space of the graph.
|
||||||
|
</description>
|
||||||
|
</signal>
|
||||||
<signal name="connection_to_empty">
|
<signal name="connection_to_empty">
|
||||||
<argument index="0" name="from" type="String">
|
<argument index="0" name="from" type="String">
|
||||||
</argument>
|
</argument>
|
||||||
|
@ -219,6 +230,7 @@
|
||||||
<argument index="2" name="release_position" type="Vector2">
|
<argument index="2" name="release_position" type="Vector2">
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
|
Signal sent when user dragging connection from output port into empty space of the graph.
|
||||||
</description>
|
</description>
|
||||||
</signal>
|
</signal>
|
||||||
<signal name="delete_nodes_request">
|
<signal name="delete_nodes_request">
|
||||||
|
|
|
@ -1241,6 +1241,30 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
|
||||||
undo_redo->add_do_method(expr, "set_size", Size2(250 * EDSCALE, 150 * EDSCALE));
|
undo_redo->add_do_method(expr, "set_size", Size2(250 * EDSCALE, 150 * EDSCALE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (to_node != -1 && to_slot != -1) {
|
||||||
|
if (vsnode->get_output_port_count() > 0) {
|
||||||
|
|
||||||
|
int _from_node = id_to_use;
|
||||||
|
int _from_slot = 0;
|
||||||
|
|
||||||
|
if (visual_shader->is_port_types_compatible(vsnode->get_output_port_type(_from_slot), visual_shader->get_node(type, to_node)->get_input_port_type(to_slot))) {
|
||||||
|
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot);
|
||||||
|
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, _from_node, _from_slot, to_node, to_slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (from_node != -1 && from_slot != -1) {
|
||||||
|
if (vsnode->get_input_port_count() > 0) {
|
||||||
|
|
||||||
|
int _to_node = id_to_use;
|
||||||
|
int _to_slot = 0;
|
||||||
|
|
||||||
|
if (visual_shader->is_port_types_compatible(visual_shader->get_node(type, from_node)->get_output_port_type(from_slot), vsnode->get_input_port_type(_to_slot))) {
|
||||||
|
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
|
||||||
|
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
undo_redo->add_do_method(this, "_update_graph");
|
undo_redo->add_do_method(this, "_update_graph");
|
||||||
undo_redo->add_undo_method(this, "_update_graph");
|
undo_redo->add_undo_method(this, "_update_graph");
|
||||||
undo_redo->commit_action();
|
undo_redo->commit_action();
|
||||||
|
@ -1310,6 +1334,15 @@ void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualShaderEditor::_connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position) {
|
void VisualShaderEditor::_connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position) {
|
||||||
|
from_node = p_from.to_int();
|
||||||
|
from_slot = p_from_slot;
|
||||||
|
_show_members_dialog(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualShaderEditor::_connection_from_empty(const String &p_to, int p_to_slot, const Vector2 &p_release_position) {
|
||||||
|
to_node = p_to.to_int();
|
||||||
|
to_slot = p_to_slot;
|
||||||
|
_show_members_dialog(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualShaderEditor::_delete_request(int which) {
|
void VisualShaderEditor::_delete_request(int which) {
|
||||||
|
@ -1375,8 +1408,6 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> p_event) {
|
||||||
|
|
||||||
void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos) {
|
void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos) {
|
||||||
|
|
||||||
members_dialog->popup();
|
|
||||||
|
|
||||||
if (at_mouse_pos) {
|
if (at_mouse_pos) {
|
||||||
saved_node_pos_dirty = true;
|
saved_node_pos_dirty = true;
|
||||||
saved_node_pos = graph->get_local_mouse_position();
|
saved_node_pos = graph->get_local_mouse_position();
|
||||||
|
@ -1385,6 +1416,7 @@ void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos) {
|
||||||
members_dialog->popup();
|
members_dialog->popup();
|
||||||
members_dialog->set_position(gpos);
|
members_dialog->set_position(gpos);
|
||||||
} else {
|
} else {
|
||||||
|
members_dialog->popup();
|
||||||
saved_node_pos_dirty = false;
|
saved_node_pos_dirty = false;
|
||||||
members_dialog->set_position(graph->get_global_position() + Point2(5 * EDSCALE, 65 * EDSCALE));
|
members_dialog->set_position(graph->get_global_position() + Point2(5 * EDSCALE, 65 * EDSCALE));
|
||||||
}
|
}
|
||||||
|
@ -1701,6 +1733,13 @@ void VisualShaderEditor::_member_create() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VisualShaderEditor::_member_cancel() {
|
||||||
|
to_node = -1;
|
||||||
|
to_slot = -1;
|
||||||
|
from_node = -1;
|
||||||
|
from_slot = -1;
|
||||||
|
}
|
||||||
|
|
||||||
void VisualShaderEditor::_tools_menu_option(int p_idx) {
|
void VisualShaderEditor::_tools_menu_option(int p_idx) {
|
||||||
|
|
||||||
TreeItem *category = members->get_root()->get_children();
|
TreeItem *category = members->get_root()->get_children();
|
||||||
|
@ -1812,6 +1851,7 @@ void VisualShaderEditor::_bind_methods() {
|
||||||
ClassDB::bind_method("_edit_port_default_input", &VisualShaderEditor::_edit_port_default_input);
|
ClassDB::bind_method("_edit_port_default_input", &VisualShaderEditor::_edit_port_default_input);
|
||||||
ClassDB::bind_method("_port_edited", &VisualShaderEditor::_port_edited);
|
ClassDB::bind_method("_port_edited", &VisualShaderEditor::_port_edited);
|
||||||
ClassDB::bind_method("_connection_to_empty", &VisualShaderEditor::_connection_to_empty);
|
ClassDB::bind_method("_connection_to_empty", &VisualShaderEditor::_connection_to_empty);
|
||||||
|
ClassDB::bind_method("_connection_from_empty", &VisualShaderEditor::_connection_from_empty);
|
||||||
ClassDB::bind_method("_line_edit_focus_out", &VisualShaderEditor::_line_edit_focus_out);
|
ClassDB::bind_method("_line_edit_focus_out", &VisualShaderEditor::_line_edit_focus_out);
|
||||||
ClassDB::bind_method("_line_edit_changed", &VisualShaderEditor::_line_edit_changed);
|
ClassDB::bind_method("_line_edit_changed", &VisualShaderEditor::_line_edit_changed);
|
||||||
ClassDB::bind_method("_port_name_focus_out", &VisualShaderEditor::_port_name_focus_out);
|
ClassDB::bind_method("_port_name_focus_out", &VisualShaderEditor::_port_name_focus_out);
|
||||||
|
@ -1843,6 +1883,7 @@ void VisualShaderEditor::_bind_methods() {
|
||||||
ClassDB::bind_method("_member_selected", &VisualShaderEditor::_member_selected);
|
ClassDB::bind_method("_member_selected", &VisualShaderEditor::_member_selected);
|
||||||
ClassDB::bind_method("_member_unselected", &VisualShaderEditor::_member_unselected);
|
ClassDB::bind_method("_member_unselected", &VisualShaderEditor::_member_unselected);
|
||||||
ClassDB::bind_method("_member_create", &VisualShaderEditor::_member_create);
|
ClassDB::bind_method("_member_create", &VisualShaderEditor::_member_create);
|
||||||
|
ClassDB::bind_method("_member_cancel", &VisualShaderEditor::_member_cancel);
|
||||||
}
|
}
|
||||||
|
|
||||||
VisualShaderEditor *VisualShaderEditor::singleton = NULL;
|
VisualShaderEditor *VisualShaderEditor::singleton = NULL;
|
||||||
|
@ -1855,6 +1896,11 @@ VisualShaderEditor::VisualShaderEditor() {
|
||||||
saved_node_pos = Point2(0, 0);
|
saved_node_pos = Point2(0, 0);
|
||||||
ShaderLanguage::get_keyword_list(&keyword_list);
|
ShaderLanguage::get_keyword_list(&keyword_list);
|
||||||
|
|
||||||
|
to_node = -1;
|
||||||
|
to_slot = -1;
|
||||||
|
from_node = -1;
|
||||||
|
from_slot = -1;
|
||||||
|
|
||||||
graph = memnew(GraphEdit);
|
graph = memnew(GraphEdit);
|
||||||
add_child(graph);
|
add_child(graph);
|
||||||
graph->set_drag_forwarding(this);
|
graph->set_drag_forwarding(this);
|
||||||
|
@ -1871,6 +1917,8 @@ VisualShaderEditor::VisualShaderEditor() {
|
||||||
graph->connect("duplicate_nodes_request", this, "_duplicate_nodes");
|
graph->connect("duplicate_nodes_request", this, "_duplicate_nodes");
|
||||||
graph->connect("delete_nodes_request", this, "_on_nodes_delete");
|
graph->connect("delete_nodes_request", this, "_on_nodes_delete");
|
||||||
graph->connect("gui_input", this, "_graph_gui_input");
|
graph->connect("gui_input", this, "_graph_gui_input");
|
||||||
|
graph->connect("connection_to_empty", this, "_connection_to_empty");
|
||||||
|
graph->connect("connection_from_empty", this, "_connection_from_empty");
|
||||||
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR);
|
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR);
|
||||||
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR);
|
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR);
|
||||||
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_BOOLEAN);
|
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_BOOLEAN);
|
||||||
|
@ -1956,6 +2004,7 @@ VisualShaderEditor::VisualShaderEditor() {
|
||||||
members_dialog->get_ok()->set_disabled(true);
|
members_dialog->get_ok()->set_disabled(true);
|
||||||
members_dialog->set_resizable(true);
|
members_dialog->set_resizable(true);
|
||||||
members_dialog->set_as_minsize();
|
members_dialog->set_as_minsize();
|
||||||
|
members_dialog->connect("hide", this, "_member_cancel");
|
||||||
add_child(members_dialog);
|
add_child(members_dialog);
|
||||||
|
|
||||||
alert = memnew(AcceptDialog);
|
alert = memnew(AcceptDialog);
|
||||||
|
|
|
@ -160,7 +160,13 @@ class VisualShaderEditor : public VBoxContainer {
|
||||||
void _edit_port_default_input(Object *p_button, int p_node, int p_port);
|
void _edit_port_default_input(Object *p_button, int p_node, int p_port);
|
||||||
void _port_edited();
|
void _port_edited();
|
||||||
|
|
||||||
|
int to_node;
|
||||||
|
int to_slot;
|
||||||
|
int from_node;
|
||||||
|
int from_slot;
|
||||||
|
|
||||||
void _connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position);
|
void _connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position);
|
||||||
|
void _connection_from_empty(const String &p_to, int p_to_slot, const Vector2 &p_release_position);
|
||||||
|
|
||||||
void _line_edit_changed(const String &p_text, Object *line_edit, int p_node_id);
|
void _line_edit_changed(const String &p_text, Object *line_edit, int p_node_id);
|
||||||
void _line_edit_focus_out(Object *line_edit, int p_node_id);
|
void _line_edit_focus_out(Object *line_edit, int p_node_id);
|
||||||
|
@ -199,6 +205,7 @@ class VisualShaderEditor : public VBoxContainer {
|
||||||
void _member_selected();
|
void _member_selected();
|
||||||
void _member_unselected();
|
void _member_unselected();
|
||||||
void _member_create();
|
void _member_create();
|
||||||
|
void _member_cancel();
|
||||||
|
|
||||||
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
|
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
|
||||||
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
|
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
|
||||||
|
|
|
@ -479,7 +479,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
|
||||||
connecting_color = gn->get_connection_input_color(j);
|
connecting_color = gn->get_connection_input_color(j);
|
||||||
connecting_target = false;
|
connecting_target = false;
|
||||||
connecting_to = pos;
|
connecting_to = pos;
|
||||||
just_disconnected = true;
|
just_disconnected = false;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -550,11 +550,18 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
|
||||||
emit_signal("connection_request", from, from_slot, to, to_slot);
|
emit_signal("connection_request", from, from_slot, to, to_slot);
|
||||||
|
|
||||||
} else if (!just_disconnected) {
|
} else if (!just_disconnected) {
|
||||||
|
|
||||||
String from = connecting_from;
|
String from = connecting_from;
|
||||||
int from_slot = connecting_index;
|
int from_slot = connecting_index;
|
||||||
Vector2 ofs = Vector2(mb->get_position().x, mb->get_position().y);
|
Vector2 ofs = Vector2(mb->get_position().x, mb->get_position().y);
|
||||||
emit_signal("connection_to_empty", from, from_slot, ofs);
|
|
||||||
|
if (!connecting_out) {
|
||||||
|
emit_signal("connection_from_empty", from, from_slot, ofs);
|
||||||
|
} else {
|
||||||
|
emit_signal("connection_to_empty", from, from_slot, ofs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
connecting = false;
|
connecting = false;
|
||||||
top_layer->update();
|
top_layer->update();
|
||||||
update();
|
update();
|
||||||
|
@ -1292,6 +1299,7 @@ void GraphEdit::_bind_methods() {
|
||||||
ADD_SIGNAL(MethodInfo("duplicate_nodes_request"));
|
ADD_SIGNAL(MethodInfo("duplicate_nodes_request"));
|
||||||
ADD_SIGNAL(MethodInfo("node_selected", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
|
ADD_SIGNAL(MethodInfo("node_selected", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
|
||||||
ADD_SIGNAL(MethodInfo("connection_to_empty", PropertyInfo(Variant::STRING, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::VECTOR2, "release_position")));
|
ADD_SIGNAL(MethodInfo("connection_to_empty", PropertyInfo(Variant::STRING, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::VECTOR2, "release_position")));
|
||||||
|
ADD_SIGNAL(MethodInfo("connection_from_empty", PropertyInfo(Variant::STRING, "to"), PropertyInfo(Variant::INT, "to_slot"), PropertyInfo(Variant::VECTOR2, "release_position")));
|
||||||
ADD_SIGNAL(MethodInfo("delete_nodes_request"));
|
ADD_SIGNAL(MethodInfo("delete_nodes_request"));
|
||||||
ADD_SIGNAL(MethodInfo("_begin_node_move"));
|
ADD_SIGNAL(MethodInfo("_begin_node_move"));
|
||||||
ADD_SIGNAL(MethodInfo("_end_node_move"));
|
ADD_SIGNAL(MethodInfo("_end_node_move"));
|
||||||
|
|
|
@ -257,7 +257,7 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po
|
||||||
VisualShaderNode::PortType from_port_type = g->nodes[p_from_node].node->get_output_port_type(p_from_port);
|
VisualShaderNode::PortType from_port_type = g->nodes[p_from_node].node->get_output_port_type(p_from_port);
|
||||||
VisualShaderNode::PortType to_port_type = g->nodes[p_to_node].node->get_input_port_type(p_to_port);
|
VisualShaderNode::PortType to_port_type = g->nodes[p_to_node].node->get_input_port_type(p_to_port);
|
||||||
|
|
||||||
if (MAX(0, from_port_type - 2) != (MAX(0, to_port_type - 2))) {
|
if (!is_port_types_compatible(from_port_type, to_port_type)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,6 +271,10 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VisualShader::is_port_types_compatible(int p_a, int p_b) const {
|
||||||
|
return MAX(0, p_a - 2) == (MAX(0, p_b - 2));
|
||||||
|
}
|
||||||
|
|
||||||
void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
|
void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
|
||||||
ERR_FAIL_INDEX(p_type, TYPE_MAX);
|
ERR_FAIL_INDEX(p_type, TYPE_MAX);
|
||||||
Graph *g = &graph[p_type];
|
Graph *g = &graph[p_type];
|
||||||
|
@ -295,8 +299,8 @@ Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port,
|
||||||
VisualShaderNode::PortType from_port_type = g->nodes[p_from_node].node->get_output_port_type(p_from_port);
|
VisualShaderNode::PortType from_port_type = g->nodes[p_from_node].node->get_output_port_type(p_from_port);
|
||||||
VisualShaderNode::PortType to_port_type = g->nodes[p_to_node].node->get_input_port_type(p_to_port);
|
VisualShaderNode::PortType to_port_type = g->nodes[p_to_node].node->get_input_port_type(p_to_port);
|
||||||
|
|
||||||
if (MAX(0, from_port_type - 2) != (MAX(0, to_port_type - 2))) {
|
if (!is_port_types_compatible(from_port_type, to_port_type)) {
|
||||||
ERR_EXPLAIN("Incompatible port types (scalar/vec/bool with transform");
|
ERR_EXPLAIN("Incompatible port types (scalar/vec/bool) with transform");
|
||||||
ERR_FAIL_V(ERR_INVALID_PARAMETER);
|
ERR_FAIL_V(ERR_INVALID_PARAMETER);
|
||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,6 +138,7 @@ public:
|
||||||
Error connect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port);
|
Error connect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port);
|
||||||
void disconnect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port);
|
void disconnect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port);
|
||||||
void connect_nodes_forced(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port);
|
void connect_nodes_forced(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port);
|
||||||
|
bool is_port_types_compatible(int p_a, int p_b) const;
|
||||||
|
|
||||||
void rebuild();
|
void rebuild();
|
||||||
void get_node_connections(Type p_type, List<Connection> *r_connections) const;
|
void get_node_connections(Type p_type, List<Connection> *r_connections) const;
|
||||||
|
|
Loading…
Add table
Reference in a new issue