|
@@ -358,7 +358,9 @@ void VisualShaderEditor::_update_graph() {
|
|
for (int i = 0; i < graph->get_child_count(); i++) {
|
|
for (int i = 0; i < graph->get_child_count(); i++) {
|
|
|
|
|
|
if (Object::cast_to<GraphNode>(graph->get_child(i))) {
|
|
if (Object::cast_to<GraphNode>(graph->get_child(i))) {
|
|
- memdelete(graph->get_child(i));
|
|
|
|
|
|
+ Node *node = graph->get_child(i);
|
|
|
|
+ graph->remove_child(node);
|
|
|
|
+ memdelete(node);
|
|
i--;
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -377,13 +379,33 @@ void VisualShaderEditor::_update_graph() {
|
|
|
|
|
|
Vector<int> nodes = visual_shader->get_node_list(type);
|
|
Vector<int> nodes = visual_shader->get_node_list(type);
|
|
|
|
|
|
|
|
+ Control *offset;
|
|
|
|
+
|
|
for (int n_i = 0; n_i < nodes.size(); n_i++) {
|
|
for (int n_i = 0; n_i < nodes.size(); n_i++) {
|
|
|
|
|
|
Vector2 position = visual_shader->get_node_position(type, nodes[n_i]);
|
|
Vector2 position = visual_shader->get_node_position(type, nodes[n_i]);
|
|
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, nodes[n_i]);
|
|
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, nodes[n_i]);
|
|
|
|
|
|
|
|
+ Ref<VisualShaderNodeGroupBase> group_node = Object::cast_to<VisualShaderNodeGroupBase>(vsnode.ptr());
|
|
|
|
+ bool is_group = !group_node.is_null();
|
|
|
|
+ Size2 size = Size2(0, 0);
|
|
|
|
+
|
|
|
|
+ Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(group_node.ptr());
|
|
|
|
+ bool is_expression = !expression_node.is_null();
|
|
|
|
+ String expression = "";
|
|
|
|
+
|
|
GraphNode *node = memnew(GraphNode);
|
|
GraphNode *node = memnew(GraphNode);
|
|
|
|
|
|
|
|
+ if (is_group) {
|
|
|
|
+ size = group_node->get_size();
|
|
|
|
+
|
|
|
|
+ node->set_resizable(true);
|
|
|
|
+ node->connect("resize_request", this, "_node_resized", varray((int)type, nodes[n_i]));
|
|
|
|
+ }
|
|
|
|
+ if (is_expression) {
|
|
|
|
+ expression = expression_node->get_expression();
|
|
|
|
+ }
|
|
|
|
+
|
|
/*if (!vsnode->is_connected("changed", this, "_node_changed")) {
|
|
/*if (!vsnode->is_connected("changed", this, "_node_changed")) {
|
|
vsnode->connect("changed", this, "_node_changed", varray(vsnode->get_instance_id()), CONNECT_DEFERRED);
|
|
vsnode->connect("changed", this, "_node_changed", varray(vsnode->get_instance_id()), CONNECT_DEFERRED);
|
|
}*/
|
|
}*/
|
|
@@ -403,6 +425,10 @@ void VisualShaderEditor::_update_graph() {
|
|
Control *custom_editor = NULL;
|
|
Control *custom_editor = NULL;
|
|
int port_offset = 0;
|
|
int port_offset = 0;
|
|
|
|
|
|
|
|
+ if (is_group) {
|
|
|
|
+ port_offset++;
|
|
|
|
+ }
|
|
|
|
+
|
|
Ref<VisualShaderNodeUniform> uniform = vsnode;
|
|
Ref<VisualShaderNodeUniform> uniform = vsnode;
|
|
if (uniform.is_valid()) {
|
|
if (uniform.is_valid()) {
|
|
graph->add_child(node);
|
|
graph->add_child(node);
|
|
@@ -438,6 +464,24 @@ void VisualShaderEditor::_update_graph() {
|
|
custom_editor = NULL;
|
|
custom_editor = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (is_group) {
|
|
|
|
+ HBoxContainer *hb2 = memnew(HBoxContainer);
|
|
|
|
+
|
|
|
|
+ Button *add_input_btn = memnew(Button);
|
|
|
|
+ add_input_btn->set_text(TTR("Add input +"));
|
|
|
|
+ add_input_btn->connect("pressed", this, "_add_input_port", varray(nodes[n_i], group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "input" + itos(group_node->get_free_input_port_id())), CONNECT_DEFERRED);
|
|
|
|
+ hb2->add_child(add_input_btn);
|
|
|
|
+
|
|
|
|
+ hb2->add_spacer();
|
|
|
|
+
|
|
|
|
+ Button *add_output_btn = memnew(Button);
|
|
|
|
+ add_output_btn->set_text(TTR("Add output +"));
|
|
|
|
+ add_output_btn->connect("pressed", this, "_add_output_port", varray(nodes[n_i], group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "output" + itos(group_node->get_free_output_port_id())), CONNECT_DEFERRED);
|
|
|
|
+ hb2->add_child(add_output_btn);
|
|
|
|
+
|
|
|
|
+ node->add_child(hb2);
|
|
|
|
+ }
|
|
|
|
+
|
|
for (int i = 0; i < MAX(vsnode->get_input_port_count(), vsnode->get_output_port_count()); i++) {
|
|
for (int i = 0; i < MAX(vsnode->get_input_port_count(), vsnode->get_output_port_count()); i++) {
|
|
|
|
|
|
if (vsnode->is_port_separator(i)) {
|
|
if (vsnode->is_port_separator(i)) {
|
|
@@ -507,21 +551,75 @@ void VisualShaderEditor::_update_graph() {
|
|
|
|
|
|
if (valid_left) {
|
|
if (valid_left) {
|
|
|
|
|
|
- Label *label = memnew(Label);
|
|
|
|
- label->set_text(name_left);
|
|
|
|
- label->add_style_override("normal", label_style); //more compact
|
|
|
|
- hb->add_child(label);
|
|
|
|
|
|
+ if (is_group) {
|
|
|
|
+
|
|
|
|
+ OptionButton *type_box = memnew(OptionButton);
|
|
|
|
+ hb->add_child(type_box);
|
|
|
|
+ type_box->add_item(TTR("Scalar"));
|
|
|
|
+ type_box->add_item(TTR("Vector"));
|
|
|
|
+ type_box->add_item(TTR("Boolean"));
|
|
|
|
+ type_box->add_item(TTR("Transform"));
|
|
|
|
+ type_box->select(group_node->get_input_port_type(i));
|
|
|
|
+ type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
|
|
|
|
+ type_box->connect("item_selected", this, "_change_input_port_type", varray(nodes[n_i], i), CONNECT_DEFERRED);
|
|
|
|
+
|
|
|
|
+ LineEdit *name_box = memnew(LineEdit);
|
|
|
|
+ hb->add_child(name_box);
|
|
|
|
+ name_box->set_custom_minimum_size(Size2(60 * EDSCALE, 0));
|
|
|
|
+ name_box->set_text(name_left);
|
|
|
|
+ name_box->set_expand_to_text_length(true);
|
|
|
|
+ name_box->connect("text_entered", this, "_change_input_port_name", varray(name_box, nodes[n_i], i));
|
|
|
|
+ name_box->connect("focus_exited", this, "_port_name_focus_out", varray(name_box, nodes[n_i], i, false));
|
|
|
|
+
|
|
|
|
+ if (is_group) {
|
|
|
|
+ Button *remove_btn = memnew(Button);
|
|
|
|
+ remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons"));
|
|
|
|
+ remove_btn->set_tooltip(TTR("Remove") + " " + name_left);
|
|
|
|
+ remove_btn->connect("pressed", this, "_remove_input_port", varray(nodes[n_i], i), CONNECT_DEFERRED);
|
|
|
|
+ hb->add_child(remove_btn);
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ Label *label = memnew(Label);
|
|
|
|
+ label->set_text(name_left);
|
|
|
|
+ label->add_style_override("normal", label_style); //more compact
|
|
|
|
+ hb->add_child(label);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
hb->add_spacer();
|
|
hb->add_spacer();
|
|
|
|
|
|
if (valid_right) {
|
|
if (valid_right) {
|
|
-
|
|
|
|
- Label *label = memnew(Label);
|
|
|
|
- label->set_text(name_right);
|
|
|
|
- label->set_align(Label::ALIGN_RIGHT);
|
|
|
|
- label->add_style_override("normal", label_style); //more compact
|
|
|
|
- hb->add_child(label);
|
|
|
|
|
|
+ if (is_group) {
|
|
|
|
+ Button *remove_btn = memnew(Button);
|
|
|
|
+ remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons"));
|
|
|
|
+ remove_btn->set_tooltip(TTR("Remove") + " " + name_left);
|
|
|
|
+ remove_btn->connect("pressed", this, "_remove_output_port", varray(nodes[n_i], i), CONNECT_DEFERRED);
|
|
|
|
+ hb->add_child(remove_btn);
|
|
|
|
+
|
|
|
|
+ LineEdit *name_box = memnew(LineEdit);
|
|
|
|
+ hb->add_child(name_box);
|
|
|
|
+ name_box->set_custom_minimum_size(Size2(60 * EDSCALE, 0));
|
|
|
|
+ name_box->set_text(name_right);
|
|
|
|
+ name_box->set_expand_to_text_length(true);
|
|
|
|
+ name_box->connect("text_entered", this, "_change_output_port_name", varray(name_box, nodes[n_i], i));
|
|
|
|
+ name_box->connect("focus_exited", this, "_port_name_focus_out", varray(name_box, nodes[n_i], i, true));
|
|
|
|
+
|
|
|
|
+ OptionButton *type_box = memnew(OptionButton);
|
|
|
|
+ hb->add_child(type_box);
|
|
|
|
+ type_box->add_item(TTR("Scalar"));
|
|
|
|
+ type_box->add_item(TTR("Vector"));
|
|
|
|
+ type_box->add_item(TTR("Boolean"));
|
|
|
|
+ type_box->add_item(TTR("Transform"));
|
|
|
|
+ type_box->select(group_node->get_output_port_type(i));
|
|
|
|
+ type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
|
|
|
|
+ type_box->connect("item_selected", this, "_change_output_port_type", varray(nodes[n_i], i), CONNECT_DEFERRED);
|
|
|
|
+ } else {
|
|
|
|
+ Label *label = memnew(Label);
|
|
|
|
+ label->set_text(name_right);
|
|
|
|
+ label->add_style_override("normal", label_style); //more compact
|
|
|
|
+ hb->add_child(label);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -540,18 +638,33 @@ void VisualShaderEditor::_update_graph() {
|
|
hb->add_child(preview);
|
|
hb->add_child(preview);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (is_group) {
|
|
|
|
+ offset = memnew(Control);
|
|
|
|
+ offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
|
|
|
|
+ node->add_child(offset);
|
|
|
|
+ port_offset++;
|
|
|
|
+ }
|
|
|
|
+
|
|
node->add_child(hb);
|
|
node->add_child(hb);
|
|
|
|
|
|
node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]);
|
|
node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]);
|
|
}
|
|
}
|
|
|
|
|
|
if (vsnode->get_output_port_for_preview() >= 0 && vsnode->get_output_port_type(vsnode->get_output_port_for_preview()) != VisualShaderNode::PORT_TYPE_TRANSFORM) {
|
|
if (vsnode->get_output_port_for_preview() >= 0 && vsnode->get_output_port_type(vsnode->get_output_port_for_preview()) != VisualShaderNode::PORT_TYPE_TRANSFORM) {
|
|
|
|
+ offset = memnew(Control);
|
|
|
|
+ offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
|
|
|
|
+ node->add_child(offset);
|
|
|
|
+
|
|
VisualShaderNodePortPreview *port_preview = memnew(VisualShaderNodePortPreview);
|
|
VisualShaderNodePortPreview *port_preview = memnew(VisualShaderNodePortPreview);
|
|
port_preview->setup(visual_shader, type, nodes[n_i], vsnode->get_output_port_for_preview());
|
|
port_preview->setup(visual_shader, type, nodes[n_i], vsnode->get_output_port_for_preview());
|
|
port_preview->set_h_size_flags(SIZE_SHRINK_CENTER);
|
|
port_preview->set_h_size_flags(SIZE_SHRINK_CENTER);
|
|
node->add_child(port_preview);
|
|
node->add_child(port_preview);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ offset = memnew(Control);
|
|
|
|
+ offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
|
|
|
|
+ node->add_child(offset);
|
|
|
|
+
|
|
String error = vsnode->get_warning(visual_shader->get_mode(), type);
|
|
String error = vsnode->get_warning(visual_shader->get_mode(), type);
|
|
if (error != String()) {
|
|
if (error != String()) {
|
|
Label *error_label = memnew(Label);
|
|
Label *error_label = memnew(Label);
|
|
@@ -560,9 +673,42 @@ void VisualShaderEditor::_update_graph() {
|
|
node->add_child(error_label);
|
|
node->add_child(error_label);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (is_expression) {
|
|
|
|
+
|
|
|
|
+ TextEdit *expression_box = memnew(TextEdit);
|
|
|
|
+ expression_node->set_control(expression_box, 0);
|
|
|
|
+ node->add_child(expression_box);
|
|
|
|
+
|
|
|
|
+ Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
|
|
|
|
+ Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
|
|
|
|
+ Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
|
|
|
|
+ Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color");
|
|
|
|
+
|
|
|
|
+ expression_box->set_syntax_coloring(true);
|
|
|
|
+
|
|
|
|
+ for (List<String>::Element *E = keyword_list.front(); E; E = E->next()) {
|
|
|
|
+
|
|
|
|
+ expression_box->add_keyword_color(E->get(), keyword_color);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ expression_box->add_font_override("font", get_font("expression", "EditorFonts"));
|
|
|
|
+ expression_box->add_color_override("font_color", text_color);
|
|
|
|
+ expression_box->add_color_override("symbol_color", symbol_color);
|
|
|
|
+ expression_box->add_color_region("/*", "*/", comment_color, false);
|
|
|
|
+ expression_box->add_color_region("//", "", comment_color, false);
|
|
|
|
+
|
|
|
|
+ expression_box->set_text(expression);
|
|
|
|
+ expression_box->set_context_menu_enabled(false);
|
|
|
|
+ expression_box->set_show_line_numbers(true);
|
|
|
|
+
|
|
|
|
+ expression_box->connect("text_changed", this, "_set_expression", varray(nodes[n_i]), CONNECT_DEFERRED);
|
|
|
|
+ }
|
|
|
|
+
|
|
if (!uniform.is_valid()) {
|
|
if (!uniform.is_valid()) {
|
|
graph->add_child(node);
|
|
graph->add_child(node);
|
|
_update_created_node(node);
|
|
_update_created_node(node);
|
|
|
|
+ if (is_group)
|
|
|
|
+ call_deferred("_set_node_size", (int)type, nodes[n_i], size);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -577,6 +723,290 @@ void VisualShaderEditor::_update_graph() {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void VisualShaderEditor::_add_input_port(int p_node, int p_port, int p_port_type, const String &p_name) {
|
|
|
|
+
|
|
|
|
+ VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
|
|
+ Ref<VisualShaderNodeExpression> node = visual_shader->get_node(type, p_node);
|
|
|
|
+ if (node.is_null()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ undo_redo->create_action(TTR("Add input port"));
|
|
|
|
+ undo_redo->add_do_method(node.ptr(), "add_input_port", p_port, p_port_type, p_name);
|
|
|
|
+ undo_redo->add_undo_method(node.ptr(), "remove_input_port", p_port);
|
|
|
|
+ undo_redo->add_do_method(this, "_update_graph");
|
|
|
|
+ undo_redo->add_undo_method(this, "_update_graph");
|
|
|
|
+ undo_redo->add_do_method(this, "_rebuild");
|
|
|
|
+ undo_redo->add_undo_method(this, "_rebuild");
|
|
|
|
+ undo_redo->commit_action();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void VisualShaderEditor::_add_output_port(int p_node, int p_port, int p_port_type, const String &p_name) {
|
|
|
|
+
|
|
|
|
+ VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
|
|
+ Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
|
|
|
|
+ if (node.is_null()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ undo_redo->create_action(TTR("Add output port"));
|
|
|
|
+ undo_redo->add_do_method(node.ptr(), "add_output_port", p_port, p_port_type, p_name);
|
|
|
|
+ undo_redo->add_undo_method(node.ptr(), "remove_output_port", p_port);
|
|
|
|
+ undo_redo->add_do_method(this, "_update_graph");
|
|
|
|
+ undo_redo->add_undo_method(this, "_update_graph");
|
|
|
|
+ undo_redo->add_do_method(this, "_rebuild");
|
|
|
|
+ undo_redo->add_undo_method(this, "_rebuild");
|
|
|
|
+ undo_redo->commit_action();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void VisualShaderEditor::_change_input_port_type(int p_type, int p_node, int p_port) {
|
|
|
|
+
|
|
|
|
+ VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
|
|
+ Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
|
|
|
|
+ if (node.is_null()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ undo_redo->create_action(TTR("Change input port type"));
|
|
|
|
+ undo_redo->add_do_method(node.ptr(), "set_input_port_type", p_port, p_type);
|
|
|
|
+ undo_redo->add_undo_method(node.ptr(), "set_input_port_type", p_port, node->get_input_port_type(p_port));
|
|
|
|
+ undo_redo->add_do_method(this, "_update_graph");
|
|
|
|
+ undo_redo->add_undo_method(this, "_update_graph");
|
|
|
|
+ undo_redo->add_do_method(this, "_rebuild");
|
|
|
|
+ undo_redo->add_undo_method(this, "_rebuild");
|
|
|
|
+ undo_redo->commit_action();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void VisualShaderEditor::_change_output_port_type(int p_type, int p_node, int p_port) {
|
|
|
|
+
|
|
|
|
+ VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
|
|
+ Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
|
|
|
|
+ if (node.is_null()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ undo_redo->create_action(TTR("Change output port type"));
|
|
|
|
+ undo_redo->add_do_method(node.ptr(), "set_output_port_type", p_port, p_type);
|
|
|
|
+ undo_redo->add_undo_method(node.ptr(), "set_output_port_type", p_port, node->get_output_port_type(p_port));
|
|
|
|
+ undo_redo->add_do_method(this, "_update_graph");
|
|
|
|
+ undo_redo->add_undo_method(this, "_update_graph");
|
|
|
|
+ undo_redo->add_do_method(this, "_rebuild");
|
|
|
|
+ undo_redo->add_undo_method(this, "_rebuild");
|
|
|
|
+ undo_redo->commit_action();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void VisualShaderEditor::_change_input_port_name(const String &p_text, Object *line_edit, int p_node_id, int p_port_id) {
|
|
|
|
+
|
|
|
|
+ VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
|
|
+
|
|
|
|
+ Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id);
|
|
|
|
+ ERR_FAIL_COND(!node.is_valid());
|
|
|
|
+
|
|
|
|
+ undo_redo->create_action(TTR("Change input port name"));
|
|
|
|
+ undo_redo->add_do_method(node.ptr(), "set_input_port_name", p_port_id, p_text);
|
|
|
|
+ undo_redo->add_undo_method(node.ptr(), "set_input_port_name", p_port_id, node->get_input_port_name(p_port_id));
|
|
|
|
+ undo_redo->add_do_method(this, "_rebuild");
|
|
|
|
+ undo_redo->add_undo_method(this, "_rebuild");
|
|
|
|
+ undo_redo->commit_action();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void VisualShaderEditor::_change_output_port_name(const String &p_text, Object *line_edit, int p_node_id, int p_port_id) {
|
|
|
|
+
|
|
|
|
+ VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
|
|
+
|
|
|
|
+ Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id);
|
|
|
|
+ ERR_FAIL_COND(!node.is_valid());
|
|
|
|
+
|
|
|
|
+ undo_redo->create_action(TTR("Change output port name"));
|
|
|
|
+ undo_redo->add_do_method(node.ptr(), "set_output_port_name", p_port_id, p_text);
|
|
|
|
+ undo_redo->add_undo_method(node.ptr(), "set_output_port_name", p_port_id, node->get_output_port_name(p_port_id));
|
|
|
|
+ undo_redo->add_do_method(this, "_rebuild");
|
|
|
|
+ undo_redo->add_undo_method(this, "_rebuild");
|
|
|
|
+ undo_redo->commit_action();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void VisualShaderEditor::_remove_input_port(int p_node, int p_port) {
|
|
|
|
+
|
|
|
|
+ VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
|
|
+ Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
|
|
|
|
+ if (node.is_null()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ undo_redo->create_action(TTR("Remove input port"));
|
|
|
|
+
|
|
|
|
+ List<VisualShader::Connection> conns;
|
|
|
|
+ visual_shader->get_node_connections(type, &conns);
|
|
|
|
+ for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
|
|
|
|
+
|
|
|
|
+ int from_node = E->get().from_node;
|
|
|
|
+ int from_port = E->get().from_port;
|
|
|
|
+ int to_node = E->get().to_node;
|
|
|
|
+ int to_port = E->get().to_port;
|
|
|
|
+
|
|
|
|
+ if (to_node == p_node) {
|
|
|
|
+ if (to_port == p_port) {
|
|
|
|
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
|
|
|
|
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port);
|
|
|
|
+ } else if (to_port > p_port) {
|
|
|
|
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
|
|
|
|
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port);
|
|
|
|
+
|
|
|
|
+ undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port - 1);
|
|
|
|
+ undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port - 1);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ undo_redo->add_do_method(node.ptr(), "remove_input_port", p_port);
|
|
|
|
+ undo_redo->add_undo_method(node.ptr(), "add_input_port", p_port, (int)node->get_input_port_type(p_port), node->get_input_port_name(p_port));
|
|
|
|
+
|
|
|
|
+ undo_redo->add_do_method(this, "_update_graph");
|
|
|
|
+ undo_redo->add_undo_method(this, "_update_graph");
|
|
|
|
+
|
|
|
|
+ undo_redo->add_do_method(this, "_rebuild");
|
|
|
|
+ undo_redo->add_undo_method(this, "_rebuild");
|
|
|
|
+
|
|
|
|
+ undo_redo->commit_action();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void VisualShaderEditor::_remove_output_port(int p_node, int p_port) {
|
|
|
|
+
|
|
|
|
+ VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
|
|
+ Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
|
|
|
|
+ if (node.is_null()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ undo_redo->create_action(TTR("Remove output port"));
|
|
|
|
+
|
|
|
|
+ List<VisualShader::Connection> conns;
|
|
|
|
+ visual_shader->get_node_connections(type, &conns);
|
|
|
|
+ for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
|
|
|
|
+
|
|
|
|
+ int from_node = E->get().from_node;
|
|
|
|
+ int from_port = E->get().from_port;
|
|
|
|
+ int to_node = E->get().to_node;
|
|
|
|
+ int to_port = E->get().to_port;
|
|
|
|
+
|
|
|
|
+ if (from_node == p_node) {
|
|
|
|
+ if (from_port == p_port) {
|
|
|
|
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
|
|
|
|
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port);
|
|
|
|
+ } else if (from_port > p_port) {
|
|
|
|
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
|
|
|
|
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port);
|
|
|
|
+
|
|
|
|
+ undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port - 1, to_node, to_port);
|
|
|
|
+ undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port - 1, to_node, to_port);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ undo_redo->add_do_method(node.ptr(), "remove_output_port", p_port);
|
|
|
|
+ undo_redo->add_undo_method(node.ptr(), "add_output_port", p_port, (int)node->get_output_port_type(p_port), node->get_output_port_name(p_port));
|
|
|
|
+
|
|
|
|
+ undo_redo->add_do_method(this, "_update_graph");
|
|
|
|
+ undo_redo->add_undo_method(this, "_update_graph");
|
|
|
|
+
|
|
|
|
+ undo_redo->add_do_method(this, "_rebuild");
|
|
|
|
+ undo_redo->add_undo_method(this, "_rebuild");
|
|
|
|
+
|
|
|
|
+ undo_redo->commit_action();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void VisualShaderEditor::_set_expression(int p_node) {
|
|
|
|
+
|
|
|
|
+ VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
|
|
+ Ref<VisualShaderNodeExpression> node = visual_shader->get_node(type, p_node);
|
|
|
|
+ if (node.is_null()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ TextEdit *expression_box = Object::cast_to<TextEdit>(node->get_control(0));
|
|
|
|
+
|
|
|
|
+ undo_redo->create_action(TTR("Set expression"));
|
|
|
|
+ undo_redo->add_do_method(node.ptr(), "set_expression", expression_box->get_text());
|
|
|
|
+ undo_redo->add_undo_method(node.ptr(), "set_expression", node->get_expression());
|
|
|
|
+ undo_redo->add_do_method(this, "_start_rebuild_timer", 1.0);
|
|
|
|
+ undo_redo->add_undo_method(this, "_rebuild");
|
|
|
|
+ undo_redo->commit_action();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void VisualShaderEditor::_start_rebuild_timer(int p_delay) {
|
|
|
|
+ build_timer->start(p_delay);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void VisualShaderEditor::_rebuild_timeout() {
|
|
|
|
+ _rebuild();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void VisualShaderEditor::_rebuild() {
|
|
|
|
+ EditorNode::get_singleton()->get_log()->clear();
|
|
|
|
+ visual_shader->rebuild();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void VisualShaderEditor::_set_node_size(int p_type, int p_node, const Vector2 &p_size) {
|
|
|
|
+
|
|
|
|
+ VisualShader::Type type = VisualShader::Type(p_type);
|
|
|
|
+ Ref<VisualShaderNode> node = visual_shader->get_node(type, p_node);
|
|
|
|
+ if (node.is_null()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Ref<VisualShaderNodeGroupBase> group_node = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr());
|
|
|
|
+
|
|
|
|
+ if (group_node.is_null()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Vector2 size = p_size;
|
|
|
|
+
|
|
|
|
+ group_node->set_size(size);
|
|
|
|
+
|
|
|
|
+ GraphNode *gn = NULL;
|
|
|
|
+ if (edit_type->get_selected() == p_type) { // check - otherwise the error will be emitted
|
|
|
|
+ Node *node2 = graph->get_node(itos(p_node));
|
|
|
|
+ gn = Object::cast_to<GraphNode>(node2);
|
|
|
|
+ if (!gn)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ gn->set_custom_minimum_size(size);
|
|
|
|
+ gn->set_size(Size2(1, 1));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
|
|
|
|
+ if (!expression_node.is_null()) {
|
|
|
|
+ Control *text_box = expression_node->get_control(0);
|
|
|
|
+ Size2 box_size = size;
|
|
|
|
+ if (gn != NULL) {
|
|
|
|
+ if (box_size.x < 150 * EDSCALE || box_size.y < 0) {
|
|
|
|
+ box_size.x = gn->get_size().x;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ box_size.x -= text_box->get_margin(Margin::MARGIN_LEFT);
|
|
|
|
+ box_size.x -= 28 * EDSCALE;
|
|
|
|
+ box_size.y -= text_box->get_margin(Margin::MARGIN_TOP);
|
|
|
|
+ box_size.y -= 28 * EDSCALE;
|
|
|
|
+ text_box->set_custom_minimum_size(Size2(box_size.x, box_size.y));
|
|
|
|
+ text_box->set_size(Size2(1, 1));
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void VisualShaderEditor::_node_resized(const Vector2 &p_new_size, int p_type, int p_node) {
|
|
|
|
+
|
|
|
|
+ VisualShader::Type type = VisualShader::Type(p_type);
|
|
|
|
+ Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
|
|
|
|
+ if (node.is_null()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ undo_redo->create_action(TTR("Resize VisualShader node"), UndoRedo::MERGE_ENDS);
|
|
|
|
+ undo_redo->add_do_method(this, "_set_node_size", p_type, p_node, p_new_size / EDSCALE);
|
|
|
|
+ undo_redo->add_undo_method(this, "_set_node_size", p_type, p_node, node->get_size());
|
|
|
|
+ undo_redo->commit_action();
|
|
|
|
+}
|
|
|
|
+
|
|
void VisualShaderEditor::_preview_select_port(int p_node, int p_port) {
|
|
void VisualShaderEditor::_preview_select_port(int p_node, int p_port) {
|
|
|
|
|
|
VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
@@ -623,6 +1053,52 @@ void VisualShaderEditor::_line_edit_focus_out(Object *line_edit, int p_node_id)
|
|
_line_edit_changed(text, line_edit, p_node_id);
|
|
_line_edit_changed(text, line_edit, p_node_id);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void VisualShaderEditor::_port_name_focus_out(Object *line_edit, int p_node_id, int p_port_id, bool p_output) {
|
|
|
|
+
|
|
|
|
+ VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
|
|
+
|
|
|
|
+ Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id);
|
|
|
|
+ ERR_FAIL_COND(!node.is_valid());
|
|
|
|
+
|
|
|
|
+ String text = Object::cast_to<LineEdit>(line_edit)->get_text();
|
|
|
|
+
|
|
|
|
+ if (!p_output) {
|
|
|
|
+ if (node->get_input_port_name(p_port_id) == text)
|
|
|
|
+ return;
|
|
|
|
+ } else {
|
|
|
|
+ if (node->get_output_port_name(p_port_id) == text)
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ List<String> input_names;
|
|
|
|
+ List<String> output_names;
|
|
|
|
+
|
|
|
|
+ for (int i = 0; i < node->get_input_port_count(); i++) {
|
|
|
|
+ if (!p_output && i == p_port_id) continue;
|
|
|
|
+ input_names.push_back(node->get_input_port_name(i));
|
|
|
|
+ }
|
|
|
|
+ for (int i = 0; i < node->get_output_port_count(); i++) {
|
|
|
|
+ if (p_output && i == p_port_id) continue;
|
|
|
|
+ output_names.push_back(node->get_output_port_name(i));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ String validated_name = visual_shader->validate_port_name(text, input_names, output_names);
|
|
|
|
+ if (validated_name == "") {
|
|
|
|
+ if (!p_output) {
|
|
|
|
+ Object::cast_to<LineEdit>(line_edit)->set_text(node->get_input_port_name(p_port_id));
|
|
|
|
+ } else {
|
|
|
|
+ Object::cast_to<LineEdit>(line_edit)->set_text(node->get_output_port_name(p_port_id));
|
|
|
|
+ }
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!p_output) {
|
|
|
|
+ _change_input_port_name(validated_name, line_edit, p_node_id, p_port_id);
|
|
|
|
+ } else {
|
|
|
|
+ _change_output_port_name(validated_name, line_edit, p_node_id, p_port_id);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
void VisualShaderEditor::_port_edited() {
|
|
void VisualShaderEditor::_port_edited() {
|
|
|
|
|
|
VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
@@ -757,6 +1233,12 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
|
|
undo_redo->create_action(TTR("Add Node to Visual Shader"));
|
|
undo_redo->create_action(TTR("Add Node to Visual Shader"));
|
|
undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, vsnode, position, id_to_use);
|
|
undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, vsnode, position, id_to_use);
|
|
undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_to_use);
|
|
undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_to_use);
|
|
|
|
+
|
|
|
|
+ VisualShaderNodeExpression *expr = Object::cast_to<VisualShaderNodeExpression>(vsnode.ptr());
|
|
|
|
+ if (expr) {
|
|
|
|
+ undo_redo->add_do_method(expr, "set_size", Size2(250 * EDSCALE, 150 * EDSCALE));
|
|
|
|
+ }
|
|
|
|
+
|
|
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();
|
|
@@ -831,10 +1313,25 @@ void VisualShaderEditor::_connection_to_empty(const String &p_from, int p_from_s
|
|
void VisualShaderEditor::_delete_request(int which) {
|
|
void VisualShaderEditor::_delete_request(int which) {
|
|
|
|
|
|
VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
|
|
|
|
+ Ref<VisualShaderNode> node = Ref<VisualShaderNode>(visual_shader->get_node(type, which));
|
|
|
|
|
|
undo_redo->create_action(TTR("Delete Node"));
|
|
undo_redo->create_action(TTR("Delete Node"));
|
|
undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, which);
|
|
undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, which);
|
|
- undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, visual_shader->get_node(type, which), visual_shader->get_node_position(type, which), which);
|
|
|
|
|
|
+ undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, which), which);
|
|
|
|
+
|
|
|
|
+ // restore size, inputs and outputs if node is group
|
|
|
|
+ VisualShaderNodeGroupBase *group = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr());
|
|
|
|
+ if (group) {
|
|
|
|
+ undo_redo->add_undo_method(group, "set_size", group->get_size());
|
|
|
|
+ undo_redo->add_undo_method(group, "set_inputs", group->get_inputs());
|
|
|
|
+ undo_redo->add_undo_method(group, "set_outputs", group->get_outputs());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // restore expression text if node is expression
|
|
|
|
+ VisualShaderNodeExpression *expression = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
|
|
|
|
+ if (expression) {
|
|
|
|
+ undo_redo->add_undo_method(expression, "set_expression", expression->get_expression());
|
|
|
|
+ }
|
|
|
|
|
|
List<VisualShader::Connection> conns;
|
|
List<VisualShader::Connection> conns;
|
|
visual_shader->get_node_connections(type, &conns);
|
|
visual_shader->get_node_connections(type, &conns);
|
|
@@ -1022,6 +1519,19 @@ void VisualShaderEditor::_duplicate_nodes() {
|
|
undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, dupli, visual_shader->get_node_position(type, E->get()) + Vector2(10, 10) * EDSCALE, id_from);
|
|
undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, dupli, visual_shader->get_node_position(type, E->get()) + Vector2(10, 10) * EDSCALE, id_from);
|
|
undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_from);
|
|
undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_from);
|
|
|
|
|
|
|
|
+ // duplicate size, inputs and outputs if node is group
|
|
|
|
+ Ref<VisualShaderNodeGroupBase> group = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr());
|
|
|
|
+ if (!group.is_null()) {
|
|
|
|
+ undo_redo->add_do_method(dupli.ptr(), "set_size", group->get_size());
|
|
|
|
+ undo_redo->add_do_method(dupli.ptr(), "set_inputs", group->get_inputs());
|
|
|
|
+ undo_redo->add_do_method(dupli.ptr(), "set_outputs", group->get_outputs());
|
|
|
|
+ }
|
|
|
|
+ // duplicate expression text if node is expression
|
|
|
|
+ Ref<VisualShaderNodeExpression> expression = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
|
|
|
|
+ if (!expression.is_null()) {
|
|
|
|
+ undo_redo->add_do_method(dupli.ptr(), "set_expression", expression->get_expression());
|
|
|
|
+ }
|
|
|
|
+
|
|
id_from++;
|
|
id_from++;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1030,7 +1540,7 @@ void VisualShaderEditor::_duplicate_nodes() {
|
|
|
|
|
|
for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
|
|
for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
|
|
if (connection_remap.has(E->get().from_node) && connection_remap.has(E->get().to_node)) {
|
|
if (connection_remap.has(E->get().from_node) && connection_remap.has(E->get().to_node)) {
|
|
- undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port);
|
|
|
|
|
|
+ undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1073,8 +1583,25 @@ void VisualShaderEditor::_on_nodes_delete() {
|
|
undo_redo->create_action(TTR("Delete Nodes"));
|
|
undo_redo->create_action(TTR("Delete Nodes"));
|
|
|
|
|
|
for (List<int>::Element *F = to_erase.front(); F; F = F->next()) {
|
|
for (List<int>::Element *F = to_erase.front(); F; F = F->next()) {
|
|
|
|
+
|
|
|
|
+ Ref<VisualShaderNode> node = visual_shader->get_node(type, F->get());
|
|
|
|
+
|
|
undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, F->get());
|
|
undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, F->get());
|
|
- undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, visual_shader->get_node(type, F->get()), visual_shader->get_node_position(type, F->get()), F->get());
|
|
|
|
|
|
+ undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, F->get()), F->get());
|
|
|
|
+
|
|
|
|
+ // restore size, inputs and outputs if node is group
|
|
|
|
+ VisualShaderNodeGroupBase *group = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr());
|
|
|
|
+ if (group) {
|
|
|
|
+ undo_redo->add_undo_method(group, "set_size", group->get_size());
|
|
|
|
+ undo_redo->add_undo_method(group, "set_inputs", group->get_inputs());
|
|
|
|
+ undo_redo->add_undo_method(group, "set_outputs", group->get_outputs());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // restore expression text if node is expression
|
|
|
|
+ VisualShaderNodeExpression *expression = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
|
|
|
|
+ if (expression) {
|
|
|
|
+ undo_redo->add_undo_method(expression, "set_expression", expression->get_expression());
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
List<VisualShader::Connection> conns;
|
|
List<VisualShader::Connection> conns;
|
|
@@ -1267,8 +1794,12 @@ void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
|
|
}
|
|
}
|
|
|
|
|
|
void VisualShaderEditor::_bind_methods() {
|
|
void VisualShaderEditor::_bind_methods() {
|
|
|
|
+ ClassDB::bind_method("_rebuild", &VisualShaderEditor::_rebuild);
|
|
ClassDB::bind_method("_update_graph", &VisualShaderEditor::_update_graph);
|
|
ClassDB::bind_method("_update_graph", &VisualShaderEditor::_update_graph);
|
|
ClassDB::bind_method("_update_options_menu", &VisualShaderEditor::_update_options_menu);
|
|
ClassDB::bind_method("_update_options_menu", &VisualShaderEditor::_update_options_menu);
|
|
|
|
+ ClassDB::bind_method("_start_rebuild_timer", &VisualShaderEditor::_start_rebuild_timer);
|
|
|
|
+ ClassDB::bind_method("_set_expression", &VisualShaderEditor::_set_expression);
|
|
|
|
+ ClassDB::bind_method("_rebuild_timeout", &VisualShaderEditor::_rebuild_timeout);
|
|
ClassDB::bind_method("_add_node", &VisualShaderEditor::_add_node);
|
|
ClassDB::bind_method("_add_node", &VisualShaderEditor::_add_node);
|
|
ClassDB::bind_method("_node_dragged", &VisualShaderEditor::_node_dragged);
|
|
ClassDB::bind_method("_node_dragged", &VisualShaderEditor::_node_dragged);
|
|
ClassDB::bind_method("_connection_request", &VisualShaderEditor::_connection_request);
|
|
ClassDB::bind_method("_connection_request", &VisualShaderEditor::_connection_request);
|
|
@@ -1283,11 +1814,22 @@ void VisualShaderEditor::_bind_methods() {
|
|
ClassDB::bind_method("_connection_to_empty", &VisualShaderEditor::_connection_to_empty);
|
|
ClassDB::bind_method("_connection_to_empty", &VisualShaderEditor::_connection_to_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("_duplicate_nodes", &VisualShaderEditor::_duplicate_nodes);
|
|
ClassDB::bind_method("_duplicate_nodes", &VisualShaderEditor::_duplicate_nodes);
|
|
ClassDB::bind_method("_mode_selected", &VisualShaderEditor::_mode_selected);
|
|
ClassDB::bind_method("_mode_selected", &VisualShaderEditor::_mode_selected);
|
|
ClassDB::bind_method("_input_select_item", &VisualShaderEditor::_input_select_item);
|
|
ClassDB::bind_method("_input_select_item", &VisualShaderEditor::_input_select_item);
|
|
ClassDB::bind_method("_preview_select_port", &VisualShaderEditor::_preview_select_port);
|
|
ClassDB::bind_method("_preview_select_port", &VisualShaderEditor::_preview_select_port);
|
|
ClassDB::bind_method("_graph_gui_input", &VisualShaderEditor::_graph_gui_input);
|
|
ClassDB::bind_method("_graph_gui_input", &VisualShaderEditor::_graph_gui_input);
|
|
|
|
+ ClassDB::bind_method("_add_input_port", &VisualShaderEditor::_add_input_port);
|
|
|
|
+ ClassDB::bind_method("_change_input_port_type", &VisualShaderEditor::_change_input_port_type);
|
|
|
|
+ ClassDB::bind_method("_change_input_port_name", &VisualShaderEditor::_change_input_port_name);
|
|
|
|
+ ClassDB::bind_method("_remove_input_port", &VisualShaderEditor::_remove_input_port);
|
|
|
|
+ ClassDB::bind_method("_add_output_port", &VisualShaderEditor::_add_output_port);
|
|
|
|
+ ClassDB::bind_method("_change_output_port_type", &VisualShaderEditor::_change_output_port_type);
|
|
|
|
+ ClassDB::bind_method("_change_output_port_name", &VisualShaderEditor::_change_output_port_name);
|
|
|
|
+ ClassDB::bind_method("_remove_output_port", &VisualShaderEditor::_remove_output_port);
|
|
|
|
+ ClassDB::bind_method("_node_resized", &VisualShaderEditor::_node_resized);
|
|
|
|
+ ClassDB::bind_method("_set_node_size", &VisualShaderEditor::_set_node_size);
|
|
|
|
|
|
ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &VisualShaderEditor::get_drag_data_fw);
|
|
ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &VisualShaderEditor::get_drag_data_fw);
|
|
ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &VisualShaderEditor::can_drop_data_fw);
|
|
ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &VisualShaderEditor::can_drop_data_fw);
|
|
@@ -1311,6 +1853,7 @@ VisualShaderEditor::VisualShaderEditor() {
|
|
updating = false;
|
|
updating = false;
|
|
saved_node_pos_dirty = false;
|
|
saved_node_pos_dirty = false;
|
|
saved_node_pos = Point2(0, 0);
|
|
saved_node_pos = Point2(0, 0);
|
|
|
|
+ ShaderLanguage::get_keyword_list(&keyword_list);
|
|
|
|
|
|
graph = memnew(GraphEdit);
|
|
graph = memnew(GraphEdit);
|
|
add_child(graph);
|
|
add_child(graph);
|
|
@@ -1710,6 +2253,7 @@ VisualShaderEditor::VisualShaderEditor() {
|
|
|
|
|
|
// SPECIAL
|
|
// SPECIAL
|
|
|
|
|
|
|
|
+ add_options.push_back(AddOption("Expression", "Special", "", "VisualShaderNodeExpression", TTR("Custom Godot Shader Language expression, with custom amount of input and output ports. This is a direct injection of code into the vertex/fragment/light function, do not use it to write the function declarations inside.")));
|
|
add_options.push_back(AddOption("Fresnel", "Special", "", "VisualShaderNodeFresnel", TTR("Returns falloff based on the dot product of surface normal and view direction of camera (pass associated inputs to it)."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
|
|
add_options.push_back(AddOption("Fresnel", "Special", "", "VisualShaderNodeFresnel", TTR("Returns falloff based on the dot product of surface normal and view direction of camera (pass associated inputs to it)."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
|
|
|
|
|
|
add_options.push_back(AddOption("ScalarDerivativeFunc", "Special", "Common", "VisualShaderNodeScalarDerivativeFunc", TTR("(GLES3 only) (Fragment/Light mode only) Scalar derivative function."), -1, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT));
|
|
add_options.push_back(AddOption("ScalarDerivativeFunc", "Special", "Common", "VisualShaderNodeScalarDerivativeFunc", TTR("(GLES3 only) (Fragment/Light mode only) Scalar derivative function."), -1, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT));
|
|
@@ -1743,6 +2287,13 @@ VisualShaderEditor::VisualShaderEditor() {
|
|
add_child(property_editor);
|
|
add_child(property_editor);
|
|
|
|
|
|
property_editor->connect("variant_changed", this, "_port_edited");
|
|
property_editor->connect("variant_changed", this, "_port_edited");
|
|
|
|
+
|
|
|
|
+ // BUILD TIMER FOR EXPRESSION NODES
|
|
|
|
+
|
|
|
|
+ build_timer = memnew(Timer);
|
|
|
|
+ add_child(build_timer);
|
|
|
|
+ build_timer->connect("timeout", this, "_rebuild_timeout");
|
|
|
|
+ build_timer->set_one_shot(true);
|
|
}
|
|
}
|
|
|
|
|
|
void VisualShaderEditorPlugin::edit(Object *p_object) {
|
|
void VisualShaderEditorPlugin::edit(Object *p_object) {
|