diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 174afd5a378..0ff2fffdeba 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -64,6 +64,40 @@ bool VisualShaderNode::is_port_separator(int p_index) const { return false; } +bool VisualShaderNode::is_output_port_connected(int p_port) const { + if (connected_output_ports.has(p_port)) { + return connected_output_ports[p_port] > 0; + } + return false; +} + +void VisualShaderNode::set_output_port_connected(int p_port, bool p_connected) { + if (p_connected) { + connected_output_ports[p_port]++; + } else { + connected_output_ports[p_port]--; + } +} + +bool VisualShaderNode::is_input_port_connected(int p_port) const { + if (connected_input_ports.has(p_port)) { + return connected_input_ports[p_port]; + } + return false; +} + +void VisualShaderNode::set_input_port_connected(int p_port, bool p_connected) { + connected_input_ports[p_port] = p_connected; +} + +bool VisualShaderNode::is_generate_input_var(int p_port) const { + return true; +} + +bool VisualShaderNode::is_code_generated() const { + return true; +} + Vector VisualShaderNode::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { return Vector(); } @@ -387,6 +421,7 @@ void VisualShader::remove_node(Type p_type, int p_id) { g->connections.erase(E); if (E->get().from_node == p_id) { g->nodes[E->get().to_node].prev_connected_nodes.erase(p_id); + g->nodes[E->get().to_node].node->set_input_port_connected(E->get().to_port, false); } } E = N; @@ -482,6 +517,8 @@ void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from c.to_port = p_to_port; g->connections.push_back(c); g->nodes[p_to_node].prev_connected_nodes.push_back(p_from_node); + g->nodes[p_from_node].node->set_output_port_connected(p_from_port, true); + g->nodes[p_to_node].node->set_input_port_connected(p_to_port, true); _queue_update(); } @@ -514,6 +551,8 @@ Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port, c.to_port = p_to_port; g->connections.push_back(c); g->nodes[p_to_node].prev_connected_nodes.push_back(p_from_node); + g->nodes[p_from_node].node->set_output_port_connected(p_from_port, true); + g->nodes[p_to_node].node->set_input_port_connected(p_to_port, true); _queue_update(); return OK; @@ -528,6 +567,8 @@ void VisualShader::disconnect_nodes(Type p_type, int p_from_node, int p_from_por if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) { g->connections.erase(E); g->nodes[p_to_node].prev_connected_nodes.erase(p_from_node); + g->nodes[p_from_node].node->set_output_port_connected(p_from_port, false); + g->nodes[p_to_node].node->set_input_port_connected(p_to_port, false); _queue_update(); return; } @@ -1078,6 +1119,36 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui // then this node + Vector params = vsnode->get_default_texture_parameters(type, node); + for (int i = 0; i < params.size(); i++) { + def_tex_params.push_back(params[i]); + } + + Ref input = vsnode; + bool skip_global = input.is_valid() && for_preview; + + if (!skip_global) { + + global_code += vsnode->generate_global(get_mode(), type, node); + + String class_name = vsnode->get_class_name(); + if (class_name == "VisualShaderNodeCustom") { + class_name = vsnode->get_script_instance()->get_script()->get_path(); + } + if (!r_classes.has(class_name)) { + global_code_per_node += vsnode->generate_global_per_node(get_mode(), type, node); + for (int i = 0; i < TYPE_MAX; i++) { + global_code_per_func[Type(i)] += vsnode->generate_global_per_func(get_mode(), Type(i), node); + } + r_classes.insert(class_name); + } + } + + if (!vsnode->is_code_generated()) { // just generate globals and ignore locals + processed.insert(node); + return OK; + } + code += "// " + vsnode->get_caption() + ":" + itos(node) + "\n"; Vector input_vars; @@ -1124,6 +1195,9 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui inputs[i] = "vec3(" + src_var + " ? 1.0 : 0.0)"; } } else { + if (!vsnode->is_generate_input_var(i)) { + continue; + } Variant defval = vsnode->get_input_port_default_value(i); if (defval.get_type() == Variant::REAL || defval.get_type() == Variant::INT) { @@ -1191,33 +1265,6 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui } } - Vector params = vsnode->get_default_texture_parameters(type, node); - for (int i = 0; i < params.size(); i++) { - def_tex_params.push_back(params[i]); - } - - Ref input = vsnode; - bool skip_global = input.is_valid() && for_preview; - - if (!skip_global) { - Ref uniform = vsnode; - if (!uniform.is_valid() || !uniform->is_global_code_generated()) { - global_code += vsnode->generate_global(get_mode(), type, node); - } - - String class_name = vsnode->get_class_name(); - if (class_name == "VisualShaderNodeCustom") { - class_name = vsnode->get_script_instance()->get_script()->get_path(); - } - if (!r_classes.has(class_name)) { - global_code_per_node += vsnode->generate_global_per_node(get_mode(), type, node); - for (int i = 0; i < TYPE_MAX; i++) { - global_code_per_func[Type(i)] += vsnode->generate_global_per_func(get_mode(), Type(i), node); - } - r_classes.insert(class_name); - } - } - code += vsnode->generate_code(get_mode(), type, node, inputs, outputs, for_preview); code += "\n"; // diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 51f5bccc5f1..4c49ef3f125 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -174,6 +174,8 @@ class VisualShaderNode : public Resource { int port_preview; Map default_input_values; + Map connected_input_ports; + Map connected_output_ports; protected: bool simple_decl; @@ -213,6 +215,14 @@ public: virtual bool is_port_separator(int p_index) const; + bool is_output_port_connected(int p_port) const; + void set_output_port_connected(int p_port, bool p_connected); + bool is_input_port_connected(int p_port) const; + void set_input_port_connected(int p_port, bool p_connected); + virtual bool is_generate_input_var(int p_port) const; + + virtual bool is_code_generated() const; + virtual Vector get_editable_properties() const; virtual Vector get_default_texture_parameters(VisualShader::Type p_type, int p_id) const; diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index daf770e92a1..3adc7e9ea40 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -3266,6 +3266,10 @@ String VisualShaderNodeTextureUniform::get_output_port_name(int p_port) const { } } +bool VisualShaderNodeTextureUniform::is_code_generated() const { + return is_output_port_connected(0) || is_output_port_connected(1); // rgb or alpha +} + String VisualShaderNodeTextureUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String code = "uniform sampler2D " + get_uniform_name(); @@ -3749,6 +3753,13 @@ String VisualShaderNodeFresnel::get_output_port_name(int p_port) const { return "result"; } +bool VisualShaderNodeFresnel::is_generate_input_var(int p_port) const { + if (p_port == 2) { + return false; + } + return true; +} + String VisualShaderNodeFresnel::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 normal; @@ -3764,7 +3775,15 @@ String VisualShaderNodeFresnel::generate_code(Shader::Mode p_mode, VisualShader: view = p_input_vars[1]; } - return "\t" + p_output_vars[0] + " = " + p_input_vars[2] + " ? (pow(clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ")) : (pow(1.0 - clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + "));\n"; + if (is_input_port_connected(2)) { + return "\t" + p_output_vars[0] + " = " + p_input_vars[2] + " ? (pow(clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ")) : (pow(1.0 - clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + "));\n"; + } else { + if (get_input_port_default_value(2)) { + return "\t" + p_output_vars[0] + " = pow(clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ");\n"; + } else { + return "\t" + p_output_vars[0] + " = pow(1.0 - clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ");\n"; + } + } } String VisualShaderNodeFresnel::get_input_port_default_hint(int p_port) const { diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index cca37273d94..9a270ce4f79 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -1445,6 +1445,8 @@ public: virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual bool is_code_generated() const; + Vector get_editable_properties() const; void set_texture_type(TextureType p_type); @@ -1580,6 +1582,7 @@ public: virtual String get_output_port_name(int p_port) const; virtual String get_input_port_default_hint(int p_port) const; + virtual bool is_generate_input_var(int p_port) const; 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; VisualShaderNodeFresnel();