summaryrefslogtreecommitdiff
path: root/scene/resources/visual_shader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/resources/visual_shader.cpp')
-rw-r--r--scene/resources/visual_shader.cpp147
1 files changed, 133 insertions, 14 deletions
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index da29f2ebd8..5ac1ad935e 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -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);