Implements expandable color ports in visual shaders

This commit is contained in:
Yuri Roubinsky 2020-12-20 18:45:53 +03:00
parent af03e9c830
commit 8f9b91dab1
6 changed files with 363 additions and 30 deletions

View file

@ -322,6 +322,12 @@ void VisualShaderGraphPlugin::register_uniform_name(int p_node_id, LineEdit *p_u
links[p_node_id].uniform_name = p_uniform_name;
}
void VisualShaderGraphPlugin::update_theme() {
vector_expanded_color[0] = VisualShaderEditor::get_singleton()->get_theme_color("axis_x_color", "Editor"); // red
vector_expanded_color[1] = VisualShaderEditor::get_singleton()->get_theme_color("axis_y_color", "Editor"); // green
vector_expanded_color[2] = VisualShaderEditor::get_singleton()->get_theme_color("axis_z_color", "Editor"); // blue
}
void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (p_type != visual_shader->get_shader_type()) {
return;
@ -340,6 +346,12 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
Color(1.0, 1.0, 0.0), // sampler
};
static const String vector_expanded_name[3] = {
"red",
"green",
"blue"
};
Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_id);
Ref<VisualShaderNodeResizableBase> resizable_node = Object::cast_to<VisualShaderNodeResizableBase>(vsnode.ptr());
@ -553,13 +565,32 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
}
}
for (int i = 0; i < MAX(vsnode->get_input_port_count(), vsnode->get_output_port_count()); i++) {
int output_port_count = 0;
for (int i = 0; i < vsnode->get_output_port_count(); i++) {
if (vsnode->_is_output_port_expanded(i)) {
if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
output_port_count += 3;
}
}
output_port_count++;
}
int max_ports = MAX(vsnode->get_input_port_count(), output_port_count);
VisualShaderNode::PortType expanded_type = VisualShaderNode::PORT_TYPE_SCALAR;
int expanded_port_counter = 0;
for (int i = 0, j = 0; i < max_ports; i++, j++) {
if (expanded_type == VisualShaderNode::PORT_TYPE_VECTOR && expanded_port_counter >= 3) {
expanded_type = VisualShaderNode::PORT_TYPE_SCALAR;
expanded_port_counter = 0;
i -= 3;
}
if (vsnode->is_port_separator(i)) {
node->add_child(memnew(HSeparator));
port_offset++;
}
bool valid_left = i < vsnode->get_input_port_count();
bool valid_left = j < vsnode->get_input_port_count();
VisualShaderNode::PortType port_left = VisualShaderNode::PORT_TYPE_SCALAR;
bool port_left_used = false;
String name_left;
@ -567,18 +598,24 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
name_left = vsnode->get_input_port_name(i);
port_left = vsnode->get_input_port_type(i);
for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) {
if (E->get().to_node == p_id && E->get().to_port == i) {
if (E->get().to_node == p_id && E->get().to_port == j) {
port_left_used = true;
}
}
}
bool valid_right = i < vsnode->get_output_port_count();
bool valid_right = true;
VisualShaderNode::PortType port_right = VisualShaderNode::PORT_TYPE_SCALAR;
String name_right;
if (valid_right) {
name_right = vsnode->get_output_port_name(i);
port_right = vsnode->get_output_port_type(i);
if (expanded_type == VisualShaderNode::PORT_TYPE_SCALAR) {
valid_right = i < vsnode->get_output_port_count();
if (valid_right) {
name_right = vsnode->get_output_port_name(i);
port_right = vsnode->get_output_port_type(i);
}
} else {
name_right = vector_expanded_name[expanded_port_counter++];
}
HBoxContainer *hb = memnew(HBoxContainer);
@ -686,17 +723,29 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
}
}
if (valid_right && visual_shader->get_shader_type() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) {
TextureButton *preview = memnew(TextureButton);
preview->set_toggle_mode(true);
preview->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityHidden", "EditorIcons"));
preview->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityVisible", "EditorIcons"));
preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
if (valid_right) {
if (vsnode->is_output_port_expandable(i)) {
TextureButton *expand = memnew(TextureButton);
expand->set_toggle_mode(true);
expand->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiTreeArrowDown", "EditorIcons"));
expand->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiTreeArrowRight", "EditorIcons"));
expand->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
expand->set_pressed(vsnode->_is_output_port_expanded(i));
expand->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_expand_output_port), varray(p_id, i, !vsnode->_is_output_port_expanded(i)), CONNECT_DEFERRED);
hb->add_child(expand);
}
if (visual_shader->get_shader_type() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) {
TextureButton *preview = memnew(TextureButton);
preview->set_toggle_mode(true);
preview->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityHidden", "EditorIcons"));
preview->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityVisible", "EditorIcons"));
preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
register_output_port(p_id, i, preview);
register_output_port(p_id, j, preview);
preview->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_preview_select_port), varray(p_id, i), CONNECT_DEFERRED);
hb->add_child(preview);
preview->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_preview_select_port), varray(p_id, j), CONNECT_DEFERRED);
hb->add_child(preview);
}
}
if (is_group) {
@ -708,7 +757,40 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
node->add_child(hb);
if (expanded_type != VisualShaderNode::PORT_TYPE_SCALAR) {
continue;
}
node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]);
if (vsnode->_is_output_port_expanded(i)) {
if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
port_offset++;
valid_left = (i + 1) < vsnode->get_input_port_count();
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
if (valid_left) {
port_left = vsnode->get_input_port_type(i + 1);
}
node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[0]);
port_offset++;
valid_left = (i + 2) < vsnode->get_input_port_count();
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
if (valid_left) {
port_left = vsnode->get_input_port_type(i + 2);
}
node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[1]);
port_offset++;
valid_left = (i + 3) < vsnode->get_input_port_count();
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
if (valid_left) {
port_left = vsnode->get_input_port_type(i + 3);
}
node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[2]);
expanded_type = VisualShaderNode::PORT_TYPE_VECTOR;
}
}
}
if (vsnode->get_output_port_for_preview() >= 0) {
@ -1293,6 +1375,7 @@ void VisualShaderEditor::_update_graph() {
graph_plugin->clear_links();
graph_plugin->make_dirty(true);
graph_plugin->update_theme();
for (int n_i = 0; n_i < nodes.size(); n_i++) {
graph_plugin->add_node(type, nodes[n_i]);
@ -1441,6 +1524,92 @@ void VisualShaderEditor::_change_output_port_name(const String &p_text, Object *
undo_redo->commit_action();
}
void VisualShaderEditor::_expand_output_port(int p_node, int p_port, bool p_expand) {
VisualShader::Type type = get_current_shader_type();
Ref<VisualShaderNode> node = visual_shader->get_node(type, p_node);
ERR_FAIL_COND(!node.is_valid());
if (p_expand) {
undo_redo->create_action(TTR("Expand Output Port"));
} else {
undo_redo->create_action(TTR("Shrink Output Port"));
}
undo_redo->add_do_method(node.ptr(), "_set_output_port_expanded", p_port, p_expand);
undo_redo->add_undo_method(node.ptr(), "_set_output_port_expanded", p_port, !p_expand);
int type_size = 0;
if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_VECTOR) {
type_size = 3;
}
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 (p_expand) {
if (from_port > p_port) { // reconnect ports after expanded ports
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(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", 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 + type_size, to_node, to_port);
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port + type_size, to_node, to_port);
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port + type_size, to_node, to_port);
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port + type_size, to_node, to_port);
}
} else {
if (from_port > p_port + type_size) { // reconnect ports after expanded ports
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(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port, to_node, to_port);
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_port - type_size, to_node, to_port);
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port - type_size, to_node, to_port);
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port - type_size, to_node, to_port);
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port - type_size, to_node, to_port);
} else if (from_port > p_port) { // disconnect component ports
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(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port, to_node, to_port);
}
}
}
}
int preview_port = node->get_output_port_for_preview();
if (p_expand) {
if (preview_port > p_port) {
undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", preview_port + type_size);
undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", preview_port);
}
} else {
if (preview_port > p_port + type_size) {
undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", preview_port - type_size);
undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", preview_port);
}
}
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
undo_redo->commit_action();
}
void VisualShaderEditor::_remove_input_port(int p_node, int p_port) {
VisualShader::Type type = get_current_shader_type();
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
@ -3469,6 +3638,7 @@ void VisualShaderEditor::_bind_methods() {
ClassDB::bind_method("_float_constant_selected", &VisualShaderEditor::_float_constant_selected);
ClassDB::bind_method("_update_constant", &VisualShaderEditor::_update_constant);
ClassDB::bind_method("_update_uniform", &VisualShaderEditor::_update_uniform);
ClassDB::bind_method("_expand_output_port", &VisualShaderEditor::_expand_output_port);
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);

View file

@ -83,6 +83,8 @@ private:
List<VisualShader::Connection> connections;
bool dirty = false;
Color vector_expanded_color[3];
protected:
static void _bind_methods();
@ -119,6 +121,7 @@ public:
void set_expression(VisualShader::Type p_type, int p_node_id, const String &p_expression);
int get_constant_index(float p_constant) const;
void update_node_size(int p_node_id);
void update_theme();
VisualShader::Type get_shader_type() const;
VisualShaderGraphPlugin();
@ -401,6 +404,7 @@ class VisualShaderEditor : public VBoxContainer {
void _remove_output_port(int p_node, int p_port);
void _change_output_port_type(int p_type, int p_node, int p_port);
void _change_output_port_name(const String &p_text, Object *p_line_edit, int p_node, int p_port);
void _expand_output_port(int p_node, int p_port, bool p_expand);
void _expression_focus_out(Object *code_edit, int p_node);

View file

@ -94,6 +94,52 @@ bool VisualShaderNode::is_generate_input_var(int p_port) const {
return true;
}
bool VisualShaderNode::is_output_port_expandable(int p_port) const {
return false;
}
void VisualShaderNode::_set_output_ports_expanded(const Array &p_values) {
for (int i = 0; i < p_values.size(); i++) {
expanded_output_ports[p_values[i]] = true;
}
emit_changed();
}
Array VisualShaderNode::_get_output_ports_expanded() const {
Array arr;
for (int i = 0; i < get_output_port_count(); i++) {
if (_is_output_port_expanded(i)) {
arr.push_back(i);
}
}
return arr;
}
void VisualShaderNode::_set_output_port_expanded(int p_port, bool p_expanded) {
expanded_output_ports[p_port] = p_expanded;
emit_changed();
}
bool VisualShaderNode::_is_output_port_expanded(int p_port) const {
if (expanded_output_ports.has(p_port)) {
return expanded_output_ports[p_port];
}
return false;
}
int VisualShaderNode::get_expanded_output_port_count() const {
int count = get_output_port_count();
int count2 = count;
for (int i = 0; i < count; i++) {
if (is_output_port_expandable(i) && _is_output_port_expanded(i)) {
if (get_output_port_type(i) == PORT_TYPE_VECTOR) {
count2 += 3;
}
}
}
return count2;
}
bool VisualShaderNode::is_code_generated() const {
return true;
}
@ -157,6 +203,12 @@ void VisualShaderNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_output_port_for_preview", "port"), &VisualShaderNode::set_output_port_for_preview);
ClassDB::bind_method(D_METHOD("get_output_port_for_preview"), &VisualShaderNode::get_output_port_for_preview);
ClassDB::bind_method(D_METHOD("_set_output_port_expanded", "port"), &VisualShaderNode::_set_output_port_expanded);
ClassDB::bind_method(D_METHOD("_is_output_port_expanded"), &VisualShaderNode::_is_output_port_expanded);
ClassDB::bind_method(D_METHOD("_set_output_ports_expanded", "values"), &VisualShaderNode::_set_output_ports_expanded);
ClassDB::bind_method(D_METHOD("_get_output_ports_expanded"), &VisualShaderNode::_get_output_ports_expanded);
ClassDB::bind_method(D_METHOD("set_input_port_default_value", "port", "value"), &VisualShaderNode::set_input_port_default_value);
ClassDB::bind_method(D_METHOD("get_input_port_default_value", "port"), &VisualShaderNode::get_input_port_default_value);
@ -165,6 +217,7 @@ void VisualShaderNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "output_port_for_preview"), "set_output_port_for_preview", "get_output_port_for_preview");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_default_input_values", "get_default_input_values");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "expanded_output_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_output_ports_expanded", "_get_output_ports_expanded");
ADD_SIGNAL(MethodInfo("editor_refresh_request"));
BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR);
@ -576,7 +629,7 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po
return false;
}
if (p_from_port < 0 || p_from_port >= g->nodes[p_from_node].node->get_output_port_count()) {
if (p_from_port < 0 || p_from_port >= g->nodes[p_from_node].node->get_expanded_output_port_count()) {
return false;
}
@ -617,7 +670,7 @@ void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from
Graph *g = &graph[p_type];
ERR_FAIL_COND(!g->nodes.has(p_from_node));
ERR_FAIL_INDEX(p_from_port, g->nodes[p_from_node].node->get_output_port_count());
ERR_FAIL_INDEX(p_from_port, g->nodes[p_from_node].node->get_expanded_output_port_count());
ERR_FAIL_COND(!g->nodes.has(p_to_node));
ERR_FAIL_INDEX(p_to_port, g->nodes[p_to_node].node->get_input_port_count());
@ -639,7 +692,7 @@ Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port,
Graph *g = &graph[p_type];
ERR_FAIL_COND_V(!g->nodes.has(p_from_node), ERR_INVALID_PARAMETER);
ERR_FAIL_INDEX_V(p_from_port, g->nodes[p_from_node].node->get_output_port_count(), ERR_INVALID_PARAMETER);
ERR_FAIL_INDEX_V(p_from_port, g->nodes[p_from_node].node->get_expanded_output_port_count(), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(!g->nodes.has(p_to_node), ERR_INVALID_PARAMETER);
ERR_FAIL_INDEX_V(p_to_port, g->nodes[p_to_node].node->get_input_port_count(), ERR_INVALID_PARAMETER);
@ -790,7 +843,7 @@ bool VisualShader::is_text_shader() const {
String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port, Vector<DefaultTextureParam> &default_tex_params) const {
Ref<VisualShaderNode> node = get_node(p_type, p_node);
ERR_FAIL_COND_V(!node.is_valid(), String());
ERR_FAIL_COND_V(p_port < 0 || p_port >= node->get_output_port_count(), String());
ERR_FAIL_COND_V(p_port < 0 || p_port >= node->get_expanded_output_port_count(), String());
ERR_FAIL_COND_V(node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_TRANSFORM, String());
StringBuilder global_code;
@ -1362,13 +1415,30 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
}
int output_count = vsnode->get_output_port_count();
int initial_output_count = output_count;
Map<int, bool> expanded_output_ports;
for (int i = 0; i < initial_output_count; i++) {
bool expanded = false;
if (vsnode->is_output_port_expandable(i) && vsnode->_is_output_port_expanded(i)) {
expanded = true;
if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
output_count += 3;
}
}
expanded_output_ports.insert(i, expanded);
}
Vector<String> output_vars;
output_vars.resize(vsnode->get_output_port_count());
output_vars.resize(output_count);
String *outputs = output_vars.ptrw();
if (vsnode->is_simple_decl()) { // less code to generate for some simple_decl nodes
for (int i = 0; i < output_count; i++) {
String var_name = "n_out" + itos(node) + "p" + itos(i);
for (int i = 0, j = 0; i < initial_output_count; i++, j++) {
String var_name = "n_out" + itos(node) + "p" + itos(j);
switch (vsnode->get_output_port_type(i)) {
case VisualShaderNode::PORT_TYPE_SCALAR:
outputs[i] = "float " + var_name;
@ -1388,35 +1458,84 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
default: {
}
}
if (expanded_output_ports[i]) {
if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
j += 3;
}
}
}
} else {
for (int i = 0; i < output_count; i++) {
outputs[i] = "n_out" + itos(node) + "p" + itos(i);
for (int i = 0, j = 0; i < initial_output_count; i++, j++) {
outputs[i] = "n_out" + itos(node) + "p" + itos(j);
switch (vsnode->get_output_port_type(i)) {
case VisualShaderNode::PORT_TYPE_SCALAR:
code += String() + "\tfloat " + outputs[i] + ";\n";
code += "\tfloat " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_SCALAR_INT:
code += String() + "\tint " + outputs[i] + ";\n";
code += "\tint " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_VECTOR:
code += String() + "\tvec3 " + outputs[i] + ";\n";
code += "\tvec3 " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_BOOLEAN:
code += String() + "\tbool " + outputs[i] + ";\n";
code += "\tbool " + outputs[i] + ";\n";
break;
case VisualShaderNode::PORT_TYPE_TRANSFORM:
code += String() + "\tmat4 " + outputs[i] + ";\n";
code += "\tmat4 " + outputs[i] + ";\n";
break;
default: {
}
}
if (expanded_output_ports[i]) {
if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
j += 3;
}
}
}
}
code += vsnode->generate_code(get_mode(), type, node, inputs, outputs, for_preview);
for (int i = 0; i < output_count; i++) {
bool new_line_inserted = false;
if (expanded_output_ports[i]) {
if (vsnode->get_output_port_type(i) == VisualShaderNode::PORT_TYPE_VECTOR) {
if (vsnode->is_output_port_connected(i + 1) || (for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component
if (!new_line_inserted) {
code += "\n";
new_line_inserted = true;
}
String r = "n_out" + itos(node) + "p" + itos(i + 1);
code += "\tfloat " + r + " = n_out" + itos(node) + "p" + itos(i) + ".r;\n";
outputs[i + 1] = r;
}
if (vsnode->is_output_port_connected(i + 2) || (for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component
if (!new_line_inserted) {
code += "\n";
new_line_inserted = true;
}
String g = "n_out" + itos(node) + "p" + itos(i + 2);
code += "\tfloat " + g + " = n_out" + itos(node) + "p" + itos(i) + ".g;\n";
outputs[i + 2] = g;
}
if (vsnode->is_output_port_connected(i + 3) || (for_preview && vsnode->get_output_port_for_preview() == (i + 3))) { // blue-component
if (!new_line_inserted) {
code += "\n";
new_line_inserted = true;
}
String b = "n_out" + itos(node) + "p" + itos(i + 3);
code += "\tfloat " + b + " = n_out" + itos(node) + "p" + itos(i) + ".b;\n";
outputs[i + 3] = b;
}
i += 3;
}
}
}
code += "\n"; //
processed.insert(node);

View file

@ -199,6 +199,7 @@ class VisualShaderNode : public Resource {
Map<int, Variant> default_input_values;
Map<int, bool> connected_input_ports;
Map<int, int> connected_output_ports;
Map<int, bool> expanded_output_ports;
protected:
bool simple_decl = true;
@ -245,6 +246,13 @@ public:
void set_input_port_connected(int p_port, bool p_connected);
virtual bool is_generate_input_var(int p_port) const;
virtual bool is_output_port_expandable(int p_port) const;
void _set_output_ports_expanded(const Array &p_data);
Array _get_output_ports_expanded() const;
void _set_output_port_expanded(int p_port, bool p_expanded);
bool _is_output_port_expanded(int p_port) const;
int get_expanded_output_port_count() const;
virtual bool is_code_generated() const;
virtual bool is_show_prop_names() const;
virtual bool is_use_prop_slots() const;

View file

@ -242,6 +242,13 @@ String VisualShaderNodeColorConstant::get_output_port_name(int p_port) const {
return p_port == 0 ? "" : "alpha"; //no output port means the editor will be used as port
}
bool VisualShaderNodeColorConstant::is_output_port_expandable(int p_port) const {
if (p_port == 0) {
return true;
}
return false;
}
String VisualShaderNodeColorConstant::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
String code;
code += "\t" + p_output_vars[0] + " = " + vformat("vec3(%.6f, %.6f, %.6f)", constant.r, constant.g, constant.b) + ";\n";
@ -455,6 +462,13 @@ String VisualShaderNodeTexture::get_output_port_name(int p_port) const {
return p_port == 0 ? "rgb" : "alpha";
}
bool VisualShaderNodeTexture::is_output_port_expandable(int p_port) const {
if (p_port == 0) {
return true;
}
return false;
}
String VisualShaderNodeTexture::get_input_port_default_hint(int p_port) const {
if (p_port == 0) {
return "default";
@ -917,6 +931,13 @@ String VisualShaderNodeSample3D::get_output_port_name(int p_port) const {
return p_port == 0 ? "rgb" : "alpha";
}
bool VisualShaderNodeSample3D::is_output_port_expandable(int p_port) const {
if (p_port == 0) {
return true;
}
return false;
}
String VisualShaderNodeSample3D::get_input_port_default_hint(int p_port) const {
if (p_port == 0) {
return "default";
@ -1168,6 +1189,13 @@ String VisualShaderNodeCubemap::get_output_port_name(int p_port) const {
return p_port == 0 ? "rgb" : "alpha";
}
bool VisualShaderNodeCubemap::is_output_port_expandable(int p_port) const {
if (p_port == 0) {
return true;
}
return false;
}
Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCubemap::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const {
VisualShader::DefaultTextureParam dtp;
dtp.name = make_unique_id(p_type, p_id, "cube");

View file

@ -163,6 +163,7 @@ public:
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
virtual bool is_output_port_expandable(int p_port) const override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
@ -275,6 +276,7 @@ public:
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
virtual bool is_output_port_expandable(int p_port) const override;
virtual String get_input_port_default_hint(int p_port) const override;
@ -359,6 +361,7 @@ public:
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
virtual bool is_output_port_expandable(int p_port) const override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
@ -452,6 +455,7 @@ public:
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
virtual bool is_output_port_expandable(int p_port) const override;
virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;