diff options
Diffstat (limited to 'scene/resources/visual_shader_nodes.cpp')
-rw-r--r-- | scene/resources/visual_shader_nodes.cpp | 3448 |
1 files changed, 2529 insertions, 919 deletions
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 2064ca10f3..e45dfdcb1b 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,10 +30,15 @@ #include "visual_shader_nodes.h" +////////////// Constants Base + +VisualShaderNodeConstant::VisualShaderNodeConstant() { +} + ////////////// Scalar(Float) String VisualShaderNodeFloatConstant::get_caption() const { - return "ScalarFloat"; + return "FloatConstant"; } int VisualShaderNodeFloatConstant::get_input_port_count() const { @@ -61,17 +66,18 @@ String VisualShaderNodeFloatConstant::get_output_port_name(int p_port) const { } String VisualShaderNodeFloatConstant::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 { - return "\t" + p_output_vars[0] + " = " + vformat("%.6f", constant) + ";\n"; + return " " + p_output_vars[0] + " = " + vformat("%.6f", constant) + ";\n"; } -void VisualShaderNodeFloatConstant::set_constant(float p_value) { - - constant = p_value; +void VisualShaderNodeFloatConstant::set_constant(float p_constant) { + if (Math::is_equal_approx(constant, p_constant)) { + return; + } + constant = p_constant; emit_changed(); } float VisualShaderNodeFloatConstant::get_constant() const { - return constant; } @@ -82,21 +88,19 @@ Vector<StringName> VisualShaderNodeFloatConstant::get_editable_properties() cons } void VisualShaderNodeFloatConstant::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_constant", "value"), &VisualShaderNodeFloatConstant::set_constant); + ClassDB::bind_method(D_METHOD("set_constant", "constant"), &VisualShaderNodeFloatConstant::set_constant); ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeFloatConstant::get_constant); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant"), "set_constant", "get_constant"); } VisualShaderNodeFloatConstant::VisualShaderNodeFloatConstant() { - constant = 0.0; } ////////////// Scalar(Int) String VisualShaderNodeIntConstant::get_caption() const { - return "ScalarInt"; + return "IntConstant"; } int VisualShaderNodeIntConstant::get_input_port_count() const { @@ -124,11 +128,14 @@ String VisualShaderNodeIntConstant::get_output_port_name(int p_port) const { } String VisualShaderNodeIntConstant::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 { - return "\t" + p_output_vars[0] + " = " + itos(constant) + ";\n"; + return " " + p_output_vars[0] + " = " + itos(constant) + ";\n"; } -void VisualShaderNodeIntConstant::set_constant(int p_value) { - constant = p_value; +void VisualShaderNodeIntConstant::set_constant(int p_constant) { + if (constant == p_constant) { + return; + } + constant = p_constant; emit_changed(); } @@ -143,21 +150,19 @@ Vector<StringName> VisualShaderNodeIntConstant::get_editable_properties() const } void VisualShaderNodeIntConstant::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_constant", "value"), &VisualShaderNodeIntConstant::set_constant); + ClassDB::bind_method(D_METHOD("set_constant", "constant"), &VisualShaderNodeIntConstant::set_constant); ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeIntConstant::get_constant); ADD_PROPERTY(PropertyInfo(Variant::INT, "constant"), "set_constant", "get_constant"); } VisualShaderNodeIntConstant::VisualShaderNodeIntConstant() { - constant = 0; } ////////////// Boolean String VisualShaderNodeBooleanConstant::get_caption() const { - return "Boolean"; + return "BooleanConstant"; } int VisualShaderNodeBooleanConstant::get_input_port_count() const { @@ -185,11 +190,14 @@ String VisualShaderNodeBooleanConstant::get_output_port_name(int p_port) const { } String VisualShaderNodeBooleanConstant::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 { - return "\t" + p_output_vars[0] + " = " + (constant ? "true" : "false") + ";\n"; + return " " + p_output_vars[0] + " = " + (constant ? "true" : "false") + ";\n"; } -void VisualShaderNodeBooleanConstant::set_constant(bool p_value) { - constant = p_value; +void VisualShaderNodeBooleanConstant::set_constant(bool p_constant) { + if (constant == p_constant) { + return; + } + constant = p_constant; emit_changed(); } @@ -204,21 +212,19 @@ Vector<StringName> VisualShaderNodeBooleanConstant::get_editable_properties() co } void VisualShaderNodeBooleanConstant::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_constant", "value"), &VisualShaderNodeBooleanConstant::set_constant); + ClassDB::bind_method(D_METHOD("set_constant", "constant"), &VisualShaderNodeBooleanConstant::set_constant); ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeBooleanConstant::get_constant); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "constant"), "set_constant", "get_constant"); } VisualShaderNodeBooleanConstant::VisualShaderNodeBooleanConstant() { - constant = false; } ////////////// Color String VisualShaderNodeColorConstant::get_caption() const { - return "Color"; + return "ColorConstant"; } int VisualShaderNodeColorConstant::get_input_port_count() const { @@ -245,23 +251,30 @@ 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 } -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 { +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"; - code += "\t" + p_output_vars[1] + " = " + vformat("%.6f", constant.a) + ";\n"; + code += " " + p_output_vars[0] + " = " + vformat("vec3(%.6f, %.6f, %.6f)", constant.r, constant.g, constant.b) + ";\n"; + code += " " + p_output_vars[1] + " = " + vformat("%.6f", constant.a) + ";\n"; return code; } -void VisualShaderNodeColorConstant::set_constant(Color p_value) { - - constant = p_value; +void VisualShaderNodeColorConstant::set_constant(const Color &p_constant) { + if (constant.is_equal_approx(p_constant)) { + return; + } + constant = p_constant; emit_changed(); } Color VisualShaderNodeColorConstant::get_constant() const { - return constant; } @@ -272,21 +285,19 @@ Vector<StringName> VisualShaderNodeColorConstant::get_editable_properties() cons } void VisualShaderNodeColorConstant::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_constant", "value"), &VisualShaderNodeColorConstant::set_constant); + ClassDB::bind_method(D_METHOD("set_constant", "constant"), &VisualShaderNodeColorConstant::set_constant); ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeColorConstant::get_constant); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "constant"), "set_constant", "get_constant"); } VisualShaderNodeColorConstant::VisualShaderNodeColorConstant() { - constant = Color(1, 1, 1, 1); } ////////////// Vector String VisualShaderNodeVec3Constant::get_caption() const { - return "Vector"; + return "VectorConstant"; } int VisualShaderNodeVec3Constant::get_input_port_count() const { @@ -314,17 +325,18 @@ String VisualShaderNodeVec3Constant::get_output_port_name(int p_port) const { } String VisualShaderNodeVec3Constant::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 { - return "\t" + p_output_vars[0] + " = " + vformat("vec3(%.6f, %.6f, %.6f)", constant.x, constant.y, constant.z) + ";\n"; + return " " + p_output_vars[0] + " = " + vformat("vec3(%.6f, %.6f, %.6f)", constant.x, constant.y, constant.z) + ";\n"; } -void VisualShaderNodeVec3Constant::set_constant(Vector3 p_value) { - - constant = p_value; +void VisualShaderNodeVec3Constant::set_constant(const Vector3 &p_constant) { + if (constant.is_equal_approx(p_constant)) { + return; + } + constant = p_constant; emit_changed(); } Vector3 VisualShaderNodeVec3Constant::get_constant() const { - return constant; } @@ -335,8 +347,7 @@ Vector<StringName> VisualShaderNodeVec3Constant::get_editable_properties() const } void VisualShaderNodeVec3Constant::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_constant", "value"), &VisualShaderNodeVec3Constant::set_constant); + ClassDB::bind_method(D_METHOD("set_constant", "constant"), &VisualShaderNodeVec3Constant::set_constant); ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeVec3Constant::get_constant); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant"), "set_constant", "get_constant"); @@ -345,10 +356,10 @@ void VisualShaderNodeVec3Constant::_bind_methods() { VisualShaderNodeVec3Constant::VisualShaderNodeVec3Constant() { } -////////////// Transform +////////////// Transform3D String VisualShaderNodeTransformConstant::get_caption() const { - return "Transform"; + return "TransformConstant"; } int VisualShaderNodeTransformConstant::get_input_port_count() const { @@ -376,10 +387,10 @@ String VisualShaderNodeTransformConstant::get_output_port_name(int p_port) const } String VisualShaderNodeTransformConstant::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 { - Transform t = constant; + Transform3D t = constant; t.basis.transpose(); - String code = "\t" + p_output_vars[0] + " = mat4("; + String code = " " + p_output_vars[0] + " = mat4("; code += vformat("vec4(%.6f, %.6f, %.6f, 0.0), ", t.basis[0].x, t.basis[0].y, t.basis[0].z); code += vformat("vec4(%.6f, %.6f, %.6f, 0.0), ", t.basis[1].x, t.basis[1].y, t.basis[1].z); code += vformat("vec4(%.6f, %.6f, %.6f, 0.0), ", t.basis[2].x, t.basis[2].y, t.basis[2].z); @@ -387,14 +398,15 @@ String VisualShaderNodeTransformConstant::generate_code(Shader::Mode p_mode, Vis return code; } -void VisualShaderNodeTransformConstant::set_constant(Transform p_value) { - - constant = p_value; +void VisualShaderNodeTransformConstant::set_constant(const Transform3D &p_constant) { + if (constant.is_equal_approx(p_constant)) { + return; + } + constant = p_constant; emit_changed(); } -Transform VisualShaderNodeTransformConstant::get_constant() const { - +Transform3D VisualShaderNodeTransformConstant::get_constant() const { return constant; } @@ -405,11 +417,10 @@ Vector<StringName> VisualShaderNodeTransformConstant::get_editable_properties() } void VisualShaderNodeTransformConstant::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_constant", "value"), &VisualShaderNodeTransformConstant::set_constant); + ClassDB::bind_method(D_METHOD("set_constant", "constant"), &VisualShaderNodeTransformConstant::set_constant); ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeTransformConstant::get_constant); - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "constant"), "set_constant", "get_constant"); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "constant"), "set_constant", "get_constant"); } VisualShaderNodeTransformConstant::VisualShaderNodeTransformConstant() { @@ -426,7 +437,6 @@ int VisualShaderNodeTexture::get_input_port_count() const { } VisualShaderNodeTexture::PortType VisualShaderNodeTexture::get_input_port_type(int p_port) const { - switch (p_port) { case 0: return PORT_TYPE_VECTOR; @@ -440,7 +450,6 @@ VisualShaderNodeTexture::PortType VisualShaderNodeTexture::get_input_port_type(i } String VisualShaderNodeTexture::get_input_port_name(int p_port) const { - switch (p_port) { case 0: return "uv"; @@ -458,26 +467,34 @@ int VisualShaderNodeTexture::get_output_port_count() const { } VisualShaderNodeTexture::PortType VisualShaderNodeTexture::get_output_port_type(int p_port) const { - if (p_port == 0 && source == SOURCE_DEPTH) + if (p_port == 0 && source == SOURCE_DEPTH) { return PORT_TYPE_SCALAR; + } return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR; } String VisualShaderNodeTexture::get_output_port_name(int p_port) const { - if (p_port == 0 && source == SOURCE_DEPTH) + if (p_port == 0 && source == SOURCE_DEPTH) { return "depth"; + } 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 "UV.xy"; + return "default"; } return ""; } static String make_unique_id(VisualShader::Type p_type, int p_id, const String &p_name) { - static const char *typepf[VisualShader::TYPE_MAX] = { "vtx", "frg", "lgt" }; return p_name + "_" + String(typepf[p_type]) + "_" + itos(p_id); } @@ -492,14 +509,19 @@ Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture::get_default_t } String VisualShaderNodeTexture::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - if (source == SOURCE_TEXTURE) { - String u = "uniform sampler2D " + make_unique_id(p_type, p_id, "tex"); switch (texture_type) { - case TYPE_DATA: break; - case TYPE_COLOR: u += " : hint_albedo"; break; - case TYPE_NORMALMAP: u += " : hint_normal"; break; + case TYPE_DATA: + break; + case TYPE_COLOR: + u += " : hint_albedo"; + break; + case TYPE_NORMAL_MAP: + u += " : hint_normal"; + break; + default: + break; } return u + ";\n"; } @@ -508,6 +530,12 @@ String VisualShaderNodeTexture::generate_global(Shader::Mode p_mode, VisualShade } String VisualShaderNodeTexture::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 default_uv; + if (p_mode != Shader::MODE_PARTICLES && p_mode != Shader::MODE_SKY) { + default_uv = "UV.xy"; + } else { + default_uv = "vec2(0.0)"; + } if (source == SOURCE_TEXTURE) { String id = make_unique_id(p_type, p_id, "tex"); @@ -515,20 +543,20 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: if (p_input_vars[0] == String()) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\tvec4 " + id + "_read = texture(" + id + ", UV.xy);\n"; + code += " vec4 " + id + "_read = texture(" + id + ", " + default_uv + ");\n"; } else { - code += "\tvec4 " + id + "_read = textureLod(" + id + ", UV.xy, " + p_input_vars[1] + ");\n"; + code += " vec4 " + id + "_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\tvec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n"; + code += " vec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n"; } else { - code += "\tvec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; + code += " vec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; } - code += "\t" + p_output_vars[0] + " = " + id + "_read.rgb;\n"; - code += "\t" + p_output_vars[1] + " = " + id + "_read.a;\n"; + code += " " + p_output_vars[0] + " = " + id + "_read.rgb;\n"; + code += " " + p_output_vars[1] + " = " + id + "_read.a;\n"; return code; } @@ -536,101 +564,98 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: String id = p_input_vars[2]; String code; - code += "\t{\n"; + code += " {\n"; if (id == String()) { - code += "\t\tvec4 " + id + "_tex_read = vec4(0.0);\n"; + code += " vec4 " + id + "_tex_read = vec4(0.0);\n"; } else { if (p_input_vars[0] == String()) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\t\tvec4 " + id + "_tex_read = texture(" + id + ", UV.xy);\n"; + code += " vec4 " + id + "_tex_read = texture(" + id + ", " + default_uv + ");\n"; } else { - code += "\t\tvec4 " + id + "_tex_read = textureLod(" + id + ", UV.xy, " + p_input_vars[1] + ");\n"; + code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\t\tvec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n"; + code += " vec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n"; } else { - code += "\t\tvec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; + code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; } - code += "\t\t" + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n"; - code += "\t\t" + p_output_vars[1] + " = " + id + "_tex_read.a;\n"; + code += " " + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n"; + code += " " + p_output_vars[1] + " = " + id + "_tex_read.a;\n"; } - code += "\t}\n"; + code += " }\n"; return code; } if (source == SOURCE_SCREEN && (p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) { - - String code = "\t{\n"; + String code = " {\n"; if (p_input_vars[0] == String() || p_for_preview) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\t\tvec4 _tex_read = textureLod(SCREEN_TEXTURE, UV.xy, 0.0 );\n"; + code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + default_uv + ", 0.0 );\n"; } else { - code += "\t\tvec4 _tex_read = textureLod(SCREEN_TEXTURE, UV.xy, " + p_input_vars[1] + ");\n"; + code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\t\tvec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ".xy, 0.0);\n"; + code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ".xy, 0.0);\n"; } else { - code += "\t\tvec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; + code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; } - code += "\t\t" + p_output_vars[0] + " = _tex_read.rgb;\n"; - code += "\t\t" + p_output_vars[1] + " = _tex_read.a;\n"; - code += "\t}\n"; + code += " " + p_output_vars[0] + " = _tex_read.rgb;\n"; + code += " " + p_output_vars[1] + " = _tex_read.a;\n"; + code += " }\n"; return code; } if (source == SOURCE_2D_TEXTURE && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) { - - String code = "\t{\n"; + String code = " {\n"; if (p_input_vars[0] == String()) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\t\tvec4 _tex_read = texture(TEXTURE , UV.xy);\n"; + code += " vec4 _tex_read = texture(TEXTURE, " + default_uv + ");\n"; } else { - code += "\t\tvec4 _tex_read = textureLod(TEXTURE, UV.xy, " + p_input_vars[1] + ");\n"; + code += " vec4 _tex_read = textureLod(TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\t\tvec4 _tex_read = texture(TEXTURE, " + p_input_vars[0] + ".xy);\n"; + code += " vec4 _tex_read = texture(TEXTURE, " + p_input_vars[0] + ".xy);\n"; } else { - code += "\t\tvec4 _tex_read = textureLod(TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; + code += " vec4 _tex_read = textureLod(TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; } - code += "\t\t" + p_output_vars[0] + " = _tex_read.rgb;\n"; - code += "\t\t" + p_output_vars[1] + " = _tex_read.a;\n"; - code += "\t}\n"; + code += " " + p_output_vars[0] + " = _tex_read.rgb;\n"; + code += " " + p_output_vars[1] + " = _tex_read.a;\n"; + code += " }\n"; return code; } if (source == SOURCE_2D_NORMAL && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) { - - String code = "\t{\n"; + String code = " {\n"; if (p_input_vars[0] == String()) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\t\tvec4 _tex_read = texture(NORMAL_TEXTURE, UV.xy);\n"; + code += " vec4 _tex_read = texture(NORMAL_TEXTURE, " + default_uv + ");\n"; } else { - code += "\t\tvec4 _tex_read = textureLod(NORMAL_TEXTURE, UV.xy, " + p_input_vars[1] + ");\n"; + code += " vec4 _tex_read = textureLod(NORMAL_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\t\tvec4 _tex_read = texture(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy);\n"; + code += " vec4 _tex_read = texture(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy);\n"; } else { - code += "\t\tvec4 _tex_read = textureLod(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; + code += " vec4 _tex_read = textureLod(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; } - code += "\t\t" + p_output_vars[0] + " = _tex_read.rgb;\n"; - code += "\t\t" + p_output_vars[1] + " = _tex_read.a;\n"; - code += "\t}\n"; + code += " " + p_output_vars[0] + " = _tex_read.rgb;\n"; + code += " " + p_output_vars[1] + " = _tex_read.a;\n"; + code += " }\n"; return code; } @@ -638,51 +663,53 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: { if (source == SOURCE_DEPTH) { String code; - code += "\t" + p_output_vars[0] + " = 0.0;\n"; - code += "\t" + p_output_vars[1] + " = 1.0;\n"; + code += " " + p_output_vars[0] + " = 0.0;\n"; + code += " " + p_output_vars[1] + " = 1.0;\n"; return code; } } if (source == SOURCE_DEPTH && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) { - - String code = "\t{\n"; + String code = " {\n"; if (p_input_vars[0] == String()) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\t\tfloat _depth = texture(DEPTH_TEXTURE, UV.xy).r;\n"; + code += " float _depth = texture(DEPTH_TEXTURE, " + default_uv + ").r;\n"; } else { - code += "\t\tfloat _depth = textureLod(DEPTH_TEXTURE, UV.xy, " + p_input_vars[1] + ").r;\n"; + code += " float _depth = textureLod(DEPTH_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ").r;\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\t\tfloat _depth = texture(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy).r;\n"; + code += " float _depth = texture(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy).r;\n"; } else { - code += "\t\tfloat _depth = textureLod(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").r;\n"; + code += " float _depth = textureLod(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").r;\n"; } - code += "\t\t" + p_output_vars[0] + " = _depth;\n"; - code += "\t\t" + p_output_vars[1] + " = 1.0;\n"; - code += "\t}\n"; + code += " " + p_output_vars[0] + " = _depth;\n"; + code += " " + p_output_vars[1] + " = 1.0;\n"; + code += " }\n"; return code; } else if (source == SOURCE_DEPTH) { String code; - code += "\t" + p_output_vars[0] + " = 0.0;\n"; - code += "\t" + p_output_vars[1] + " = 1.0;\n"; + code += " " + p_output_vars[0] + " = 0.0;\n"; + code += " " + p_output_vars[1] + " = 1.0;\n"; return code; } //none String code; - code += "\t" + p_output_vars[0] + " = vec3(0.0);\n"; - code += "\t" + p_output_vars[1] + " = 1.0;\n"; + code += " " + p_output_vars[0] + " = vec3(0.0);\n"; + code += " " + p_output_vars[1] + " = 1.0;\n"; return code; } void VisualShaderNodeTexture::set_source(Source p_source) { - source = p_source; - switch (source) { + ERR_FAIL_INDEX(int(p_source), int(SOURCE_MAX)); + if (source == p_source) { + return; + } + switch (p_source) { case SOURCE_TEXTURE: simple_decl = true; break; @@ -701,28 +728,33 @@ void VisualShaderNodeTexture::set_source(Source p_source) { case SOURCE_PORT: simple_decl = false; break; + default: + break; } + source = p_source; emit_changed(); - emit_signal("editor_refresh_request"); + emit_signal(SNAME("editor_refresh_request")); } VisualShaderNodeTexture::Source VisualShaderNodeTexture::get_source() const { return source; } -void VisualShaderNodeTexture::set_texture(Ref<Texture2D> p_value) { - - texture = p_value; +void VisualShaderNodeTexture::set_texture(Ref<Texture2D> p_texture) { + texture = p_texture; emit_changed(); } Ref<Texture2D> VisualShaderNodeTexture::get_texture() const { - return texture; } -void VisualShaderNodeTexture::set_texture_type(TextureType p_type) { - texture_type = p_type; +void VisualShaderNodeTexture::set_texture_type(TextureType p_texture_type) { + ERR_FAIL_INDEX(int(p_texture_type), int(TYPE_MAX)); + if (texture_type == p_texture_type) { + return; + } + texture_type = p_texture_type; emit_changed(); } @@ -741,6 +773,9 @@ Vector<StringName> VisualShaderNodeTexture::get_editable_properties() const { } String VisualShaderNodeTexture::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const { + if (is_input_port_connected(2) && source != SOURCE_PORT) { + return TTR("The sampler port is connected but not used. Consider changing the source to 'SamplerPort'."); + } if (source == SOURCE_TEXTURE) { return String(); // all good @@ -751,22 +786,18 @@ String VisualShaderNodeTexture::get_warning(Shader::Mode p_mode, VisualShader::T } if (source == SOURCE_SCREEN && (p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) { - return String(); // all good } if (source == SOURCE_2D_TEXTURE && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) { - return String(); // all good } if (source == SOURCE_2D_NORMAL && p_mode == Shader::MODE_CANVAS_ITEM) { - return String(); // all good } if (source == SOURCE_DEPTH && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) { - if (get_output_port_for_preview() == 0) { // DEPTH_TEXTURE is not supported in preview(canvas_item) shader return TTR("Invalid source for preview."); } @@ -777,7 +808,6 @@ String VisualShaderNodeTexture::get_warning(Shader::Mode p_mode, VisualShader::T } void VisualShaderNodeTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_source", "value"), &VisualShaderNodeTexture::set_source); ClassDB::bind_method(D_METHOD("get_source"), &VisualShaderNodeTexture::get_source); @@ -789,7 +819,7 @@ void VisualShaderNodeTexture::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,Screen,Texture2D,NormalMap2D,Depth,SamplerPort"), "set_source", "get_source"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normalmap"), "set_texture_type", "get_texture_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map"), "set_texture_type", "get_texture_type"); BIND_ENUM_CONSTANT(SOURCE_TEXTURE); BIND_ENUM_CONSTANT(SOURCE_SCREEN); @@ -797,14 +827,440 @@ void VisualShaderNodeTexture::_bind_methods() { BIND_ENUM_CONSTANT(SOURCE_2D_NORMAL); BIND_ENUM_CONSTANT(SOURCE_DEPTH); BIND_ENUM_CONSTANT(SOURCE_PORT); + BIND_ENUM_CONSTANT(SOURCE_MAX); + BIND_ENUM_CONSTANT(TYPE_DATA); BIND_ENUM_CONSTANT(TYPE_COLOR); - BIND_ENUM_CONSTANT(TYPE_NORMALMAP); + BIND_ENUM_CONSTANT(TYPE_NORMAL_MAP); + BIND_ENUM_CONSTANT(TYPE_MAX); } VisualShaderNodeTexture::VisualShaderNodeTexture() { - texture_type = TYPE_DATA; - source = SOURCE_TEXTURE; +} + +////////////// CurveTexture + +String VisualShaderNodeCurveTexture::get_caption() const { + return "CurveTexture"; +} + +int VisualShaderNodeCurveTexture::get_input_port_count() const { + return 1; +} + +VisualShaderNodeCurveTexture::PortType VisualShaderNodeCurveTexture::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeCurveTexture::get_input_port_name(int p_port) const { + return String(); +} + +int VisualShaderNodeCurveTexture::get_output_port_count() const { + return 1; +} + +VisualShaderNodeCurveTexture::PortType VisualShaderNodeCurveTexture::get_output_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeCurveTexture::get_output_port_name(int p_port) const { + return String(); +} + +void VisualShaderNodeCurveTexture::set_texture(Ref<CurveTexture> p_texture) { + texture = p_texture; + emit_changed(); +} + +Ref<CurveTexture> VisualShaderNodeCurveTexture::get_texture() const { + return texture; +} + +Vector<StringName> VisualShaderNodeCurveTexture::get_editable_properties() const { + Vector<StringName> props; + props.push_back("texture"); + return props; +} + +String VisualShaderNodeCurveTexture::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + return "uniform sampler2D " + make_unique_id(p_type, p_id, "curve") + ";\n"; +} + +String VisualShaderNodeCurveTexture::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 { + if (p_input_vars[0] == String()) { + return " " + p_output_vars[0] + " = 0.0;\n"; + } + String id = make_unique_id(p_type, p_id, "curve"); + String code; + code += " " + p_output_vars[0] + " = texture(" + id + ", vec2(" + p_input_vars[0] + ")).r;\n"; + return code; +} + +Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCurveTexture::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "curve"); + dtp.param = texture; + Vector<VisualShader::DefaultTextureParam> ret; + ret.push_back(dtp); + return ret; +} + +void VisualShaderNodeCurveTexture::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_texture", "texture"), &VisualShaderNodeCurveTexture::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &VisualShaderNodeCurveTexture::get_texture); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_texture", "get_texture"); +} + +bool VisualShaderNodeCurveTexture::is_use_prop_slots() const { + return true; +} + +VisualShaderNodeCurveTexture::VisualShaderNodeCurveTexture() { + simple_decl = true; + allow_v_resize = false; +} + +////////////// CurveXYZTexture + +String VisualShaderNodeCurveXYZTexture::get_caption() const { + return "CurveXYZTexture"; +} + +int VisualShaderNodeCurveXYZTexture::get_input_port_count() const { + return 1; +} + +VisualShaderNodeCurveXYZTexture::PortType VisualShaderNodeCurveXYZTexture::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeCurveXYZTexture::get_input_port_name(int p_port) const { + return String(); +} + +int VisualShaderNodeCurveXYZTexture::get_output_port_count() const { + return 1; +} + +VisualShaderNodeCurveXYZTexture::PortType VisualShaderNodeCurveXYZTexture::get_output_port_type(int p_port) const { + return PORT_TYPE_VECTOR; +} + +String VisualShaderNodeCurveXYZTexture::get_output_port_name(int p_port) const { + return String(); +} + +void VisualShaderNodeCurveXYZTexture::set_texture(Ref<CurveXYZTexture> p_texture) { + texture = p_texture; + emit_changed(); +} + +Ref<CurveXYZTexture> VisualShaderNodeCurveXYZTexture::get_texture() const { + return texture; +} + +Vector<StringName> VisualShaderNodeCurveXYZTexture::get_editable_properties() const { + Vector<StringName> props; + props.push_back("texture"); + return props; +} + +String VisualShaderNodeCurveXYZTexture::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + return "uniform sampler2D " + make_unique_id(p_type, p_id, "curve3d") + ";\n"; +} + +String VisualShaderNodeCurveXYZTexture::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 { + if (p_input_vars[0] == String()) { + return " " + p_output_vars[0] + " = vec3(0.0);\n"; + } + String id = make_unique_id(p_type, p_id, "curve3d"); + String code; + code += " " + p_output_vars[0] + " = texture(" + id + ", vec2(" + p_input_vars[0] + ")).rgb;\n"; + return code; +} + +Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCurveXYZTexture::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "curve3d"); + dtp.param = texture; + Vector<VisualShader::DefaultTextureParam> ret; + ret.push_back(dtp); + return ret; +} + +void VisualShaderNodeCurveXYZTexture::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_texture", "texture"), &VisualShaderNodeCurveXYZTexture::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &VisualShaderNodeCurveXYZTexture::get_texture); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "CurveXYZTexture"), "set_texture", "get_texture"); +} + +bool VisualShaderNodeCurveXYZTexture::is_use_prop_slots() const { + return true; +} + +VisualShaderNodeCurveXYZTexture::VisualShaderNodeCurveXYZTexture() { + simple_decl = true; + allow_v_resize = false; +} + +////////////// Sample3D + +int VisualShaderNodeSample3D::get_input_port_count() const { + return 3; +} + +VisualShaderNodeSample3D::PortType VisualShaderNodeSample3D::get_input_port_type(int p_port) const { + switch (p_port) { + case 0: + return PORT_TYPE_VECTOR; + case 1: + return PORT_TYPE_SCALAR; + case 2: + return PORT_TYPE_SAMPLER; + default: + return PORT_TYPE_SCALAR; + } +} + +String VisualShaderNodeSample3D::get_input_port_name(int p_port) const { + switch (p_port) { + case 0: + return "uvw"; + case 1: + return "lod"; + default: + return ""; + } +} + +int VisualShaderNodeSample3D::get_output_port_count() const { + return 2; +} + +VisualShaderNodeSample3D::PortType VisualShaderNodeSample3D::get_output_port_type(int p_port) const { + return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR; +} + +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"; + } + return ""; +} + +String VisualShaderNodeSample3D::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 default_uv; + if (p_mode != Shader::MODE_PARTICLES && p_mode != Shader::MODE_SKY) { + default_uv = "vec3(UV, 0.0)"; + } else { + default_uv = "vec3(0.0)"; + } + + String code; + if (source == SOURCE_TEXTURE || source == SOURCE_PORT) { + String id; + code += " {\n"; + if (source == SOURCE_TEXTURE) { + id = make_unique_id(p_type, p_id, "tex3d"); + } else { + id = p_input_vars[2]; + } + if (id != String()) { + if (p_input_vars[0] == String()) { // Use UV by default. + if (p_input_vars[1] == String()) { + code += " vec4 " + id + "_tex_read = texture(" + id + ", " + default_uv + ");\n"; + } else { + code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n"; + } + } else if (p_input_vars[1] == String()) { + //no lod + code += " vec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n"; + } else { + code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + } + } else { + code += " vec4 " + id + "_tex_read = vec4(0.0);\n"; + } + + code += " " + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n"; + code += " " + p_output_vars[1] + " = " + id + "_tex_read.a;\n"; + code += " }\n"; + return code; + } + code += " " + p_output_vars[0] + " = vec3(0.0);\n"; + code += " " + p_output_vars[1] + " = 1.0;\n"; + return code; +} + +void VisualShaderNodeSample3D::set_source(Source p_source) { + ERR_FAIL_INDEX(int(p_source), int(SOURCE_MAX)); + if (source == p_source) { + return; + } + source = p_source; + emit_changed(); + emit_signal(SNAME("editor_refresh_request")); +} + +VisualShaderNodeSample3D::Source VisualShaderNodeSample3D::get_source() const { + return source; +} + +void VisualShaderNodeSample3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_source", "value"), &VisualShaderNodeSample3D::set_source); + ClassDB::bind_method(D_METHOD("get_source"), &VisualShaderNodeSample3D::get_source); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,SamplerPort"), "set_source", "get_source"); + + BIND_ENUM_CONSTANT(SOURCE_TEXTURE); + BIND_ENUM_CONSTANT(SOURCE_PORT); + BIND_ENUM_CONSTANT(SOURCE_MAX); +} + +String VisualShaderNodeSample3D::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const { + if (is_input_port_connected(2) && source != SOURCE_PORT) { + return TTR("The sampler port is connected but not used. Consider changing the source to 'SamplerPort'."); + } + + if (source == SOURCE_TEXTURE) { + return String(); // all good + } + if (source == SOURCE_PORT) { + return String(); // all good + } + return TTR("Invalid source for shader."); +} + +VisualShaderNodeSample3D::VisualShaderNodeSample3D() { + simple_decl = false; +} + +////////////// Texture2DArray + +String VisualShaderNodeTexture2DArray::get_caption() const { + return "Texture2DArray"; +} + +String VisualShaderNodeTexture2DArray::get_input_port_name(int p_port) const { + if (p_port == 2) { + return "sampler2DArray"; + } + return VisualShaderNodeSample3D::get_input_port_name(p_port); +} + +Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture2DArray::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "tex3d"); + dtp.param = texture_array; + Vector<VisualShader::DefaultTextureParam> ret; + ret.push_back(dtp); + return ret; +} + +String VisualShaderNodeTexture2DArray::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + if (source == SOURCE_TEXTURE) { + return "uniform sampler2DArray " + make_unique_id(p_type, p_id, "tex3d") + ";\n"; + } + return String(); +} + +void VisualShaderNodeTexture2DArray::set_texture_array(Ref<Texture2DArray> p_texture_array) { + texture_array = p_texture_array; + emit_changed(); +} + +Ref<Texture2DArray> VisualShaderNodeTexture2DArray::get_texture_array() const { + return texture_array; +} + +Vector<StringName> VisualShaderNodeTexture2DArray::get_editable_properties() const { + Vector<StringName> props; + props.push_back("source"); + if (source == SOURCE_TEXTURE) { + props.push_back("texture_array"); + } + return props; +} + +void VisualShaderNodeTexture2DArray::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_texture_array", "value"), &VisualShaderNodeTexture2DArray::set_texture_array); + ClassDB::bind_method(D_METHOD("get_texture_array"), &VisualShaderNodeTexture2DArray::get_texture_array); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_array", PROPERTY_HINT_RESOURCE_TYPE, "Texture2DArray"), "set_texture_array", "get_texture_array"); +} + +VisualShaderNodeTexture2DArray::VisualShaderNodeTexture2DArray() { +} + +////////////// Texture3D + +String VisualShaderNodeTexture3D::get_caption() const { + return "Texture3D"; +} + +String VisualShaderNodeTexture3D::get_input_port_name(int p_port) const { + if (p_port == 2) { + return "sampler3D"; + } + return VisualShaderNodeSample3D::get_input_port_name(p_port); +} + +Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture3D::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "tex3d"); + dtp.param = texture; + Vector<VisualShader::DefaultTextureParam> ret; + ret.push_back(dtp); + return ret; +} + +String VisualShaderNodeTexture3D::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + if (source == SOURCE_TEXTURE) { + return "uniform sampler3D " + make_unique_id(p_type, p_id, "tex3d") + ";\n"; + } + return String(); +} + +void VisualShaderNodeTexture3D::set_texture(Ref<Texture3D> p_texture) { + texture = p_texture; + emit_changed(); +} + +Ref<Texture3D> VisualShaderNodeTexture3D::get_texture() const { + return texture; +} + +Vector<StringName> VisualShaderNodeTexture3D::get_editable_properties() const { + Vector<StringName> props; + props.push_back("source"); + if (source == SOURCE_TEXTURE) { + props.push_back("texture"); + } + return props; +} + +void VisualShaderNodeTexture3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_texture", "value"), &VisualShaderNodeTexture3D::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &VisualShaderNodeTexture3D::get_texture); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture"); +} + +VisualShaderNodeTexture3D::VisualShaderNodeTexture3D() { } ////////////// Cubemap @@ -855,6 +1311,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"); @@ -865,13 +1328,19 @@ Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCubemap::get_default_t } String VisualShaderNodeCubemap::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - if (source == SOURCE_TEXTURE) { String u = "uniform samplerCube " + make_unique_id(p_type, p_id, "cube"); switch (texture_type) { - case TYPE_DATA: break; - case TYPE_COLOR: u += " : hint_albedo"; break; - case TYPE_NORMALMAP: u += " : hint_normal"; break; + case TYPE_DATA: + break; + case TYPE_COLOR: + u += " : hint_albedo"; + break; + case TYPE_NORMAL_MAP: + u += " : hint_normal"; + break; + default: + break; } return u + ";\n"; } @@ -879,6 +1348,12 @@ String VisualShaderNodeCubemap::generate_global(Shader::Mode p_mode, VisualShade } String VisualShaderNodeCubemap::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 default_uv; + if (p_mode != Shader::MODE_PARTICLES && p_mode != Shader::MODE_SKY) { + default_uv = "vec3(UV, 0.0)"; + } else { + default_uv = "vec3(0.0)"; + } String code; String id; @@ -890,67 +1365,73 @@ String VisualShaderNodeCubemap::generate_code(Shader::Mode p_mode, VisualShader: return String(); } - code += "\t{\n"; + code += " {\n"; if (id == String()) { - code += "\t\tvec4 " + id + "_read = vec4(0.0);\n"; - code += "\t\t" + p_output_vars[0] + " = " + id + "_read.rgb;\n"; - code += "\t\t" + p_output_vars[1] + " = " + id + "_read.a;\n"; - code += "\t}\n"; + code += " vec4 " + id + "_read = vec4(0.0);\n"; + code += " " + p_output_vars[0] + " = " + id + "_read.rgb;\n"; + code += " " + p_output_vars[1] + " = " + id + "_read.a;\n"; + code += " }\n"; return code; } if (p_input_vars[0] == String()) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\t\tvec4 " + id + "_read = texture(" + id + " , vec3(UV, 0.0));\n"; + code += " vec4 " + id + "_read = texture(" + id + ", " + default_uv + ");\n"; } else { - code += "\t\tvec4 " + id + "_read = textureLod(" + id + " , vec3(UV, 0.0)" + " , " + p_input_vars[1] + " );\n"; + code += " vec4 " + id + "_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + " );\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\t\tvec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ");\n"; + code += " vec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ");\n"; } else { - code += "\t\tvec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + code += " vec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } - code += "\t\t" + p_output_vars[0] + " = " + id + "_read.rgb;\n"; - code += "\t\t" + p_output_vars[1] + " = " + id + "_read.a;\n"; - code += "\t}\n"; + code += " " + p_output_vars[0] + " = " + id + "_read.rgb;\n"; + code += " " + p_output_vars[1] + " = " + id + "_read.a;\n"; + code += " }\n"; return code; } String VisualShaderNodeCubemap::get_input_port_default_hint(int p_port) const { if (p_port == 0) { - return "vec3(UV, 0.0)"; + return "default"; } return ""; } void VisualShaderNodeCubemap::set_source(Source p_source) { + ERR_FAIL_INDEX(int(p_source), int(SOURCE_MAX)); + if (source == p_source) { + return; + } source = p_source; emit_changed(); - emit_signal("editor_refresh_request"); + emit_signal(SNAME("editor_refresh_request")); } VisualShaderNodeCubemap::Source VisualShaderNodeCubemap::get_source() const { return source; } -void VisualShaderNodeCubemap::set_cube_map(Ref<Cubemap> p_value) { - - cube_map = p_value; +void VisualShaderNodeCubemap::set_cube_map(Ref<Cubemap> p_cube_map) { + cube_map = p_cube_map; emit_changed(); } Ref<Cubemap> VisualShaderNodeCubemap::get_cube_map() const { - return cube_map; } -void VisualShaderNodeCubemap::set_texture_type(TextureType p_type) { - texture_type = p_type; +void VisualShaderNodeCubemap::set_texture_type(TextureType p_texture_type) { + ERR_FAIL_INDEX(int(p_texture_type), int(TYPE_MAX)); + if (texture_type == p_texture_type) { + return; + } + texture_type = p_texture_type; emit_changed(); } @@ -968,8 +1449,14 @@ Vector<StringName> VisualShaderNodeCubemap::get_editable_properties() const { return props; } -void VisualShaderNodeCubemap::_bind_methods() { +String VisualShaderNodeCubemap::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const { + if (is_input_port_connected(2) && source != SOURCE_PORT) { + return TTR("The sampler port is connected but not used. Consider changing the source to 'SamplerPort'."); + } + return String(); +} +void VisualShaderNodeCubemap::_bind_methods() { ClassDB::bind_method(D_METHOD("set_source", "value"), &VisualShaderNodeCubemap::set_source); ClassDB::bind_method(D_METHOD("get_source"), &VisualShaderNodeCubemap::get_source); @@ -981,19 +1468,19 @@ void VisualShaderNodeCubemap::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,SamplerPort"), "set_source", "get_source"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "cube_map", PROPERTY_HINT_RESOURCE_TYPE, "Cubemap"), "set_cube_map", "get_cube_map"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normalmap"), "set_texture_type", "get_texture_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map"), "set_texture_type", "get_texture_type"); BIND_ENUM_CONSTANT(SOURCE_TEXTURE); BIND_ENUM_CONSTANT(SOURCE_PORT); + BIND_ENUM_CONSTANT(SOURCE_MAX); BIND_ENUM_CONSTANT(TYPE_DATA); BIND_ENUM_CONSTANT(TYPE_COLOR); - BIND_ENUM_CONSTANT(TYPE_NORMALMAP); + BIND_ENUM_CONSTANT(TYPE_NORMAL_MAP); + BIND_ENUM_CONSTANT(TYPE_MAX); } VisualShaderNodeCubemap::VisualShaderNodeCubemap() { - texture_type = TYPE_DATA; - source = SOURCE_TEXTURE; simple_decl = false; } @@ -1028,33 +1515,54 @@ String VisualShaderNodeFloatOp::get_output_port_name(int p_port) const { } String VisualShaderNodeFloatOp::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 = "\t" + p_output_vars[0] + " = "; + String code = " " + p_output_vars[0] + " = "; switch (op) { - - case OP_ADD: code += p_input_vars[0] + " + " + p_input_vars[1] + ";\n"; break; - case OP_SUB: code += p_input_vars[0] + " - " + p_input_vars[1] + ";\n"; break; - case OP_MUL: code += p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; break; - case OP_DIV: code += p_input_vars[0] + " / " + p_input_vars[1] + ";\n"; break; - case OP_MOD: code += "mod(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_POW: code += "pow(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_MAX: code += "max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_MIN: code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_ATAN2: code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_STEP: code += "step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_ADD: + code += p_input_vars[0] + " + " + p_input_vars[1] + ";\n"; + break; + case OP_SUB: + code += p_input_vars[0] + " - " + p_input_vars[1] + ";\n"; + break; + case OP_MUL: + code += p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; + break; + case OP_DIV: + code += p_input_vars[0] + " / " + p_input_vars[1] + ";\n"; + break; + case OP_MOD: + code += "mod(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_POW: + code += "pow(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_MAX: + code += "max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_MIN: + code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_ATAN2: + code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_STEP: + code += "step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + default: + break; } - return code; } void VisualShaderNodeFloatOp::set_operator(Operator p_op) { - + ERR_FAIL_INDEX(int(p_op), int(OP_ENUM_SIZE)); + if (op == p_op) { + return; + } op = p_op; emit_changed(); } VisualShaderNodeFloatOp::Operator VisualShaderNodeFloatOp::get_operator() const { - return op; } @@ -1065,11 +1573,10 @@ Vector<StringName> VisualShaderNodeFloatOp::get_editable_properties() const { } void VisualShaderNodeFloatOp::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeFloatOp::set_operator); ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeFloatOp::get_operator); - ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Sub,Multiply,Divide,Remainder,Power,Max,Min,Atan2,Step"), "set_operator", "get_operator"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Subtract,Multiply,Divide,Remainder,Power,Max,Min,ATan2,Step"), "set_operator", "get_operator"); BIND_ENUM_CONSTANT(OP_ADD); BIND_ENUM_CONSTANT(OP_SUB); @@ -1081,10 +1588,10 @@ void VisualShaderNodeFloatOp::_bind_methods() { BIND_ENUM_CONSTANT(OP_MIN); BIND_ENUM_CONSTANT(OP_ATAN2); BIND_ENUM_CONSTANT(OP_STEP); + BIND_ENUM_CONSTANT(OP_ENUM_SIZE); } VisualShaderNodeFloatOp::VisualShaderNodeFloatOp() { - op = OP_ADD; set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); } @@ -1120,24 +1627,41 @@ String VisualShaderNodeIntOp::get_output_port_name(int p_port) const { } String VisualShaderNodeIntOp::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 = "\t" + p_output_vars[0] + " = "; + String code = " " + p_output_vars[0] + " = "; switch (op) { - - case OP_ADD: code += p_input_vars[0] + " + " + p_input_vars[1] + ";\n"; break; - case OP_SUB: code += p_input_vars[0] + " - " + p_input_vars[1] + ";\n"; break; - case OP_MUL: code += p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; break; - case OP_DIV: code += p_input_vars[0] + " / " + p_input_vars[1] + ";\n"; break; - case OP_MOD: code += p_input_vars[0] + " % " + p_input_vars[1] + ";\n"; break; - case OP_MAX: code += "max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_MIN: code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_ADD: + code += p_input_vars[0] + " + " + p_input_vars[1] + ";\n"; + break; + case OP_SUB: + code += p_input_vars[0] + " - " + p_input_vars[1] + ";\n"; + break; + case OP_MUL: + code += p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; + break; + case OP_DIV: + code += p_input_vars[0] + " / " + p_input_vars[1] + ";\n"; + break; + case OP_MOD: + code += p_input_vars[0] + " % " + p_input_vars[1] + ";\n"; + break; + case OP_MAX: + code += "max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_MIN: + code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + default: + break; } return code; } void VisualShaderNodeIntOp::set_operator(Operator p_op) { - + ERR_FAIL_INDEX(int(p_op), OP_ENUM_SIZE); + if (op == p_op) { + return; + } op = p_op; emit_changed(); } @@ -1153,11 +1677,10 @@ Vector<StringName> VisualShaderNodeIntOp::get_editable_properties() const { } void VisualShaderNodeIntOp::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeIntOp::set_operator); ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeIntOp::get_operator); - ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Sub,Multiply,Divide,Remainder,Max,Min"), "set_operator", "get_operator"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Subtract,Multiply,Divide,Remainder,Max,Min"), "set_operator", "get_operator"); BIND_ENUM_CONSTANT(OP_ADD); BIND_ENUM_CONSTANT(OP_SUB); @@ -1166,10 +1689,10 @@ void VisualShaderNodeIntOp::_bind_methods() { BIND_ENUM_CONSTANT(OP_MOD); BIND_ENUM_CONSTANT(OP_MAX); BIND_ENUM_CONSTANT(OP_MIN); + BIND_ENUM_CONSTANT(OP_ENUM_SIZE); } VisualShaderNodeIntOp::VisualShaderNodeIntOp() { - op = OP_ADD; set_input_port_default_value(0, 0); set_input_port_default_value(1, 0); } @@ -1205,35 +1728,61 @@ String VisualShaderNodeVectorOp::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorOp::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 = "\t" + p_output_vars[0] + " = "; + String code = " " + p_output_vars[0] + " = "; switch (op) { - - case OP_ADD: code += p_input_vars[0] + " + " + p_input_vars[1] + ";\n"; break; - case OP_SUB: code += p_input_vars[0] + " - " + p_input_vars[1] + ";\n"; break; - case OP_MUL: code += p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; break; - case OP_DIV: code += p_input_vars[0] + " / " + p_input_vars[1] + ";\n"; break; - case OP_MOD: code += "mod(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_POW: code += "pow(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_MAX: code += "max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_MIN: code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_CROSS: code += "cross(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_ATAN2: code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_REFLECT: code += "reflect(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_STEP: code += "step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_ADD: + code += p_input_vars[0] + " + " + p_input_vars[1] + ";\n"; + break; + case OP_SUB: + code += p_input_vars[0] + " - " + p_input_vars[1] + ";\n"; + break; + case OP_MUL: + code += p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; + break; + case OP_DIV: + code += p_input_vars[0] + " / " + p_input_vars[1] + ";\n"; + break; + case OP_MOD: + code += "mod(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_POW: + code += "pow(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_MAX: + code += "max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_MIN: + code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_CROSS: + code += "cross(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_ATAN2: + code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_REFLECT: + code += "reflect(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_STEP: + code += "step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + default: + break; } return code; } void VisualShaderNodeVectorOp::set_operator(Operator p_op) { - + ERR_FAIL_INDEX(int(p_op), int(OP_ENUM_SIZE)); + if (op == p_op) { + return; + } op = p_op; emit_changed(); } VisualShaderNodeVectorOp::Operator VisualShaderNodeVectorOp::get_operator() const { - return op; } @@ -1244,11 +1793,10 @@ Vector<StringName> VisualShaderNodeVectorOp::get_editable_properties() const { } void VisualShaderNodeVectorOp::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeVectorOp::set_operator); ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeVectorOp::get_operator); - ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Sub,Multiply,Divide,Remainder,Power,Max,Min,Cross,Atan2,Reflect,Step"), "set_operator", "get_operator"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Subtract,Multiply,Divide,Remainder,Power,Max,Min,Cross,ATan2,Reflect,Step"), "set_operator", "get_operator"); BIND_ENUM_CONSTANT(OP_ADD); BIND_ENUM_CONSTANT(OP_SUB); @@ -1262,10 +1810,10 @@ void VisualShaderNodeVectorOp::_bind_methods() { BIND_ENUM_CONSTANT(OP_ATAN2); BIND_ENUM_CONSTANT(OP_REFLECT); BIND_ENUM_CONSTANT(OP_STEP); + BIND_ENUM_CONSTANT(OP_ENUM_SIZE); } VisualShaderNodeVectorOp::VisualShaderNodeVectorOp() { - op = OP_ADD; set_input_port_default_value(0, Vector3()); set_input_port_default_value(1, Vector3()); } @@ -1301,90 +1849,84 @@ String VisualShaderNodeColorOp::get_output_port_name(int p_port) const { } String VisualShaderNodeColorOp::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; static const char *axisn[3] = { "x", "y", "z" }; switch (op) { case OP_SCREEN: { - - code += "\t" + p_output_vars[0] + " = vec3(1.0) - (vec3(1.0) - " + p_input_vars[0] + ") * (vec3(1.0) - " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = vec3(1.0) - (vec3(1.0) - " + p_input_vars[0] + ") * (vec3(1.0) - " + p_input_vars[1] + ");\n"; } break; case OP_DIFFERENCE: { - - code += "\t" + p_output_vars[0] + " = abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ");\n"; } break; case OP_DARKEN: { - - code += "\t" + p_output_vars[0] + " = min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } break; case OP_LIGHTEN: { - - code += "\t" + p_output_vars[0] + " = max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } break; case OP_OVERLAY: { - for (int i = 0; i < 3; i++) { - code += "\t{\n"; - code += "\t\tfloat base = " + p_input_vars[0] + "." + axisn[i] + ";\n"; - code += "\t\tfloat blend = " + p_input_vars[1] + "." + axisn[i] + ";\n"; - code += "\t\tif (base < 0.5) {\n"; - code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = 2.0 * base * blend;\n"; - code += "\t\t} else {\n"; - code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = 1.0 - 2.0 * (1.0 - blend) * (1.0 - base);\n"; - code += "\t\t}\n"; - code += "\t}\n"; + code += " {\n"; + code += " float base = " + p_input_vars[0] + "." + axisn[i] + ";\n"; + code += " float blend = " + p_input_vars[1] + "." + axisn[i] + ";\n"; + code += " if (base < 0.5) {\n"; + code += " " + p_output_vars[0] + "." + axisn[i] + " = 2.0 * base * blend;\n"; + code += " } else {\n"; + code += " " + p_output_vars[0] + "." + axisn[i] + " = 1.0 - 2.0 * (1.0 - blend) * (1.0 - base);\n"; + code += " }\n"; + code += " }\n"; } } break; case OP_DODGE: { - - code += "\t" + p_output_vars[0] + " = (" + p_input_vars[0] + ") / (vec3(1.0) - " + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = (" + p_input_vars[0] + ") / (vec3(1.0) - " + p_input_vars[1] + ");\n"; } break; case OP_BURN: { - - code += "\t" + p_output_vars[0] + " = vec3(1.0) - (vec3(1.0) - " + p_input_vars[0] + ") / (" + p_input_vars[1] + ");\n"; + code += " " + p_output_vars[0] + " = vec3(1.0) - (vec3(1.0) - " + p_input_vars[0] + ") / (" + p_input_vars[1] + ");\n"; } break; case OP_SOFT_LIGHT: { - for (int i = 0; i < 3; i++) { - code += "\t{\n"; - code += "\t\tfloat base = " + p_input_vars[0] + "." + axisn[i] + ";\n"; - code += "\t\tfloat blend = " + p_input_vars[1] + "." + axisn[i] + ";\n"; - code += "\t\tif (base < 0.5) {\n"; - code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (base * (blend + 0.5));\n"; - code += "\t\t} else {\n"; - code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (1.0 - (1.0 - base) * (1.0 - (blend - 0.5)));\n"; - code += "\t\t}\n"; - code += "\t}\n"; + code += " {\n"; + code += " float base = " + p_input_vars[0] + "." + axisn[i] + ";\n"; + code += " float blend = " + p_input_vars[1] + "." + axisn[i] + ";\n"; + code += " if (base < 0.5) {\n"; + code += " " + p_output_vars[0] + "." + axisn[i] + " = (base * (blend + 0.5));\n"; + code += " } else {\n"; + code += " " + p_output_vars[0] + "." + axisn[i] + " = (1.0 - (1.0 - base) * (1.0 - (blend - 0.5)));\n"; + code += " }\n"; + code += " }\n"; } } break; case OP_HARD_LIGHT: { - for (int i = 0; i < 3; i++) { - code += "\t{\n"; - code += "\t\tfloat base = " + p_input_vars[0] + "." + axisn[i] + ";\n"; - code += "\t\tfloat blend = " + p_input_vars[1] + "." + axisn[i] + ";\n"; - code += "\t\tif (base < 0.5) {\n"; - code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (base * (2.0 * blend));\n"; - code += "\t\t} else {\n"; - code += "\t\t\t" + p_output_vars[0] + "." + axisn[i] + " = (1.0 - (1.0 - base) * (1.0 - 2.0 * (blend - 0.5)));\n"; - code += "\t\t}\n"; - code += "\t}\n"; + code += " {\n"; + code += " float base = " + p_input_vars[0] + "." + axisn[i] + ";\n"; + code += " float blend = " + p_input_vars[1] + "." + axisn[i] + ";\n"; + code += " if (base < 0.5) {\n"; + code += " " + p_output_vars[0] + "." + axisn[i] + " = (base * (2.0 * blend));\n"; + code += " } else {\n"; + code += " " + p_output_vars[0] + "." + axisn[i] + " = (1.0 - (1.0 - base) * (1.0 - 2.0 * (blend - 0.5)));\n"; + code += " }\n"; + code += " }\n"; } } break; + default: + break; } return code; } void VisualShaderNodeColorOp::set_operator(Operator p_op) { - - op = p_op; - switch (op) { + ERR_FAIL_INDEX(int(p_op), int(OP_MAX)); + if (op == p_op) { + return; + } + switch (p_op) { case OP_SCREEN: simple_decl = true; break; @@ -1412,12 +1954,14 @@ void VisualShaderNodeColorOp::set_operator(Operator p_op) { case OP_HARD_LIGHT: simple_decl = false; break; + default: + break; } + op = p_op; emit_changed(); } VisualShaderNodeColorOp::Operator VisualShaderNodeColorOp::get_operator() const { - return op; } @@ -1428,11 +1972,10 @@ Vector<StringName> VisualShaderNodeColorOp::get_editable_properties() const { } void VisualShaderNodeColorOp::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeColorOp::set_operator); ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeColorOp::get_operator); - ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Screen,Difference,Darken,Lighten,Overlay,Dodge,Burn,SoftLight,HardLight"), "set_operator", "get_operator"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Screen,Difference,Darken,Lighten,Overlay,Dodge,Burn,Soft Light,Hard Light"), "set_operator", "get_operator"); BIND_ENUM_CONSTANT(OP_SCREEN); BIND_ENUM_CONSTANT(OP_DIFFERENCE); @@ -1443,91 +1986,109 @@ void VisualShaderNodeColorOp::_bind_methods() { BIND_ENUM_CONSTANT(OP_BURN); BIND_ENUM_CONSTANT(OP_SOFT_LIGHT); BIND_ENUM_CONSTANT(OP_HARD_LIGHT); + BIND_ENUM_CONSTANT(OP_MAX); } VisualShaderNodeColorOp::VisualShaderNodeColorOp() { - op = OP_SCREEN; set_input_port_default_value(0, Vector3()); set_input_port_default_value(1, Vector3()); } -////////////// Transform Mult +////////////// Transform Op -String VisualShaderNodeTransformMult::get_caption() const { - return "TransformMult"; +String VisualShaderNodeTransformOp::get_caption() const { + return "TransformOp"; } -int VisualShaderNodeTransformMult::get_input_port_count() const { +int VisualShaderNodeTransformOp::get_input_port_count() const { return 2; } -VisualShaderNodeTransformMult::PortType VisualShaderNodeTransformMult::get_input_port_type(int p_port) const { +VisualShaderNodeTransformOp::PortType VisualShaderNodeTransformOp::get_input_port_type(int p_port) const { return PORT_TYPE_TRANSFORM; } -String VisualShaderNodeTransformMult::get_input_port_name(int p_port) const { +String VisualShaderNodeTransformOp::get_input_port_name(int p_port) const { return p_port == 0 ? "a" : "b"; } -int VisualShaderNodeTransformMult::get_output_port_count() const { +int VisualShaderNodeTransformOp::get_output_port_count() const { return 1; } -VisualShaderNodeTransformMult::PortType VisualShaderNodeTransformMult::get_output_port_type(int p_port) const { +VisualShaderNodeTransformOp::PortType VisualShaderNodeTransformOp::get_output_port_type(int p_port) const { return PORT_TYPE_TRANSFORM; } -String VisualShaderNodeTransformMult::get_output_port_name(int p_port) const { +String VisualShaderNodeTransformOp::get_output_port_name(int p_port) const { return "mult"; //no output port means the editor will be used as port } -String VisualShaderNodeTransformMult::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 { - - if (op == OP_AxB) { - return "\t" + p_output_vars[0] + " = " + p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; - } else if (op == OP_BxA) { - return "\t" + p_output_vars[0] + " = " + p_input_vars[1] + " * " + p_input_vars[0] + ";\n"; - } else if (op == OP_AxB_COMP) { - return "\t" + p_output_vars[0] + " = matrixCompMult(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; - } else { - return "\t" + p_output_vars[0] + " = matrixCompMult(" + p_input_vars[1] + ", " + p_input_vars[0] + ");\n"; +String VisualShaderNodeTransformOp::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 { + switch (op) { + case OP_AxB: + return " " + p_output_vars[0] + " = " + p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; + case OP_BxA: + return " " + p_output_vars[0] + " = " + p_input_vars[1] + " * " + p_input_vars[0] + ";\n"; + case OP_AxB_COMP: + return " " + p_output_vars[0] + " = matrixCompMult(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + case OP_BxA_COMP: + return " " + p_output_vars[0] + " = matrixCompMult(" + p_input_vars[1] + ", " + p_input_vars[0] + ");\n"; + case OP_ADD: + return " " + p_output_vars[0] + " = " + p_input_vars[0] + " + " + p_input_vars[1] + ";\n"; + case OP_A_MINUS_B: + return " " + p_output_vars[0] + " = " + p_input_vars[0] + " - " + p_input_vars[1] + ";\n"; + case OP_B_MINUS_A: + return " " + p_output_vars[0] + " = " + p_input_vars[1] + " - " + p_input_vars[0] + ";\n"; + case OP_A_DIV_B: + return " " + p_output_vars[0] + " = " + p_input_vars[0] + " / " + p_input_vars[1] + ";\n"; + case OP_B_DIV_A: + return " " + p_output_vars[0] + " = " + p_input_vars[1] + " / " + p_input_vars[0] + ";\n"; + default: + return ""; } } -void VisualShaderNodeTransformMult::set_operator(Operator p_op) { - +void VisualShaderNodeTransformOp::set_operator(Operator p_op) { + ERR_FAIL_INDEX(int(p_op), int(OP_MAX)); + if (op == p_op) { + return; + } op = p_op; emit_changed(); } -VisualShaderNodeTransformMult::Operator VisualShaderNodeTransformMult::get_operator() const { - +VisualShaderNodeTransformOp::Operator VisualShaderNodeTransformOp::get_operator() const { return op; } -Vector<StringName> VisualShaderNodeTransformMult::get_editable_properties() const { +Vector<StringName> VisualShaderNodeTransformOp::get_editable_properties() const { Vector<StringName> props; props.push_back("operator"); return props; } -void VisualShaderNodeTransformMult::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeTransformMult::set_operator); - ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeTransformMult::get_operator); +void VisualShaderNodeTransformOp::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeTransformOp::set_operator); + ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeTransformOp::get_operator); - ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "A x B,B x A,A x B(per component),B x A(per component)"), "set_operator", "get_operator"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "A x B,B x A,A x B(per component),B x A(per component),A + B,A - B,B - A,A / B,B / A"), "set_operator", "get_operator"); BIND_ENUM_CONSTANT(OP_AxB); BIND_ENUM_CONSTANT(OP_BxA); BIND_ENUM_CONSTANT(OP_AxB_COMP); BIND_ENUM_CONSTANT(OP_BxA_COMP); + BIND_ENUM_CONSTANT(OP_ADD); + BIND_ENUM_CONSTANT(OP_A_MINUS_B); + BIND_ENUM_CONSTANT(OP_B_MINUS_A); + BIND_ENUM_CONSTANT(OP_A_DIV_B); + BIND_ENUM_CONSTANT(OP_B_DIV_A); + BIND_ENUM_CONSTANT(OP_MAX); } -VisualShaderNodeTransformMult::VisualShaderNodeTransformMult() { - op = OP_AxB; - set_input_port_default_value(0, Transform()); - set_input_port_default_value(1, Transform()); +VisualShaderNodeTransformOp::VisualShaderNodeTransformOp() { + set_input_port_default_value(0, Transform3D()); + set_input_port_default_value(1, Transform3D()); } ////////////// TransformVec Mult @@ -1562,24 +2123,26 @@ String VisualShaderNodeTransformVecMult::get_output_port_name(int p_port) const String VisualShaderNodeTransformVecMult::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 { if (op == OP_AxB) { - return "\t" + p_output_vars[0] + " = (" + p_input_vars[0] + " * vec4(" + p_input_vars[1] + ", 1.0)).xyz;\n"; + return " " + p_output_vars[0] + " = (" + p_input_vars[0] + " * vec4(" + p_input_vars[1] + ", 1.0)).xyz;\n"; } else if (op == OP_BxA) { - return "\t" + p_output_vars[0] + " = (vec4(" + p_input_vars[1] + ", 1.0) * " + p_input_vars[0] + ").xyz;\n"; + return " " + p_output_vars[0] + " = (vec4(" + p_input_vars[1] + ", 1.0) * " + p_input_vars[0] + ").xyz;\n"; } else if (op == OP_3x3_AxB) { - return "\t" + p_output_vars[0] + " = (" + p_input_vars[0] + " * vec4(" + p_input_vars[1] + ", 0.0)).xyz;\n"; + return " " + p_output_vars[0] + " = (" + p_input_vars[0] + " * vec4(" + p_input_vars[1] + ", 0.0)).xyz;\n"; } else { - return "\t" + p_output_vars[0] + " = (vec4(" + p_input_vars[1] + ", 0.0) * " + p_input_vars[0] + ").xyz;\n"; + return " " + p_output_vars[0] + " = (vec4(" + p_input_vars[1] + ", 0.0) * " + p_input_vars[0] + ").xyz;\n"; } } void VisualShaderNodeTransformVecMult::set_operator(Operator p_op) { - + ERR_FAIL_INDEX(int(p_op), int(OP_MAX)); + if (op == p_op) { + return; + } op = p_op; emit_changed(); } VisualShaderNodeTransformVecMult::Operator VisualShaderNodeTransformVecMult::get_operator() const { - return op; } @@ -1590,7 +2153,6 @@ Vector<StringName> VisualShaderNodeTransformVecMult::get_editable_properties() c } void VisualShaderNodeTransformVecMult::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeTransformVecMult::set_operator); ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeTransformVecMult::get_operator); @@ -1600,11 +2162,11 @@ void VisualShaderNodeTransformVecMult::_bind_methods() { BIND_ENUM_CONSTANT(OP_BxA); BIND_ENUM_CONSTANT(OP_3x3_AxB); BIND_ENUM_CONSTANT(OP_3x3_BxA); + BIND_ENUM_CONSTANT(OP_MAX); } VisualShaderNodeTransformVecMult::VisualShaderNodeTransformVecMult() { - op = OP_AxB; - set_input_port_default_value(0, Transform()); + set_input_port_default_value(0, Transform3D()); set_input_port_default_value(1, Vector3()); } @@ -1639,8 +2201,7 @@ String VisualShaderNodeFloatFunc::get_output_port_name(int p_port) const { } String VisualShaderNodeFloatFunc::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 { - - static const char *scalar_func_id[FUNC_ONEMINUS + 1] = { + static const char *functions[FUNC_MAX] = { "sin($)", "cos($)", "tan($)", @@ -1674,18 +2235,19 @@ String VisualShaderNodeFloatFunc::generate_code(Shader::Mode p_mode, VisualShade "trunc($)", "1.0 - $" }; - - return "\t" + p_output_vars[0] + " = " + String(scalar_func_id[func]).replace("$", p_input_vars[0]) + ";\n"; + return " " + p_output_vars[0] + " = " + String(functions[func]).replace("$", p_input_vars[0]) + ";\n"; } void VisualShaderNodeFloatFunc::set_function(Function p_func) { - + ERR_FAIL_INDEX(int(p_func), int(FUNC_MAX)); + if (func == p_func) { + return; + } func = p_func; emit_changed(); } VisualShaderNodeFloatFunc::Function VisualShaderNodeFloatFunc::get_function() const { - return func; } @@ -1696,7 +2258,6 @@ Vector<StringName> VisualShaderNodeFloatFunc::get_editable_properties() const { } void VisualShaderNodeFloatFunc::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeFloatFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeFloatFunc::get_function); @@ -1734,10 +2295,10 @@ void VisualShaderNodeFloatFunc::_bind_methods() { BIND_ENUM_CONSTANT(FUNC_ROUNDEVEN); BIND_ENUM_CONSTANT(FUNC_TRUNC); BIND_ENUM_CONSTANT(FUNC_ONEMINUS); + BIND_ENUM_CONSTANT(FUNC_MAX); } VisualShaderNodeFloatFunc::VisualShaderNodeFloatFunc() { - func = FUNC_SIGN; set_input_port_default_value(0, 0.0); } @@ -1748,9 +2309,6 @@ String VisualShaderNodeIntFunc::get_caption() const { } int VisualShaderNodeIntFunc::get_input_port_count() const { - if (func == FUNC_CLAMP) { - return 3; - } return 1; } @@ -1759,15 +2317,6 @@ VisualShaderNodeIntFunc::PortType VisualShaderNodeIntFunc::get_input_port_type(i } String VisualShaderNodeIntFunc::get_input_port_name(int p_port) const { - if (func == FUNC_CLAMP) { - if (p_port == 0) { - return ""; - } else if (p_port == 1) { - return "min"; - } else if (p_port == 2) { - return "max"; - } - } return ""; } @@ -1784,33 +2333,25 @@ String VisualShaderNodeIntFunc::get_output_port_name(int p_port) const { } String VisualShaderNodeIntFunc::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 { - if (func == FUNC_CLAMP) { - return "\t" + p_output_vars[0] + " = clamp(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; - } - - static const char *int_func_id[FUNC_SIGN + 1] = { + static const char *functions[FUNC_MAX] = { "abs($)", - "", "-($)", "sign($)" }; - return "\t" + p_output_vars[0] + " = " + String(int_func_id[func]).replace("$", p_input_vars[0]) + ";\n"; + return " " + p_output_vars[0] + " = " + String(functions[func]).replace("$", p_input_vars[0]) + ";\n"; } void VisualShaderNodeIntFunc::set_function(Function p_func) { - if (func != p_func) { - if (p_func == FUNC_CLAMP) { - set_input_port_default_value(1, 0); - set_input_port_default_value(2, 0); - } + ERR_FAIL_INDEX(int(p_func), int(FUNC_MAX)); + if (func == p_func) { + return; } func = p_func; emit_changed(); } VisualShaderNodeIntFunc::Function VisualShaderNodeIntFunc::get_function() const { - return func; } @@ -1821,20 +2362,18 @@ Vector<StringName> VisualShaderNodeIntFunc::get_editable_properties() const { } void VisualShaderNodeIntFunc::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeIntFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeIntFunc::get_function); - ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Abs,Clamp,Negate,Sign"), "set_function", "get_function"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Abs,Negate,Sign"), "set_function", "get_function"); BIND_ENUM_CONSTANT(FUNC_ABS); - BIND_ENUM_CONSTANT(FUNC_CLAMP); BIND_ENUM_CONSTANT(FUNC_NEGATE); BIND_ENUM_CONSTANT(FUNC_SIGN); + BIND_ENUM_CONSTANT(FUNC_MAX); } VisualShaderNodeIntFunc::VisualShaderNodeIntFunc() { - func = FUNC_SIGN; set_input_port_default_value(0, 0); } @@ -1869,8 +2408,7 @@ String VisualShaderNodeVectorFunc::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorFunc::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 { - - static const char *vec_func_id[FUNC_ONEMINUS + 1] = { + static const char *vec_func_id[FUNC_MAX] = { "normalize($)", "max(min($, vec3(1.0)), vec3(0.0))", "-($)", @@ -1911,45 +2449,47 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad String code; if (func == FUNC_RGB2HSV) { - code += "\t{\n"; - code += "\t\tvec3 c = " + p_input_vars[0] + ";\n"; - code += "\t\tvec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n"; - code += "\t\tvec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n"; - code += "\t\tvec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n"; - code += "\t\tfloat d = q.x - min(q.w, q.y);\n"; - code += "\t\tfloat e = 1.0e-10;\n"; - code += "\t\t" + p_output_vars[0] + " = vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n"; - code += "\t}\n"; + code += " {\n"; + code += " vec3 c = " + p_input_vars[0] + ";\n"; + code += " vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n"; + code += " vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n"; + code += " vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n"; + code += " float d = q.x - min(q.w, q.y);\n"; + code += " float e = 1.0e-10;\n"; + code += " " + p_output_vars[0] + " = vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n"; + code += " }\n"; } else if (func == FUNC_HSV2RGB) { - code += "\t{\n"; - code += "\t\tvec3 c = " + p_input_vars[0] + ";\n"; - code += "\t\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n"; - code += "\t\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n"; - code += "\t\t" + p_output_vars[0] + " = c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n"; - code += "\t}\n"; + code += " {\n"; + code += " vec3 c = " + p_input_vars[0] + ";\n"; + code += " vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n"; + code += " vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n"; + code += " " + p_output_vars[0] + " = c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n"; + code += " }\n"; } else { - code += "\t" + p_output_vars[0] + " = " + String(vec_func_id[func]).replace("$", p_input_vars[0]) + ";\n"; + code += " " + p_output_vars[0] + " = " + String(vec_func_id[func]).replace("$", p_input_vars[0]) + ";\n"; } return code; } void VisualShaderNodeVectorFunc::set_function(Function p_func) { - - func = p_func; - if (func == FUNC_RGB2HSV) { + ERR_FAIL_INDEX(int(p_func), int(FUNC_MAX)); + if (func == p_func) { + return; + } + if (p_func == FUNC_RGB2HSV) { simple_decl = false; - } else if (func == FUNC_HSV2RGB) { + } else if (p_func == FUNC_HSV2RGB) { simple_decl = false; } else { simple_decl = true; } + func = p_func; emit_changed(); } VisualShaderNodeVectorFunc::Function VisualShaderNodeVectorFunc::get_function() const { - return func; } @@ -1960,7 +2500,6 @@ Vector<StringName> VisualShaderNodeVectorFunc::get_editable_properties() const { } void VisualShaderNodeVectorFunc::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeVectorFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeVectorFunc::get_function); @@ -2001,10 +2540,10 @@ void VisualShaderNodeVectorFunc::_bind_methods() { BIND_ENUM_CONSTANT(FUNC_TANH); BIND_ENUM_CONSTANT(FUNC_TRUNC); BIND_ENUM_CONSTANT(FUNC_ONEMINUS); + BIND_ENUM_CONSTANT(FUNC_MAX); } VisualShaderNodeVectorFunc::VisualShaderNodeVectorFunc() { - func = FUNC_NORMALIZE; set_input_port_default_value(0, Vector3()); } @@ -2039,27 +2578,28 @@ String VisualShaderNodeColorFunc::get_output_port_name(int p_port) const { } String VisualShaderNodeColorFunc::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; switch (func) { case FUNC_GRAYSCALE: - code += "\t{\n"; - code += "\t\tvec3 c = " + p_input_vars[0] + ";\n"; - code += "\t\tfloat max1 = max(c.r, c.g);\n"; - code += "\t\tfloat max2 = max(max1, c.b);\n"; - code += "\t\tfloat max3 = max(max1, max2);\n"; - code += "\t\t" + p_output_vars[0] + " = vec3(max3, max3, max3);\n"; - code += "\t}\n"; + code += " {\n"; + code += " vec3 c = " + p_input_vars[0] + ";\n"; + code += " float max1 = max(c.r, c.g);\n"; + code += " float max2 = max(max1, c.b);\n"; + code += " float max3 = max(max1, max2);\n"; + code += " " + p_output_vars[0] + " = vec3(max3, max3, max3);\n"; + code += " }\n"; break; case FUNC_SEPIA: - code += "\t{\n"; - code += "\t\tvec3 c = " + p_input_vars[0] + ";\n"; - code += "\t\tfloat r = (c.r * .393) + (c.g *.769) + (c.b * .189);\n"; - code += "\t\tfloat g = (c.r * .349) + (c.g *.686) + (c.b * .168);\n"; - code += "\t\tfloat b = (c.r * .272) + (c.g *.534) + (c.b * .131);\n"; - code += "\t\t" + p_output_vars[0] + " = vec3(r, g, b);\n"; - code += "\t}\n"; + code += " {\n"; + code += " vec3 c = " + p_input_vars[0] + ";\n"; + code += " float r = (c.r * .393) + (c.g *.769) + (c.b * .189);\n"; + code += " float g = (c.r * .349) + (c.g *.686) + (c.b * .168);\n"; + code += " float b = (c.r * .272) + (c.g *.534) + (c.b * .131);\n"; + code += " " + p_output_vars[0] + " = vec3(r, g, b);\n"; + code += " }\n"; + break; + default: break; } @@ -2067,13 +2607,15 @@ String VisualShaderNodeColorFunc::generate_code(Shader::Mode p_mode, VisualShade } void VisualShaderNodeColorFunc::set_function(Function p_func) { - + ERR_FAIL_INDEX(int(p_func), int(FUNC_MAX)); + if (func == p_func) { + return; + } func = p_func; emit_changed(); } VisualShaderNodeColorFunc::Function VisualShaderNodeColorFunc::get_function() const { - return func; } @@ -2084,7 +2626,6 @@ Vector<StringName> VisualShaderNodeColorFunc::get_editable_properties() const { } void VisualShaderNodeColorFunc::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeColorFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeColorFunc::get_function); @@ -2092,12 +2633,12 @@ void VisualShaderNodeColorFunc::_bind_methods() { BIND_ENUM_CONSTANT(FUNC_GRAYSCALE); BIND_ENUM_CONSTANT(FUNC_SEPIA); + BIND_ENUM_CONSTANT(FUNC_MAX); } VisualShaderNodeColorFunc::VisualShaderNodeColorFunc() { - func = FUNC_GRAYSCALE; - set_input_port_default_value(0, Vector3()); simple_decl = false; + set_input_port_default_value(0, Vector3()); } ////////////// Transform Func @@ -2131,25 +2672,26 @@ String VisualShaderNodeTransformFunc::get_output_port_name(int p_port) const { } String VisualShaderNodeTransformFunc::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 { - - static const char *funcs[FUNC_TRANSPOSE + 1] = { + static const char *functions[FUNC_MAX] = { "inverse($)", "transpose($)" }; String code; - code += "\t" + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; + code += " " + p_output_vars[0] + " = " + String(functions[func]).replace("$", p_input_vars[0]) + ";\n"; return code; } void VisualShaderNodeTransformFunc::set_function(Function p_func) { - + ERR_FAIL_INDEX(int(p_func), int(FUNC_MAX)); + if (func == p_func) { + return; + } func = p_func; emit_changed(); } VisualShaderNodeTransformFunc::Function VisualShaderNodeTransformFunc::get_function() const { - return func; } @@ -2160,7 +2702,6 @@ Vector<StringName> VisualShaderNodeTransformFunc::get_editable_properties() cons } void VisualShaderNodeTransformFunc::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeTransformFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeTransformFunc::get_function); @@ -2168,11 +2709,145 @@ void VisualShaderNodeTransformFunc::_bind_methods() { BIND_ENUM_CONSTANT(FUNC_INVERSE); BIND_ENUM_CONSTANT(FUNC_TRANSPOSE); + BIND_ENUM_CONSTANT(FUNC_MAX); } VisualShaderNodeTransformFunc::VisualShaderNodeTransformFunc() { - func = FUNC_INVERSE; - set_input_port_default_value(0, Transform()); + set_input_port_default_value(0, Transform3D()); +} + +////////////// UV Func + +String VisualShaderNodeUVFunc::get_caption() const { + return "UVFunc"; +} + +int VisualShaderNodeUVFunc::get_input_port_count() const { + return 3; +} + +VisualShaderNodeUVFunc::PortType VisualShaderNodeUVFunc::get_input_port_type(int p_port) const { + switch (p_port) { + case 0: + [[fallthrough]]; // uv + case 1: + return PORT_TYPE_VECTOR; // scale + case 2: + return PORT_TYPE_VECTOR; // offset & pivot + default: + break; + } + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeUVFunc::get_input_port_name(int p_port) const { + switch (p_port) { + case 0: + return "uv"; + case 1: + return "scale"; + case 2: + switch (func) { + case FUNC_PANNING: + return "offset"; + case FUNC_SCALING: + return "pivot"; + default: + break; + } + break; + default: + break; + } + return ""; +} + +String VisualShaderNodeUVFunc::get_input_port_default_hint(int p_port) const { + if (p_port == 0) { + return "UV"; + } + return ""; +} + +int VisualShaderNodeUVFunc::get_output_port_count() const { + return 1; +} + +VisualShaderNodeUVFunc::PortType VisualShaderNodeUVFunc::get_output_port_type(int p_port) const { + return PORT_TYPE_VECTOR; +} + +String VisualShaderNodeUVFunc::get_output_port_name(int p_port) const { + return "uv"; +} + +bool VisualShaderNodeUVFunc::is_show_prop_names() const { + return true; +} + +String VisualShaderNodeUVFunc::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; + + String uv; + if (p_input_vars[0].is_empty()) { + uv = "vec3(UV.xy, 0.0)"; + } else { + uv = vformat("%s", p_input_vars[0]); + } + String scale = vformat("%s", p_input_vars[1]); + String offset_pivot = vformat("%s", p_input_vars[2]); + + switch (func) { + case FUNC_PANNING: { + code += vformat(" %s = fma(%s, %s, %s);\n", p_output_vars[0], offset_pivot, scale, uv); + } break; + case FUNC_SCALING: { + code += vformat(" %s = fma((%s - %s), %s, %s);\n", p_output_vars[0], uv, offset_pivot, scale, offset_pivot); + } break; + default: + break; + } + return code; +} + +void VisualShaderNodeUVFunc::set_function(VisualShaderNodeUVFunc::Function p_func) { + ERR_FAIL_INDEX(int(p_func), int(FUNC_MAX)); + if (func == p_func) { + return; + } + if (p_func == FUNC_PANNING) { + set_input_port_default_value(2, Vector3()); // offset + } else { // FUNC_SCALING + set_input_port_default_value(2, Vector3(0.5, 0.5, 0.0)); // pivot + } + func = p_func; + emit_changed(); +} + +VisualShaderNodeUVFunc::Function VisualShaderNodeUVFunc::get_function() const { + return func; +} + +Vector<StringName> VisualShaderNodeUVFunc::get_editable_properties() const { + Vector<StringName> props; + props.push_back("function"); + return props; +} + +void VisualShaderNodeUVFunc::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeUVFunc::set_function); + ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeUVFunc::get_function); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Panning,Scaling"), "set_function", "get_function"); + + BIND_ENUM_CONSTANT(FUNC_PANNING); + BIND_ENUM_CONSTANT(FUNC_SCALING); + BIND_ENUM_CONSTANT(FUNC_MAX); +} + +VisualShaderNodeUVFunc::VisualShaderNodeUVFunc() { + set_input_port_default_value(1, Vector3(1.0, 1.0, 0.0)); // scale + set_input_port_default_value(2, Vector3()); // offset } ////////////// Dot Product @@ -2206,7 +2881,7 @@ String VisualShaderNodeDotProduct::get_output_port_name(int p_port) const { } String VisualShaderNodeDotProduct::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 { - return "\t" + p_output_vars[0] + " = dot(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + return " " + p_output_vars[0] + " = dot(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } VisualShaderNodeDotProduct::VisualShaderNodeDotProduct() { @@ -2245,7 +2920,7 @@ String VisualShaderNodeVectorLen::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorLen::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 { - return "\t" + p_output_vars[0] + " = length(" + p_input_vars[0] + ");\n"; + return " " + p_output_vars[0] + " = length(" + p_input_vars[0] + ");\n"; } VisualShaderNodeVectorLen::VisualShaderNodeVectorLen() { @@ -2283,11 +2958,11 @@ String VisualShaderNodeDeterminant::get_output_port_name(int p_port) const { } String VisualShaderNodeDeterminant::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 { - return "\t" + p_output_vars[0] + " = determinant(" + p_input_vars[0] + ");\n"; + return " " + p_output_vars[0] + " = determinant(" + p_input_vars[0] + ");\n"; } VisualShaderNodeDeterminant::VisualShaderNodeDeterminant() { - set_input_port_default_value(0, Transform()); + set_input_port_default_value(0, Transform3D()); } ////////////// Scalar Derivative Function @@ -2321,26 +2996,27 @@ String VisualShaderNodeScalarDerivativeFunc::get_output_port_name(int p_port) co } String VisualShaderNodeScalarDerivativeFunc::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 { - - static const char *funcs[FUNC_Y + 1] = { + static const char *functions[FUNC_MAX] = { "fwidth($)", "dFdx($)", "dFdy($)" }; String code; - code += "\t" + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; + code += " " + p_output_vars[0] + " = " + String(functions[func]).replace("$", p_input_vars[0]) + ";\n"; return code; } void VisualShaderNodeScalarDerivativeFunc::set_function(Function p_func) { - + ERR_FAIL_INDEX(int(p_func), int(FUNC_MAX)); + if (func == p_func) { + return; + } func = p_func; emit_changed(); } VisualShaderNodeScalarDerivativeFunc::Function VisualShaderNodeScalarDerivativeFunc::get_function() const { - return func; } @@ -2351,7 +3027,6 @@ Vector<StringName> VisualShaderNodeScalarDerivativeFunc::get_editable_properties } void VisualShaderNodeScalarDerivativeFunc::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeScalarDerivativeFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeScalarDerivativeFunc::get_function); @@ -2360,10 +3035,10 @@ void VisualShaderNodeScalarDerivativeFunc::_bind_methods() { BIND_ENUM_CONSTANT(FUNC_SUM); BIND_ENUM_CONSTANT(FUNC_X); BIND_ENUM_CONSTANT(FUNC_Y); + BIND_ENUM_CONSTANT(FUNC_MAX); } VisualShaderNodeScalarDerivativeFunc::VisualShaderNodeScalarDerivativeFunc() { - func = FUNC_SUM; set_input_port_default_value(0, 0.0); } @@ -2398,26 +3073,27 @@ String VisualShaderNodeVectorDerivativeFunc::get_output_port_name(int p_port) co } String VisualShaderNodeVectorDerivativeFunc::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 { - - static const char *funcs[FUNC_Y + 1] = { + static const char *functions[FUNC_MAX] = { "fwidth($)", "dFdx($)", "dFdy($)" }; String code; - code += "\t" + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; + code += " " + p_output_vars[0] + " = " + String(functions[func]).replace("$", p_input_vars[0]) + ";\n"; return code; } void VisualShaderNodeVectorDerivativeFunc::set_function(Function p_func) { - + ERR_FAIL_INDEX(int(p_func), int(FUNC_MAX)); + if (func == p_func) { + return; + } func = p_func; emit_changed(); } VisualShaderNodeVectorDerivativeFunc::Function VisualShaderNodeVectorDerivativeFunc::get_function() const { - return func; } @@ -2428,7 +3104,6 @@ Vector<StringName> VisualShaderNodeVectorDerivativeFunc::get_editable_properties } void VisualShaderNodeVectorDerivativeFunc::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeVectorDerivativeFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeVectorDerivativeFunc::get_function); @@ -2437,103 +3112,124 @@ void VisualShaderNodeVectorDerivativeFunc::_bind_methods() { BIND_ENUM_CONSTANT(FUNC_SUM); BIND_ENUM_CONSTANT(FUNC_X); BIND_ENUM_CONSTANT(FUNC_Y); + BIND_ENUM_CONSTANT(FUNC_MAX); } VisualShaderNodeVectorDerivativeFunc::VisualShaderNodeVectorDerivativeFunc() { - func = FUNC_SUM; set_input_port_default_value(0, Vector3()); } -////////////// Scalar Clamp +////////////// Clamp -String VisualShaderNodeScalarClamp::get_caption() const { - return "ScalarClamp"; +String VisualShaderNodeClamp::get_caption() const { + return "Clamp"; } -int VisualShaderNodeScalarClamp::get_input_port_count() const { +int VisualShaderNodeClamp::get_input_port_count() const { return 3; } -VisualShaderNodeScalarClamp::PortType VisualShaderNodeScalarClamp::get_input_port_type(int p_port) const { +VisualShaderNodeClamp::PortType VisualShaderNodeClamp::get_input_port_type(int p_port) const { + switch (op_type) { + case OP_TYPE_INT: + return PORT_TYPE_SCALAR_INT; + case OP_TYPE_VECTOR: + return PORT_TYPE_VECTOR; + default: + break; + } return PORT_TYPE_SCALAR; } -String VisualShaderNodeScalarClamp::get_input_port_name(int p_port) const { - if (p_port == 0) +String VisualShaderNodeClamp::get_input_port_name(int p_port) const { + if (p_port == 0) { return ""; - else if (p_port == 1) + } else if (p_port == 1) { return "min"; - else if (p_port == 2) + } else if (p_port == 2) { return "max"; + } return ""; } -int VisualShaderNodeScalarClamp::get_output_port_count() const { +int VisualShaderNodeClamp::get_output_port_count() const { return 1; } -VisualShaderNodeScalarClamp::PortType VisualShaderNodeScalarClamp::get_output_port_type(int p_port) const { +VisualShaderNodeClamp::PortType VisualShaderNodeClamp::get_output_port_type(int p_port) const { + switch (op_type) { + case OP_TYPE_INT: + return PORT_TYPE_SCALAR_INT; + case OP_TYPE_VECTOR: + return PORT_TYPE_VECTOR; + default: + break; + } return PORT_TYPE_SCALAR; } -String VisualShaderNodeScalarClamp::get_output_port_name(int p_port) const { +String VisualShaderNodeClamp::get_output_port_name(int p_port) const { return ""; } -String VisualShaderNodeScalarClamp::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 { - return "\t" + p_output_vars[0] + " = clamp(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; -} - -VisualShaderNodeScalarClamp::VisualShaderNodeScalarClamp() { - set_input_port_default_value(0, 0.0); - set_input_port_default_value(1, 0.0); - set_input_port_default_value(2, 1.0); +String VisualShaderNodeClamp::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 { + return " " + p_output_vars[0] + " = clamp(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } -////////////// Vector Clamp - -String VisualShaderNodeVectorClamp::get_caption() const { - return "VectorClamp"; -} - -int VisualShaderNodeVectorClamp::get_input_port_count() const { - return 3; -} - -VisualShaderNodeVectorClamp::PortType VisualShaderNodeVectorClamp::get_input_port_type(int p_port) const { - return PORT_TYPE_VECTOR; +void VisualShaderNodeClamp::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX((int)p_op_type, int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; + } + switch (p_op_type) { + case OP_TYPE_FLOAT: + set_input_port_default_value(0, 0.0); + set_input_port_default_value(1, 0.0); + set_input_port_default_value(2, 0.0); + break; + case OP_TYPE_INT: + set_input_port_default_value(0, 0); + set_input_port_default_value(1, 0); + set_input_port_default_value(2, 0); + break; + case OP_TYPE_VECTOR: + set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); + set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); + set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); + break; + default: + break; + } + op_type = p_op_type; + emit_changed(); } -String VisualShaderNodeVectorClamp::get_input_port_name(int p_port) const { - if (p_port == 0) - return ""; - else if (p_port == 1) - return "min"; - else if (p_port == 2) - return "max"; - return ""; +VisualShaderNodeClamp::OpType VisualShaderNodeClamp::get_op_type() const { + return op_type; } -int VisualShaderNodeVectorClamp::get_output_port_count() const { - return 1; +Vector<StringName> VisualShaderNodeClamp::get_editable_properties() const { + Vector<StringName> props; + props.push_back("op_type"); + return props; } -VisualShaderNodeVectorClamp::PortType VisualShaderNodeVectorClamp::get_output_port_type(int p_port) const { - return PORT_TYPE_VECTOR; -} +void VisualShaderNodeClamp::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeClamp::set_op_type); + ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeClamp::get_op_type); -String VisualShaderNodeVectorClamp::get_output_port_name(int p_port) const { - return ""; -} + ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Float,Int,Vector"), "set_op_type", "get_op_type"); -String VisualShaderNodeVectorClamp::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 { - return "\t" + p_output_vars[0] + " = clamp(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; + BIND_ENUM_CONSTANT(OP_TYPE_FLOAT); + BIND_ENUM_CONSTANT(OP_TYPE_INT); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR); + BIND_ENUM_CONSTANT(OP_TYPE_MAX); } -VisualShaderNodeVectorClamp::VisualShaderNodeVectorClamp() { - set_input_port_default_value(0, Vector3(0, 0, 0)); - set_input_port_default_value(1, Vector3(0, 0, 0)); - set_input_port_default_value(2, Vector3(1, 1, 1)); +VisualShaderNodeClamp::VisualShaderNodeClamp() { + set_input_port_default_value(0, 0.0); + set_input_port_default_value(1, 0.0); + set_input_port_default_value(2, 1.0); } ////////////// FaceForward @@ -2576,7 +3272,7 @@ String VisualShaderNodeFaceForward::get_output_port_name(int p_port) const { } String VisualShaderNodeFaceForward::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 { - return "\t" + p_output_vars[0] + " = faceforward(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; + return " " + p_output_vars[0] + " = faceforward(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } VisualShaderNodeFaceForward::VisualShaderNodeFaceForward() { @@ -2623,7 +3319,7 @@ String VisualShaderNodeOuterProduct::get_output_port_name(int p_port) const { } String VisualShaderNodeOuterProduct::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 { - return "\t" + p_output_vars[0] + " = outerProduct(vec4(" + p_input_vars[0] + ", 0.0), vec4(" + p_input_vars[1] + ", 0.0));\n"; + return " " + p_output_vars[0] + " = outerProduct(vec4(" + p_input_vars[0] + ", 0.0), vec4(" + p_input_vars[1] + ", 0.0));\n"; } VisualShaderNodeOuterProduct::VisualShaderNodeOuterProduct() { @@ -2631,193 +3327,254 @@ VisualShaderNodeOuterProduct::VisualShaderNodeOuterProduct() { set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); } -////////////// Vector-Scalar Step +////////////// Step -String VisualShaderNodeVectorScalarStep::get_caption() const { - return "VectorScalarStep"; +String VisualShaderNodeStep::get_caption() const { + return "Step"; } -int VisualShaderNodeVectorScalarStep::get_input_port_count() const { +int VisualShaderNodeStep::get_input_port_count() const { return 2; } -VisualShaderNodeVectorScalarStep::PortType VisualShaderNodeVectorScalarStep::get_input_port_type(int p_port) const { - if (p_port == 0) { - return PORT_TYPE_SCALAR; +VisualShaderNodeStep::PortType VisualShaderNodeStep::get_input_port_type(int p_port) const { + switch (op_type) { + case OP_TYPE_VECTOR: + return PORT_TYPE_VECTOR; + case OP_TYPE_VECTOR_SCALAR: + if (p_port == 1) { + return PORT_TYPE_VECTOR; + } + break; + default: + break; } - return PORT_TYPE_VECTOR; + return PORT_TYPE_SCALAR; } -String VisualShaderNodeVectorScalarStep::get_input_port_name(int p_port) const { - if (p_port == 0) +String VisualShaderNodeStep::get_input_port_name(int p_port) const { + if (p_port == 0) { return "edge"; - else if (p_port == 1) + } else if (p_port == 1) { return "x"; + } return ""; } -int VisualShaderNodeVectorScalarStep::get_output_port_count() const { +int VisualShaderNodeStep::get_output_port_count() const { return 1; } -VisualShaderNodeVectorScalarStep::PortType VisualShaderNodeVectorScalarStep::get_output_port_type(int p_port) const { - return PORT_TYPE_VECTOR; +VisualShaderNodeStep::PortType VisualShaderNodeStep::get_output_port_type(int p_port) const { + switch (op_type) { + case OP_TYPE_VECTOR: + return PORT_TYPE_VECTOR; + case OP_TYPE_VECTOR_SCALAR: + return PORT_TYPE_VECTOR; + default: + break; + } + return PORT_TYPE_SCALAR; } -String VisualShaderNodeVectorScalarStep::get_output_port_name(int p_port) const { +String VisualShaderNodeStep::get_output_port_name(int p_port) const { return ""; } -String VisualShaderNodeVectorScalarStep::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 { - return "\t" + p_output_vars[0] + " = step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; -} - -VisualShaderNodeVectorScalarStep::VisualShaderNodeVectorScalarStep() { - set_input_port_default_value(0, 0.0); - set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); -} - -////////////// Scalar SmoothStep - -String VisualShaderNodeScalarSmoothStep::get_caption() const { - return "ScalarSmoothStep"; -} - -int VisualShaderNodeScalarSmoothStep::get_input_port_count() const { - return 3; +void VisualShaderNodeStep::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; + } + switch (p_op_type) { + case OP_TYPE_SCALAR: + if (op_type == OP_TYPE_VECTOR) { + set_input_port_default_value(0, 0.0); // edge + } + if (op_type == OP_TYPE_VECTOR || op_type == OP_TYPE_VECTOR_SCALAR) { + set_input_port_default_value(1, 0.0); // x + } + break; + case OP_TYPE_VECTOR: + if (op_type == OP_TYPE_SCALAR || op_type == OP_TYPE_VECTOR_SCALAR) { + set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); // edge + } + if (op_type == OP_TYPE_SCALAR) { + set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); // x + } + break; + case OP_TYPE_VECTOR_SCALAR: + if (op_type == OP_TYPE_VECTOR) { + set_input_port_default_value(0, 0.0); // edge + } + if (op_type == OP_TYPE_SCALAR) { + set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); // x + } + break; + default: + break; + } + op_type = p_op_type; + emit_changed(); } -VisualShaderNodeScalarSmoothStep::PortType VisualShaderNodeScalarSmoothStep::get_input_port_type(int p_port) const { - return PORT_TYPE_SCALAR; +VisualShaderNodeStep::OpType VisualShaderNodeStep::get_op_type() const { + return op_type; } -String VisualShaderNodeScalarSmoothStep::get_input_port_name(int p_port) const { - if (p_port == 0) - return "edge0"; - else if (p_port == 1) - return "edge1"; - else if (p_port == 2) - return "x"; - return ""; +String VisualShaderNodeStep::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 { + return " " + p_output_vars[0] + " = step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } -int VisualShaderNodeScalarSmoothStep::get_output_port_count() const { - return 1; +Vector<StringName> VisualShaderNodeStep::get_editable_properties() const { + Vector<StringName> props; + props.push_back("op_type"); + return props; } -VisualShaderNodeScalarSmoothStep::PortType VisualShaderNodeScalarSmoothStep::get_output_port_type(int p_port) const { - return PORT_TYPE_SCALAR; -} +void VisualShaderNodeStep::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeStep::set_op_type); + ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeStep::get_op_type); -String VisualShaderNodeScalarSmoothStep::get_output_port_name(int p_port) const { - return ""; -} + ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector,VectorScalar"), "set_op_type", "get_op_type"); -String VisualShaderNodeScalarSmoothStep::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 { - return "\t" + p_output_vars[0] + " = smoothstep(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; + BIND_ENUM_CONSTANT(OP_TYPE_SCALAR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_SCALAR); + BIND_ENUM_CONSTANT(OP_TYPE_MAX); } -VisualShaderNodeScalarSmoothStep::VisualShaderNodeScalarSmoothStep() { +VisualShaderNodeStep::VisualShaderNodeStep() { set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); - set_input_port_default_value(2, 0.0); } -////////////// Vector SmoothStep +////////////// SmoothStep -String VisualShaderNodeVectorSmoothStep::get_caption() const { - return "VectorSmoothStep"; +String VisualShaderNodeSmoothStep::get_caption() const { + return "SmoothStep"; } -int VisualShaderNodeVectorSmoothStep::get_input_port_count() const { +int VisualShaderNodeSmoothStep::get_input_port_count() const { return 3; } -VisualShaderNodeVectorSmoothStep::PortType VisualShaderNodeVectorSmoothStep::get_input_port_type(int p_port) const { - return PORT_TYPE_VECTOR; +VisualShaderNodeSmoothStep::PortType VisualShaderNodeSmoothStep::get_input_port_type(int p_port) const { + switch (op_type) { + case OP_TYPE_VECTOR: + return PORT_TYPE_VECTOR; + case OP_TYPE_VECTOR_SCALAR: + if (p_port == 2) { + return PORT_TYPE_VECTOR; // x + } + break; + default: + break; + } + return PORT_TYPE_SCALAR; } -String VisualShaderNodeVectorSmoothStep::get_input_port_name(int p_port) const { - if (p_port == 0) +String VisualShaderNodeSmoothStep::get_input_port_name(int p_port) const { + if (p_port == 0) { return "edge0"; - else if (p_port == 1) + } else if (p_port == 1) { return "edge1"; - else if (p_port == 2) + } else if (p_port == 2) { return "x"; + } return ""; } -int VisualShaderNodeVectorSmoothStep::get_output_port_count() const { +int VisualShaderNodeSmoothStep::get_output_port_count() const { return 1; } -VisualShaderNodeVectorSmoothStep::PortType VisualShaderNodeVectorSmoothStep::get_output_port_type(int p_port) const { - return PORT_TYPE_VECTOR; +VisualShaderNodeSmoothStep::PortType VisualShaderNodeSmoothStep::get_output_port_type(int p_port) const { + switch (op_type) { + case OP_TYPE_VECTOR: + return PORT_TYPE_VECTOR; + case OP_TYPE_VECTOR_SCALAR: + return PORT_TYPE_VECTOR; + default: + break; + } + return PORT_TYPE_SCALAR; } -String VisualShaderNodeVectorSmoothStep::get_output_port_name(int p_port) const { +String VisualShaderNodeSmoothStep::get_output_port_name(int p_port) const { return ""; } -String VisualShaderNodeVectorSmoothStep::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 { - return "\t" + p_output_vars[0] + " = smoothstep(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; -} - -VisualShaderNodeVectorSmoothStep::VisualShaderNodeVectorSmoothStep() { - set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); - set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); - set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); -} - -////////////// Vector-Scalar SmoothStep - -String VisualShaderNodeVectorScalarSmoothStep::get_caption() const { - return "VectorScalarSmoothStep"; -} - -int VisualShaderNodeVectorScalarSmoothStep::get_input_port_count() const { - return 3; -} - -VisualShaderNodeVectorScalarSmoothStep::PortType VisualShaderNodeVectorScalarSmoothStep::get_input_port_type(int p_port) const { - if (p_port == 0) { - return PORT_TYPE_SCALAR; - } else if (p_port == 1) { - return PORT_TYPE_SCALAR; +void VisualShaderNodeSmoothStep::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; } - return PORT_TYPE_VECTOR; + switch (p_op_type) { + case OP_TYPE_SCALAR: + if (op_type == OP_TYPE_VECTOR) { + set_input_port_default_value(0, 0.0); // edge0 + set_input_port_default_value(1, 0.0); // edge1 + } + if (op_type == OP_TYPE_VECTOR || op_type == OP_TYPE_VECTOR_SCALAR) { + set_input_port_default_value(2, 0.0); // x + } + break; + case OP_TYPE_VECTOR: + if (op_type == OP_TYPE_SCALAR || op_type == OP_TYPE_VECTOR_SCALAR) { + set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); // edge0 + set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); // edge1 + } + if (op_type == OP_TYPE_SCALAR) { + set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); // x + } + break; + case OP_TYPE_VECTOR_SCALAR: + if (op_type == OP_TYPE_VECTOR) { + set_input_port_default_value(0, 0.0); // edge0 + set_input_port_default_value(1, 0.0); // edge1 + } + if (op_type == OP_TYPE_SCALAR) { + set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); // x + } + break; + default: + break; + } + op_type = p_op_type; + emit_changed(); } -String VisualShaderNodeVectorScalarSmoothStep::get_input_port_name(int p_port) const { - if (p_port == 0) - return "edge0"; - else if (p_port == 1) - return "edge1"; - else if (p_port == 2) - return "x"; - return ""; +VisualShaderNodeSmoothStep::OpType VisualShaderNodeSmoothStep::get_op_type() const { + return op_type; } -int VisualShaderNodeVectorScalarSmoothStep::get_output_port_count() const { - return 1; +String VisualShaderNodeSmoothStep::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 { + return " " + p_output_vars[0] + " = smoothstep(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } -VisualShaderNodeVectorScalarSmoothStep::PortType VisualShaderNodeVectorScalarSmoothStep::get_output_port_type(int p_port) const { - return PORT_TYPE_VECTOR; +Vector<StringName> VisualShaderNodeSmoothStep::get_editable_properties() const { + Vector<StringName> props; + props.push_back("op_type"); + return props; } -String VisualShaderNodeVectorScalarSmoothStep::get_output_port_name(int p_port) const { - return ""; -} +void VisualShaderNodeSmoothStep::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeSmoothStep::set_op_type); + ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeSmoothStep::get_op_type); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector,VectorScalar"), "set_op_type", "get_op_type"); -String VisualShaderNodeVectorScalarSmoothStep::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 { - return "\t" + p_output_vars[0] + " = smoothstep(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; + BIND_ENUM_CONSTANT(OP_TYPE_SCALAR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_SCALAR); + BIND_ENUM_CONSTANT(OP_TYPE_MAX); } -VisualShaderNodeVectorScalarSmoothStep::VisualShaderNodeVectorScalarSmoothStep() { +VisualShaderNodeSmoothStep::VisualShaderNodeSmoothStep() { set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); - set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); + set_input_port_default_value(2, 0.0); } ////////////// Distance @@ -2856,7 +3613,7 @@ String VisualShaderNodeVectorDistance::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorDistance::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 { - return "\t" + p_output_vars[0] + " = distance(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + return " " + p_output_vars[0] + " = distance(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } VisualShaderNodeVectorDistance::VisualShaderNodeVectorDistance() { @@ -2875,7 +3632,6 @@ int VisualShaderNodeVectorRefract::get_input_port_count() const { } VisualShaderNodeVectorRefract::PortType VisualShaderNodeVectorRefract::get_input_port_type(int p_port) const { - if (p_port == 2) { return PORT_TYPE_SCALAR; } @@ -2907,7 +3663,7 @@ String VisualShaderNodeVectorRefract::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorRefract::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 { - return "\t" + p_output_vars[0] + " = refract(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; + return " " + p_output_vars[0] + " = refract(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } VisualShaderNodeVectorRefract::VisualShaderNodeVectorRefract() { @@ -2916,21 +3672,32 @@ VisualShaderNodeVectorRefract::VisualShaderNodeVectorRefract() { set_input_port_default_value(2, 0.0); } -////////////// Scalar Mix +////////////// Mix -String VisualShaderNodeScalarInterp::get_caption() const { - return "ScalarMix"; +String VisualShaderNodeMix::get_caption() const { + return "Mix"; } -int VisualShaderNodeScalarInterp::get_input_port_count() const { +int VisualShaderNodeMix::get_input_port_count() const { return 3; } -VisualShaderNodeScalarInterp::PortType VisualShaderNodeScalarInterp::get_input_port_type(int p_port) const { +VisualShaderNodeMix::PortType VisualShaderNodeMix::get_input_port_type(int p_port) const { + switch (op_type) { + case OP_TYPE_VECTOR: + return PORT_TYPE_VECTOR; + case OP_TYPE_VECTOR_SCALAR: + if (p_port == 2) { + break; + } + return PORT_TYPE_VECTOR; + default: + break; + } return PORT_TYPE_SCALAR; } -String VisualShaderNodeScalarInterp::get_input_port_name(int p_port) const { +String VisualShaderNodeMix::get_input_port_name(int p_port) const { if (p_port == 0) { return "a"; } else if (p_port == 1) { @@ -2940,120 +3707,90 @@ String VisualShaderNodeScalarInterp::get_input_port_name(int p_port) const { } } -int VisualShaderNodeScalarInterp::get_output_port_count() const { +int VisualShaderNodeMix::get_output_port_count() const { return 1; } -VisualShaderNodeScalarInterp::PortType VisualShaderNodeScalarInterp::get_output_port_type(int p_port) const { +VisualShaderNodeMix::PortType VisualShaderNodeMix::get_output_port_type(int p_port) const { + switch (op_type) { + case OP_TYPE_VECTOR: + return PORT_TYPE_VECTOR; + case OP_TYPE_VECTOR_SCALAR: + return PORT_TYPE_VECTOR; + default: + break; + } return PORT_TYPE_SCALAR; } -String VisualShaderNodeScalarInterp::get_output_port_name(int p_port) const { +String VisualShaderNodeMix::get_output_port_name(int p_port) const { return "mix"; } -String VisualShaderNodeScalarInterp::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 { - return "\t" + p_output_vars[0] + " = mix(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; -} - -VisualShaderNodeScalarInterp::VisualShaderNodeScalarInterp() { - set_input_port_default_value(0, 0.0); - set_input_port_default_value(1, 1.0); - set_input_port_default_value(2, 0.5); -} - -////////////// Vector Mix - -String VisualShaderNodeVectorInterp::get_caption() const { - return "VectorMix"; -} - -int VisualShaderNodeVectorInterp::get_input_port_count() const { - return 3; -} - -VisualShaderNodeVectorInterp::PortType VisualShaderNodeVectorInterp::get_input_port_type(int p_port) const { - return PORT_TYPE_VECTOR; -} - -String VisualShaderNodeVectorInterp::get_input_port_name(int p_port) const { - if (p_port == 0) { - return "a"; - } else if (p_port == 1) { - return "b"; - } else { - return "weight"; +void VisualShaderNodeMix::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; } + switch (p_op_type) { + case OP_TYPE_SCALAR: + set_input_port_default_value(0, 0.0); // a + set_input_port_default_value(1, 1.0); // b + if (op_type == OP_TYPE_VECTOR) { + set_input_port_default_value(2, 0.5); // weight + } + break; + case OP_TYPE_VECTOR: + set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); // a + set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); // b + if (op_type == OP_TYPE_SCALAR || op_type == OP_TYPE_VECTOR_SCALAR) { + set_input_port_default_value(2, Vector3(0.5, 0.5, 0.5)); // weight + } + break; + case OP_TYPE_VECTOR_SCALAR: + set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); // a + set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); // b + if (op_type == OP_TYPE_VECTOR) { + set_input_port_default_value(2, 0.5); // weight + } + break; + default: + break; + } + op_type = p_op_type; + emit_changed(); } -int VisualShaderNodeVectorInterp::get_output_port_count() const { - return 1; -} - -VisualShaderNodeVectorInterp::PortType VisualShaderNodeVectorInterp::get_output_port_type(int p_port) const { - return PORT_TYPE_VECTOR; -} - -String VisualShaderNodeVectorInterp::get_output_port_name(int p_port) const { - return "mix"; -} - -String VisualShaderNodeVectorInterp::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 { - return "\t" + p_output_vars[0] + " = mix(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; -} - -VisualShaderNodeVectorInterp::VisualShaderNodeVectorInterp() { - set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); - set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); - set_input_port_default_value(2, Vector3(0.5, 0.5, 0.5)); -} - -////////////// Vector Mix (by scalar) - -String VisualShaderNodeVectorScalarMix::get_caption() const { - return "VectorScalarMix"; -} - -int VisualShaderNodeVectorScalarMix::get_input_port_count() const { - return 3; -} - -VisualShaderNodeVectorScalarMix::PortType VisualShaderNodeVectorScalarMix::get_input_port_type(int p_port) const { - if (p_port == 2) - return PORT_TYPE_SCALAR; - return PORT_TYPE_VECTOR; +VisualShaderNodeMix::OpType VisualShaderNodeMix::get_op_type() const { + return op_type; } -String VisualShaderNodeVectorScalarMix::get_input_port_name(int p_port) const { - if (p_port == 0) { - return "a"; - } else if (p_port == 1) { - return "b"; - } else { - return "weight"; - } +String VisualShaderNodeMix::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 { + return " " + p_output_vars[0] + " = mix(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } -int VisualShaderNodeVectorScalarMix::get_output_port_count() const { - return 1; +Vector<StringName> VisualShaderNodeMix::get_editable_properties() const { + Vector<StringName> props; + props.push_back("op_type"); + return props; } -VisualShaderNodeVectorScalarMix::PortType VisualShaderNodeVectorScalarMix::get_output_port_type(int p_port) const { - return PORT_TYPE_VECTOR; -} +void VisualShaderNodeMix::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeMix::set_op_type); + ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeMix::get_op_type); -String VisualShaderNodeVectorScalarMix::get_output_port_name(int p_port) const { - return "mix"; -} + ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector,VectorScalar"), "set_op_type", "get_op_type"); -String VisualShaderNodeVectorScalarMix::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 { - return "\t" + p_output_vars[0] + " = mix(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; + BIND_ENUM_CONSTANT(OP_TYPE_SCALAR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_SCALAR); + BIND_ENUM_CONSTANT(OP_TYPE_MAX); } -VisualShaderNodeVectorScalarMix::VisualShaderNodeVectorScalarMix() { - set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); - set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); - set_input_port_default_value(2, 0.5); +VisualShaderNodeMix::VisualShaderNodeMix() { + set_input_port_default_value(0, 0.0); // a + set_input_port_default_value(1, 1.0); // b + set_input_port_default_value(2, 0.5); // weight } ////////////// Vector Compose @@ -3093,11 +3830,10 @@ String VisualShaderNodeVectorCompose::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorCompose::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 { - return "\t" + p_output_vars[0] + " = vec3(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; + return " " + p_output_vars[0] + " = vec3(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; } VisualShaderNodeVectorCompose::VisualShaderNodeVectorCompose() { - set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); set_input_port_default_value(2, 0.0); @@ -3142,11 +3878,10 @@ String VisualShaderNodeTransformCompose::get_output_port_name(int p_port) const } String VisualShaderNodeTransformCompose::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 { - return "\t" + p_output_vars[0] + " = mat4(vec4(" + p_input_vars[0] + ", 0.0), vec4(" + p_input_vars[1] + ", 0.0), vec4(" + p_input_vars[2] + ", 0.0), vec4(" + p_input_vars[3] + ", 1.0));\n"; + return " " + p_output_vars[0] + " = mat4(vec4(" + p_input_vars[0] + ", 0.0), vec4(" + p_input_vars[1] + ", 0.0), vec4(" + p_input_vars[2] + ", 0.0), vec4(" + p_input_vars[3] + ", 1.0));\n"; } VisualShaderNodeTransformCompose::VisualShaderNodeTransformCompose() { - set_input_port_default_value(0, Vector3()); set_input_port_default_value(1, Vector3()); set_input_port_default_value(2, Vector3()); @@ -3190,9 +3925,9 @@ String VisualShaderNodeVectorDecompose::get_output_port_name(int p_port) const { String VisualShaderNodeVectorDecompose::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] + " = " + p_input_vars[0] + ".x;\n"; - code += "\t" + p_output_vars[1] + " = " + p_input_vars[0] + ".y;\n"; - code += "\t" + p_output_vars[2] + " = " + p_input_vars[0] + ".z;\n"; + code += " " + p_output_vars[0] + " = " + p_input_vars[0] + ".x;\n"; + code += " " + p_output_vars[1] + " = " + p_input_vars[0] + ".y;\n"; + code += " " + p_output_vars[2] + " = " + p_input_vars[0] + ".z;\n"; return code; } @@ -3240,15 +3975,15 @@ String VisualShaderNodeTransformDecompose::get_output_port_name(int p_port) cons String VisualShaderNodeTransformDecompose::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] + " = " + p_input_vars[0] + "[0].xyz;\n"; - code += "\t" + p_output_vars[1] + " = " + p_input_vars[0] + "[1].xyz;\n"; - code += "\t" + p_output_vars[2] + " = " + p_input_vars[0] + "[2].xyz;\n"; - code += "\t" + p_output_vars[3] + " = " + p_input_vars[0] + "[3].xyz;\n"; + code += " " + p_output_vars[0] + " = " + p_input_vars[0] + "[0].xyz;\n"; + code += " " + p_output_vars[1] + " = " + p_input_vars[0] + "[1].xyz;\n"; + code += " " + p_output_vars[2] + " = " + p_input_vars[0] + "[2].xyz;\n"; + code += " " + p_output_vars[3] + " = " + p_input_vars[0] + "[3].xyz;\n"; return code; } VisualShaderNodeTransformDecompose::VisualShaderNodeTransformDecompose() { - set_input_port_default_value(0, Transform()); + set_input_port_default_value(0, Transform3D()); } ////////////// Float Uniform @@ -3282,19 +4017,38 @@ String VisualShaderNodeFloatUniform::get_output_port_name(int p_port) const { } String VisualShaderNodeFloatUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = ""; if (hint == HINT_RANGE) { - return "uniform float " + get_uniform_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ");\n"; + code += _get_qual_str() + "uniform float " + get_uniform_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ")"; } else if (hint == HINT_RANGE_STEP) { - return "uniform float " + get_uniform_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ", " + rtos(hint_range_step) + ");\n"; + code += _get_qual_str() + "uniform float " + get_uniform_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ", " + rtos(hint_range_step) + ")"; + } else { + code += _get_qual_str() + "uniform float " + get_uniform_name(); + } + if (default_value_enabled) { + code += " = " + rtos(default_value); } - return "uniform float " + get_uniform_name() + ";\n"; + code += ";\n"; + return code; } String VisualShaderNodeFloatUniform::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 { - return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; + return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; +} + +bool VisualShaderNodeFloatUniform::is_show_prop_names() const { + return true; +} + +bool VisualShaderNodeFloatUniform::is_use_prop_slots() const { + return true; } void VisualShaderNodeFloatUniform::set_hint(Hint p_hint) { + ERR_FAIL_INDEX(int(p_hint), int(HINT_MAX)); + if (hint == p_hint) { + return; + } hint = p_hint; emit_changed(); } @@ -3304,6 +4058,9 @@ VisualShaderNodeFloatUniform::Hint VisualShaderNodeFloatUniform::get_hint() cons } void VisualShaderNodeFloatUniform::set_min(float p_value) { + if (Math::is_equal_approx(hint_range_min, p_value)) { + return; + } hint_range_min = p_value; emit_changed(); } @@ -3313,6 +4070,9 @@ float VisualShaderNodeFloatUniform::get_min() const { } void VisualShaderNodeFloatUniform::set_max(float p_value) { + if (Math::is_equal_approx(hint_range_max, p_value)) { + return; + } hint_range_max = p_value; emit_changed(); } @@ -3322,6 +4082,9 @@ float VisualShaderNodeFloatUniform::get_max() const { } void VisualShaderNodeFloatUniform::set_step(float p_value) { + if (Math::is_equal_approx(hint_range_step, p_value)) { + return; + } hint_range_step = p_value; emit_changed(); } @@ -3330,6 +4093,30 @@ float VisualShaderNodeFloatUniform::get_step() const { return hint_range_step; } +void VisualShaderNodeFloatUniform::set_default_value_enabled(bool p_enabled) { + if (default_value_enabled == p_enabled) { + return; + } + default_value_enabled = p_enabled; + emit_changed(); +} + +bool VisualShaderNodeFloatUniform::is_default_value_enabled() const { + return default_value_enabled; +} + +void VisualShaderNodeFloatUniform::set_default_value(float p_value) { + if (Math::is_equal_approx(default_value, p_value)) { + return; + } + default_value = p_value; + emit_changed(); +} + +float VisualShaderNodeFloatUniform::get_default_value() const { + return default_value; +} + void VisualShaderNodeFloatUniform::_bind_methods() { ClassDB::bind_method(D_METHOD("set_hint", "hint"), &VisualShaderNodeFloatUniform::set_hint); ClassDB::bind_method(D_METHOD("get_hint"), &VisualShaderNodeFloatUniform::get_hint); @@ -3343,18 +4130,35 @@ void VisualShaderNodeFloatUniform::_bind_methods() { ClassDB::bind_method(D_METHOD("set_step", "value"), &VisualShaderNodeFloatUniform::set_step); ClassDB::bind_method(D_METHOD("get_step"), &VisualShaderNodeFloatUniform::get_step); + ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeFloatUniform::set_default_value_enabled); + ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeFloatUniform::is_default_value_enabled); + + ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeFloatUniform::set_default_value); + ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeFloatUniform::get_default_value); + ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range+Step"), "set_hint", "get_hint"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min"), "set_min", "get_min"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max"), "set_max", "get_max"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step"), "set_step", "get_step"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "default_value"), "set_default_value", "get_default_value"); BIND_ENUM_CONSTANT(HINT_NONE); BIND_ENUM_CONSTANT(HINT_RANGE); BIND_ENUM_CONSTANT(HINT_RANGE_STEP); + BIND_ENUM_CONSTANT(HINT_MAX); +} + +bool VisualShaderNodeFloatUniform::is_qualifier_supported(Qualifier p_qual) const { + return true; // all qualifiers are supported +} + +bool VisualShaderNodeFloatUniform::is_convertible_to_constant() const { + return true; // conversion is allowed } Vector<StringName> VisualShaderNodeFloatUniform::get_editable_properties() const { - Vector<StringName> props; + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); props.push_back("hint"); if (hint == HINT_RANGE || hint == HINT_RANGE_STEP) { props.push_back("min"); @@ -3363,14 +4167,14 @@ Vector<StringName> VisualShaderNodeFloatUniform::get_editable_properties() const if (hint == HINT_RANGE_STEP) { props.push_back("step"); } + props.push_back("default_value_enabled"); + if (default_value_enabled) { + props.push_back("default_value"); + } return props; } VisualShaderNodeFloatUniform::VisualShaderNodeFloatUniform() { - hint = HINT_NONE; - hint_range_min = 0.0; - hint_range_max = 1.0; - hint_range_step = 0.1; } ////////////// Integer Uniform @@ -3404,19 +4208,38 @@ String VisualShaderNodeIntUniform::get_output_port_name(int p_port) const { } String VisualShaderNodeIntUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = ""; if (hint == HINT_RANGE) { - return "uniform int " + get_uniform_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ");\n"; + code += _get_qual_str() + "uniform int " + get_uniform_name() + " : hint_range(" + itos(hint_range_min) + ", " + itos(hint_range_max) + ")"; } else if (hint == HINT_RANGE_STEP) { - return "uniform int " + get_uniform_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ", " + rtos(hint_range_step) + ");\n"; + code += _get_qual_str() + "uniform int " + get_uniform_name() + " : hint_range(" + itos(hint_range_min) + ", " + itos(hint_range_max) + ", " + itos(hint_range_step) + ")"; + } else { + code += _get_qual_str() + "uniform int " + get_uniform_name(); } - return "uniform int " + get_uniform_name() + ";\n"; + if (default_value_enabled) { + code += " = " + itos(default_value); + } + code += ";\n"; + return code; } String VisualShaderNodeIntUniform::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 { - return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; + return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; +} + +bool VisualShaderNodeIntUniform::is_show_prop_names() const { + return true; +} + +bool VisualShaderNodeIntUniform::is_use_prop_slots() const { + return true; } void VisualShaderNodeIntUniform::set_hint(Hint p_hint) { + ERR_FAIL_INDEX(int(p_hint), int(HINT_MAX)); + if (hint == p_hint) { + return; + } hint = p_hint; emit_changed(); } @@ -3426,6 +4249,9 @@ VisualShaderNodeIntUniform::Hint VisualShaderNodeIntUniform::get_hint() const { } void VisualShaderNodeIntUniform::set_min(int p_value) { + if (hint_range_min == p_value) { + return; + } hint_range_min = p_value; emit_changed(); } @@ -3435,6 +4261,9 @@ int VisualShaderNodeIntUniform::get_min() const { } void VisualShaderNodeIntUniform::set_max(int p_value) { + if (hint_range_max == p_value) { + return; + } hint_range_max = p_value; emit_changed(); } @@ -3444,6 +4273,9 @@ int VisualShaderNodeIntUniform::get_max() const { } void VisualShaderNodeIntUniform::set_step(int p_value) { + if (hint_range_step == p_value) { + return; + } hint_range_step = p_value; emit_changed(); } @@ -3452,6 +4284,30 @@ int VisualShaderNodeIntUniform::get_step() const { return hint_range_step; } +void VisualShaderNodeIntUniform::set_default_value_enabled(bool p_default_value_enabled) { + if (default_value_enabled == p_default_value_enabled) { + return; + } + default_value_enabled = p_default_value_enabled; + emit_changed(); +} + +bool VisualShaderNodeIntUniform::is_default_value_enabled() const { + return default_value_enabled; +} + +void VisualShaderNodeIntUniform::set_default_value(int p_default_value) { + if (default_value == p_default_value) { + return; + } + default_value = p_default_value; + emit_changed(); +} + +int VisualShaderNodeIntUniform::get_default_value() const { + return default_value; +} + void VisualShaderNodeIntUniform::_bind_methods() { ClassDB::bind_method(D_METHOD("set_hint", "hint"), &VisualShaderNodeIntUniform::set_hint); ClassDB::bind_method(D_METHOD("get_hint"), &VisualShaderNodeIntUniform::get_hint); @@ -3465,18 +4321,35 @@ void VisualShaderNodeIntUniform::_bind_methods() { ClassDB::bind_method(D_METHOD("set_step", "value"), &VisualShaderNodeIntUniform::set_step); ClassDB::bind_method(D_METHOD("get_step"), &VisualShaderNodeIntUniform::get_step); - ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range+Step"), "set_hint", "get_hint"); + ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeIntUniform::set_default_value_enabled); + ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeIntUniform::is_default_value_enabled); + + ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeIntUniform::set_default_value); + ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeIntUniform::get_default_value); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range + Step"), "set_hint", "get_hint"); ADD_PROPERTY(PropertyInfo(Variant::INT, "min"), "set_min", "get_min"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max"), "set_max", "get_max"); ADD_PROPERTY(PropertyInfo(Variant::INT, "step"), "set_step", "get_step"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "default_value"), "set_default_value", "get_default_value"); BIND_ENUM_CONSTANT(HINT_NONE); BIND_ENUM_CONSTANT(HINT_RANGE); BIND_ENUM_CONSTANT(HINT_RANGE_STEP); + BIND_ENUM_CONSTANT(HINT_MAX); +} + +bool VisualShaderNodeIntUniform::is_qualifier_supported(Qualifier p_qual) const { + return true; // all qualifiers are supported +} + +bool VisualShaderNodeIntUniform::is_convertible_to_constant() const { + return true; // conversion is allowed } Vector<StringName> VisualShaderNodeIntUniform::get_editable_properties() const { - Vector<StringName> props; + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); props.push_back("hint"); if (hint == HINT_RANGE || hint == HINT_RANGE_STEP) { props.push_back("min"); @@ -3485,14 +4358,14 @@ Vector<StringName> VisualShaderNodeIntUniform::get_editable_properties() const { if (hint == HINT_RANGE_STEP) { props.push_back("step"); } + props.push_back("default_value_enabled"); + if (default_value_enabled) { + props.push_back("default_value"); + } return props; } VisualShaderNodeIntUniform::VisualShaderNodeIntUniform() { - hint = HINT_NONE; - hint_range_min = 0; - hint_range_max = 100; - hint_range_step = 1; } ////////////// Boolean Uniform @@ -3525,12 +4398,81 @@ String VisualShaderNodeBooleanUniform::get_output_port_name(int p_port) const { return ""; //no output port means the editor will be used as port } +void VisualShaderNodeBooleanUniform::set_default_value_enabled(bool p_default_value_enabled) { + if (default_value_enabled == p_default_value_enabled) { + return; + } + default_value_enabled = p_default_value_enabled; + emit_changed(); +} + +bool VisualShaderNodeBooleanUniform::is_default_value_enabled() const { + return default_value_enabled; +} + +void VisualShaderNodeBooleanUniform::set_default_value(bool p_default_value) { + if (default_value == p_default_value) { + return; + } + default_value = p_default_value; + emit_changed(); +} + +bool VisualShaderNodeBooleanUniform::get_default_value() const { + return default_value; +} + String VisualShaderNodeBooleanUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - return "uniform bool " + get_uniform_name() + ";\n"; + String code = _get_qual_str() + "uniform bool " + get_uniform_name(); + if (default_value_enabled) { + if (default_value) { + code += " = true"; + } else { + code += " = false"; + } + } + code += ";\n"; + return code; } String VisualShaderNodeBooleanUniform::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 { - return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; + return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; +} + +bool VisualShaderNodeBooleanUniform::is_show_prop_names() const { + return true; +} + +bool VisualShaderNodeBooleanUniform::is_use_prop_slots() const { + return true; +} + +void VisualShaderNodeBooleanUniform::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeBooleanUniform::set_default_value_enabled); + ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeBooleanUniform::is_default_value_enabled); + + ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeBooleanUniform::set_default_value); + ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeBooleanUniform::get_default_value); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value"), "set_default_value", "get_default_value"); +} + +bool VisualShaderNodeBooleanUniform::is_qualifier_supported(Qualifier p_qual) const { + return true; // all qualifiers are supported +} + +bool VisualShaderNodeBooleanUniform::is_convertible_to_constant() const { + return true; // conversion is allowed +} + +Vector<StringName> VisualShaderNodeBooleanUniform::get_editable_properties() const { + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); + props.push_back("default_value_enabled"); + if (default_value_enabled) { + props.push_back("default_value"); + } + return props; } VisualShaderNodeBooleanUniform::VisualShaderNodeBooleanUniform() { @@ -3566,17 +4508,77 @@ String VisualShaderNodeColorUniform::get_output_port_name(int p_port) const { return p_port == 0 ? "color" : "alpha"; //no output port means the editor will be used as port } -String VisualShaderNodeColorUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { +void VisualShaderNodeColorUniform::set_default_value_enabled(bool p_enabled) { + if (default_value_enabled == p_enabled) { + return; + } + default_value_enabled = p_enabled; + emit_changed(); +} + +bool VisualShaderNodeColorUniform::is_default_value_enabled() const { + return default_value_enabled; +} - return "uniform vec4 " + get_uniform_name() + " : hint_color;\n"; +void VisualShaderNodeColorUniform::set_default_value(const Color &p_value) { + if (default_value.is_equal_approx(p_value)) { + return; + } + default_value = p_value; + emit_changed(); +} + +Color VisualShaderNodeColorUniform::get_default_value() const { + return default_value; +} + +String VisualShaderNodeColorUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = _get_qual_str() + "uniform vec4 " + get_uniform_name() + " : hint_color"; + if (default_value_enabled) { + code += vformat(" = vec4(%.6f, %.6f, %.6f, %.6f)", default_value.r, default_value.g, default_value.b, default_value.a); + } + code += ";\n"; + return code; } String VisualShaderNodeColorUniform::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 = "\t" + p_output_vars[0] + " = " + get_uniform_name() + ".rgb;\n"; - code += "\t" + p_output_vars[1] + " = " + get_uniform_name() + ".a;\n"; + String code = " " + p_output_vars[0] + " = " + get_uniform_name() + ".rgb;\n"; + code += " " + p_output_vars[1] + " = " + get_uniform_name() + ".a;\n"; return code; } +bool VisualShaderNodeColorUniform::is_show_prop_names() const { + return true; +} + +void VisualShaderNodeColorUniform::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeColorUniform::set_default_value_enabled); + ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeColorUniform::is_default_value_enabled); + + ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeColorUniform::set_default_value); + ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeColorUniform::get_default_value); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "default_value"), "set_default_value", "get_default_value"); +} + +bool VisualShaderNodeColorUniform::is_qualifier_supported(Qualifier p_qual) const { + return true; // all qualifiers are supported +} + +bool VisualShaderNodeColorUniform::is_convertible_to_constant() const { + return true; // conversion is allowed +} + +Vector<StringName> VisualShaderNodeColorUniform::get_editable_properties() const { + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); + props.push_back("default_value_enabled"); + if (default_value_enabled) { + props.push_back("default_value"); + } + return props; +} + VisualShaderNodeColorUniform::VisualShaderNodeColorUniform() { } @@ -3610,12 +4612,71 @@ String VisualShaderNodeVec3Uniform::get_output_port_name(int p_port) const { return ""; //no output port means the editor will be used as port } +void VisualShaderNodeVec3Uniform::set_default_value_enabled(bool p_enabled) { + default_value_enabled = p_enabled; + emit_changed(); +} + +bool VisualShaderNodeVec3Uniform::is_default_value_enabled() const { + return default_value_enabled; +} + +void VisualShaderNodeVec3Uniform::set_default_value(const Vector3 &p_value) { + default_value = p_value; + emit_changed(); +} + +Vector3 VisualShaderNodeVec3Uniform::get_default_value() const { + return default_value; +} + String VisualShaderNodeVec3Uniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - return "uniform vec3 " + get_uniform_name() + ";\n"; + String code = _get_qual_str() + "uniform vec3 " + get_uniform_name(); + if (default_value_enabled) { + code += vformat(" = vec3(%.6f, %.6f, %.6f)", default_value.x, default_value.y, default_value.z); + } + code += ";\n"; + return code; } String VisualShaderNodeVec3Uniform::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 { - return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; + return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; +} + +void VisualShaderNodeVec3Uniform::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeVec3Uniform::set_default_value_enabled); + ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeVec3Uniform::is_default_value_enabled); + + ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeVec3Uniform::set_default_value); + ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeVec3Uniform::get_default_value); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "default_value"), "set_default_value", "get_default_value"); +} + +bool VisualShaderNodeVec3Uniform::is_show_prop_names() const { + return true; +} + +bool VisualShaderNodeVec3Uniform::is_use_prop_slots() const { + return true; +} + +bool VisualShaderNodeVec3Uniform::is_qualifier_supported(Qualifier p_qual) const { + return true; // all qualifiers are supported +} + +bool VisualShaderNodeVec3Uniform::is_convertible_to_constant() const { + return true; // conversion is allowed +} + +Vector<StringName> VisualShaderNodeVec3Uniform::get_editable_properties() const { + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); + props.push_back("default_value_enabled"); + if (default_value_enabled) { + props.push_back("default_value"); + } + return props; } VisualShaderNodeVec3Uniform::VisualShaderNodeVec3Uniform() { @@ -3651,12 +4712,78 @@ String VisualShaderNodeTransformUniform::get_output_port_name(int p_port) const return ""; //no output port means the editor will be used as port } +void VisualShaderNodeTransformUniform::set_default_value_enabled(bool p_enabled) { + default_value_enabled = p_enabled; + emit_changed(); +} + +bool VisualShaderNodeTransformUniform::is_default_value_enabled() const { + return default_value_enabled; +} + +void VisualShaderNodeTransformUniform::set_default_value(const Transform3D &p_value) { + default_value = p_value; + emit_changed(); +} + +Transform3D VisualShaderNodeTransformUniform::get_default_value() const { + return default_value; +} + String VisualShaderNodeTransformUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - return "uniform mat4 " + get_uniform_name() + ";\n"; + String code = _get_qual_str() + "uniform mat4 " + get_uniform_name(); + if (default_value_enabled) { + Vector3 row0 = default_value.basis.get_row(0); + Vector3 row1 = default_value.basis.get_row(1); + Vector3 row2 = default_value.basis.get_row(2); + Vector3 origin = default_value.origin; + code += " = mat4(" + vformat("vec4(%.6f, %.6f, %.6f, 0.0)", row0.x, row0.y, row0.z) + vformat(", vec4(%.6f, %.6f, %.6f, 0.0)", row1.x, row1.y, row1.z) + vformat(", vec4(%.6f, %.6f, %.6f, 0.0)", row2.x, row2.y, row2.z) + vformat(", vec4(%.6f, %.6f, %.6f, 1.0)", origin.x, origin.y, origin.z) + ")"; + } + code += ";\n"; + return code; } String VisualShaderNodeTransformUniform::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 { - return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; + return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; +} + +void VisualShaderNodeTransformUniform::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeTransformUniform::set_default_value_enabled); + ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeTransformUniform::is_default_value_enabled); + + ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeTransformUniform::set_default_value); + ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeTransformUniform::get_default_value); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "default_value"), "set_default_value", "get_default_value"); +} + +bool VisualShaderNodeTransformUniform::is_show_prop_names() const { + return true; +} + +bool VisualShaderNodeTransformUniform::is_use_prop_slots() const { + return true; +} + +bool VisualShaderNodeTransformUniform::is_qualifier_supported(Qualifier p_qual) const { + if (p_qual == Qualifier::QUAL_INSTANCE) { + return false; + } + return true; +} + +bool VisualShaderNodeTransformUniform::is_convertible_to_constant() const { + return true; // conversion is allowed +} + +Vector<StringName> VisualShaderNodeTransformUniform::get_editable_properties() const { + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); + props.push_back("default_value_enabled"); + if (default_value_enabled) { + props.push_back("default_value"); + } + return props; } VisualShaderNodeTransformUniform::VisualShaderNodeTransformUniform() { @@ -3685,7 +4812,6 @@ int VisualShaderNodeTextureUniform::get_output_port_count() const { } VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_output_port_type(int p_port) const { - switch (p_port) { case 0: return PORT_TYPE_VECTOR; @@ -3699,7 +4825,6 @@ VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_out } String VisualShaderNodeTextureUniform::get_output_port_name(int p_port) const { - switch (p_port) { case 0: return "rgb"; @@ -3713,54 +4838,76 @@ String VisualShaderNodeTextureUniform::get_output_port_name(int p_port) const { } String VisualShaderNodeTextureUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - String code = "uniform sampler2D " + get_uniform_name(); + String code = _get_qual_str() + "uniform sampler2D " + get_uniform_name(); switch (texture_type) { case TYPE_DATA: - if (color_default == COLOR_DEFAULT_BLACK) + if (color_default == COLOR_DEFAULT_BLACK) { code += " : hint_black;\n"; - else + } else { code += ";\n"; + } break; case TYPE_COLOR: - if (color_default == COLOR_DEFAULT_BLACK) + if (color_default == COLOR_DEFAULT_BLACK) { code += " : hint_black_albedo;\n"; - else + } else { code += " : hint_albedo;\n"; + } + break; + case TYPE_NORMAL_MAP: + code += " : hint_normal;\n"; + break; + case TYPE_ANISO: + code += " : hint_aniso;\n"; + break; + default: + code += ";\n"; break; - case TYPE_NORMALMAP: code += " : hint_normal;\n"; break; - case TYPE_ANISO: code += " : hint_aniso;\n"; break; } return code; } +bool VisualShaderNodeTextureUniform::is_code_generated() const { + return is_output_port_connected(0) || is_output_port_connected(1); // rgb or alpha +} + String VisualShaderNodeTextureUniform::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 default_uv; + if (p_mode != Shader::MODE_PARTICLES && p_mode != Shader::MODE_SKY) { + default_uv = "UV.xy"; + } else { + default_uv = "vec2(0.0)"; + } String id = get_uniform_name(); - String code = "\t{\n"; + String code = " {\n"; if (p_input_vars[0] == String()) { // Use UV by default. if (p_input_vars[1] == String()) { - code += "\t\tvec4 n_tex_read = texture(" + id + ", UV.xy);\n"; + code += " vec4 n_tex_read = texture(" + id + ", " + default_uv + ");\n"; } else { - code += "\t\tvec4 n_tex_read = textureLod(" + id + ", UV.xy, " + p_input_vars[1] + ");\n"; + code += " vec4 n_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n"; } } else if (p_input_vars[1] == String()) { //no lod - code += "\t\tvec4 n_tex_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n"; + code += " vec4 n_tex_read = texture(" + id + ", " + p_input_vars[0] + ".xy);\n"; } else { - code += "\t\tvec4 n_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; + code += " vec4 n_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n"; } - code += "\t\t" + p_output_vars[0] + " = n_tex_read.rgb;\n"; - code += "\t\t" + p_output_vars[1] + " = n_tex_read.a;\n"; - code += "\t}\n"; + code += " " + p_output_vars[0] + " = n_tex_read.rgb;\n"; + code += " " + p_output_vars[1] + " = n_tex_read.a;\n"; + code += " }\n"; return code; } -void VisualShaderNodeTextureUniform::set_texture_type(TextureType p_type) { - - texture_type = p_type; +void VisualShaderNodeTextureUniform::set_texture_type(TextureType p_texture_type) { + ERR_FAIL_INDEX(int(p_texture_type), int(TYPE_MAX)); + if (texture_type == p_texture_type) { + return; + } + texture_type = p_texture_type; emit_changed(); } @@ -3768,8 +4915,12 @@ VisualShaderNodeTextureUniform::TextureType VisualShaderNodeTextureUniform::get_ return texture_type; } -void VisualShaderNodeTextureUniform::set_color_default(ColorDefault p_default) { - color_default = p_default; +void VisualShaderNodeTextureUniform::set_color_default(ColorDefault p_color_default) { + ERR_FAIL_INDEX(int(p_color_default), int(COLOR_DEFAULT_MAX)); + if (color_default == p_color_default) { + return; + } + color_default = p_color_default; emit_changed(); } @@ -3778,7 +4929,7 @@ VisualShaderNodeTextureUniform::ColorDefault VisualShaderNodeTextureUniform::get } Vector<StringName> VisualShaderNodeTextureUniform::get_editable_properties() const { - Vector<StringName> props; + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); props.push_back("texture_type"); props.push_back("color_default"); return props; @@ -3791,28 +4942,46 @@ void VisualShaderNodeTextureUniform::_bind_methods() { ClassDB::bind_method(D_METHOD("set_color_default", "type"), &VisualShaderNodeTextureUniform::set_color_default); ClassDB::bind_method(D_METHOD("get_color_default"), &VisualShaderNodeTextureUniform::get_color_default); - ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normalmap,Aniso"), "set_texture_type", "get_texture_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map,Anisotropic"), "set_texture_type", "get_texture_type"); ADD_PROPERTY(PropertyInfo(Variant::INT, "color_default", PROPERTY_HINT_ENUM, "White Default,Black Default"), "set_color_default", "get_color_default"); BIND_ENUM_CONSTANT(TYPE_DATA); BIND_ENUM_CONSTANT(TYPE_COLOR); - BIND_ENUM_CONSTANT(TYPE_NORMALMAP); + BIND_ENUM_CONSTANT(TYPE_NORMAL_MAP); BIND_ENUM_CONSTANT(TYPE_ANISO); + BIND_ENUM_CONSTANT(TYPE_MAX); BIND_ENUM_CONSTANT(COLOR_DEFAULT_WHITE); BIND_ENUM_CONSTANT(COLOR_DEFAULT_BLACK); + BIND_ENUM_CONSTANT(COLOR_DEFAULT_MAX); } String VisualShaderNodeTextureUniform::get_input_port_default_hint(int p_port) const { if (p_port == 0) { - return "UV.xy"; + return "default"; } return ""; } +bool VisualShaderNodeTextureUniform::is_qualifier_supported(Qualifier p_qual) const { + switch (p_qual) { + case Qualifier::QUAL_NONE: + return true; + case Qualifier::QUAL_GLOBAL: + return true; + case Qualifier::QUAL_INSTANCE: + return false; + default: + break; + } + return false; +} + +bool VisualShaderNodeTextureUniform::is_convertible_to_constant() const { + return false; // conversion is not allowed +} + VisualShaderNodeTextureUniform::VisualShaderNodeTextureUniform() { - texture_type = TYPE_DATA; - color_default = COLOR_DEFAULT_WHITE; simple_decl = false; } @@ -3827,9 +4996,7 @@ int VisualShaderNodeTextureUniformTriplanar::get_input_port_count() const { } VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniformTriplanar::get_input_port_type(int p_port) const { - if (p_port == 0) { - return PORT_TYPE_VECTOR; - } else if (p_port == 1) { + if (p_port == 0 || p_port == 1) { return PORT_TYPE_VECTOR; } return PORT_TYPE_SCALAR; @@ -3845,62 +5012,58 @@ String VisualShaderNodeTextureUniformTriplanar::get_input_port_name(int p_port) } String VisualShaderNodeTextureUniformTriplanar::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - String code; code += "// TRIPLANAR FUNCTION GLOBAL CODE\n"; - code += "\tvec4 triplanar_texture(sampler2D p_sampler, vec3 p_weights, vec3 p_triplanar_pos) {\n"; - code += "\t\tvec4 samp = vec4(0.0);\n"; - code += "\t\tsamp += texture(p_sampler, p_triplanar_pos.xy) * p_weights.z;\n"; - code += "\t\tsamp += texture(p_sampler, p_triplanar_pos.xz) * p_weights.y;\n"; - code += "\t\tsamp += texture(p_sampler, p_triplanar_pos.zy * vec2(-1.0, 1.0)) * p_weights.x;\n"; - code += "\t\treturn samp;\n"; - code += "\t}\n"; + code += " vec4 triplanar_texture(sampler2D p_sampler, vec3 p_weights, vec3 p_triplanar_pos) {\n"; + code += " vec4 samp = vec4(0.0);\n"; + code += " samp += texture(p_sampler, p_triplanar_pos.xy) * p_weights.z;\n"; + code += " samp += texture(p_sampler, p_triplanar_pos.xz) * p_weights.y;\n"; + code += " samp += texture(p_sampler, p_triplanar_pos.zy * vec2(-1.0, 1.0)) * p_weights.x;\n"; + code += " return samp;\n"; + code += " }\n"; code += "\n"; - code += "\tuniform vec3 triplanar_scale = vec3(1.0, 1.0, 1.0);\n"; - code += "\tuniform vec3 triplanar_offset;\n"; - code += "\tuniform float triplanar_sharpness = 0.5;\n"; + code += " uniform vec3 triplanar_scale = vec3(1.0, 1.0, 1.0);\n"; + code += " uniform vec3 triplanar_offset;\n"; + code += " uniform float triplanar_sharpness = 0.5;\n"; code += "\n"; - code += "\tvarying vec3 triplanar_power_normal;\n"; - code += "\tvarying vec3 triplanar_pos;\n"; + code += " varying vec3 triplanar_power_normal;\n"; + code += " varying vec3 triplanar_pos;\n"; return code; } String VisualShaderNodeTextureUniformTriplanar::generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - String code; if (p_type == VisualShader::TYPE_VERTEX) { - - code += "\t// TRIPLANAR FUNCTION VERTEX CODE\n"; - code += "\t\ttriplanar_power_normal = pow(abs(NORMAL), vec3(triplanar_sharpness));\n"; - code += "\t\ttriplanar_power_normal /= dot(triplanar_power_normal, vec3(1.0));\n"; - code += "\t\ttriplanar_pos = VERTEX * triplanar_scale + triplanar_offset;\n"; - code += "\t\ttriplanar_pos *= vec3(1.0, -1.0, 1.0);\n"; + code += " // TRIPLANAR FUNCTION VERTEX CODE\n"; + code += " triplanar_power_normal = pow(abs(NORMAL), vec3(triplanar_sharpness));\n"; + code += " triplanar_power_normal /= dot(triplanar_power_normal, vec3(1.0));\n"; + code += " triplanar_pos = VERTEX * triplanar_scale + triplanar_offset;\n"; + code += " triplanar_pos *= vec3(1.0, -1.0, 1.0);\n"; } return code; } String VisualShaderNodeTextureUniformTriplanar::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 id = get_uniform_name(); - String code = "\t{\n"; + String code = " {\n"; if (p_input_vars[0] == String() && p_input_vars[1] == String()) { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", triplanar_power_normal, triplanar_pos );\n"; + code += " vec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, triplanar_pos);\n"; } else if (p_input_vars[0] != String() && p_input_vars[1] == String()) { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", " + p_input_vars[0] + ", triplanar_pos );\n"; + code += " vec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", triplanar_pos);\n"; } else if (p_input_vars[0] == String() && p_input_vars[1] != String()) { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", triplanar_power_normal," + p_input_vars[1] + " );\n"; + code += " vec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, " + p_input_vars[1] + ");\n"; } else { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + " );\n"; + code += " vec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } - code += "\t\t" + p_output_vars[0] + " = n_tex_read.rgb;\n"; - code += "\t\t" + p_output_vars[1] + " = n_tex_read.a;\n"; - code += "\t}\n"; + code += " " + p_output_vars[0] + " = n_tex_read.rgb;\n"; + code += " " + p_output_vars[1] + " = n_tex_read.a;\n"; + code += " }\n"; return code; } @@ -3917,6 +5080,152 @@ String VisualShaderNodeTextureUniformTriplanar::get_input_port_default_hint(int VisualShaderNodeTextureUniformTriplanar::VisualShaderNodeTextureUniformTriplanar() { } +////////////// Texture2DArray Uniform + +String VisualShaderNodeTexture2DArrayUniform::get_caption() const { + return "Texture2DArrayUniform"; +} + +int VisualShaderNodeTexture2DArrayUniform::get_output_port_count() const { + return 1; +} + +VisualShaderNodeTexture2DArrayUniform::PortType VisualShaderNodeTexture2DArrayUniform::get_output_port_type(int p_port) const { + return PORT_TYPE_SAMPLER; +} + +String VisualShaderNodeTexture2DArrayUniform::get_output_port_name(int p_port) const { + return "sampler2DArray"; +} + +int VisualShaderNodeTexture2DArrayUniform::get_input_port_count() const { + return 0; +} + +VisualShaderNodeTexture2DArrayUniform::PortType VisualShaderNodeTexture2DArrayUniform::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeTexture2DArrayUniform::get_input_port_name(int p_port) const { + return ""; +} + +String VisualShaderNodeTexture2DArrayUniform::get_input_port_default_hint(int p_port) const { + return ""; +} + +String VisualShaderNodeTexture2DArrayUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = _get_qual_str() + "uniform sampler2DArray " + get_uniform_name(); + + switch (texture_type) { + case TYPE_DATA: + if (color_default == COLOR_DEFAULT_BLACK) { + code += " : hint_black;\n"; + } else { + code += ";\n"; + } + break; + case TYPE_COLOR: + if (color_default == COLOR_DEFAULT_BLACK) { + code += " : hint_black_albedo;\n"; + } else { + code += " : hint_albedo;\n"; + } + break; + case TYPE_NORMAL_MAP: + code += " : hint_normal;\n"; + break; + case TYPE_ANISO: + code += " : hint_aniso;\n"; + break; + default: + code += ";\n"; + break; + } + + return code; +} + +String VisualShaderNodeTexture2DArrayUniform::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 { + return String(); +} + +VisualShaderNodeTexture2DArrayUniform::VisualShaderNodeTexture2DArrayUniform() { +} + +////////////// Texture3D Uniform + +String VisualShaderNodeTexture3DUniform::get_caption() const { + return "Texture3DUniform"; +} + +int VisualShaderNodeTexture3DUniform::get_output_port_count() const { + return 1; +} + +VisualShaderNodeTexture3DUniform::PortType VisualShaderNodeTexture3DUniform::get_output_port_type(int p_port) const { + return PORT_TYPE_SAMPLER; +} + +String VisualShaderNodeTexture3DUniform::get_output_port_name(int p_port) const { + return "sampler3D"; +} + +int VisualShaderNodeTexture3DUniform::get_input_port_count() const { + return 0; +} + +VisualShaderNodeTexture3DUniform::PortType VisualShaderNodeTexture3DUniform::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeTexture3DUniform::get_input_port_name(int p_port) const { + return ""; +} + +String VisualShaderNodeTexture3DUniform::get_input_port_default_hint(int p_port) const { + return ""; +} + +String VisualShaderNodeTexture3DUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = _get_qual_str() + "uniform sampler3D " + get_uniform_name(); + + switch (texture_type) { + case TYPE_DATA: + if (color_default == COLOR_DEFAULT_BLACK) { + code += " : hint_black;\n"; + } else { + code += ";\n"; + } + break; + case TYPE_COLOR: + if (color_default == COLOR_DEFAULT_BLACK) { + code += " : hint_black_albedo;\n"; + } else { + code += " : hint_albedo;\n"; + } + break; + case TYPE_NORMAL_MAP: + code += " : hint_normal;\n"; + break; + case TYPE_ANISO: + code += " : hint_aniso;\n"; + break; + default: + code += ";\n"; + break; + } + + return code; +} + +String VisualShaderNodeTexture3DUniform::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 { + return String(); +} + +VisualShaderNodeTexture3DUniform::VisualShaderNodeTexture3DUniform() { +} + ////////////// Cubemap Uniform String VisualShaderNodeCubemapUniform::get_caption() const { @@ -3952,23 +5261,32 @@ String VisualShaderNodeCubemapUniform::get_input_port_default_hint(int p_port) c } String VisualShaderNodeCubemapUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - String code = "uniform samplerCube " + get_uniform_name(); + String code = _get_qual_str() + "uniform samplerCube " + get_uniform_name(); switch (texture_type) { case TYPE_DATA: - if (color_default == COLOR_DEFAULT_BLACK) + if (color_default == COLOR_DEFAULT_BLACK) { code += " : hint_black;\n"; - else + } else { code += ";\n"; + } break; case TYPE_COLOR: - if (color_default == COLOR_DEFAULT_BLACK) + if (color_default == COLOR_DEFAULT_BLACK) { code += " : hint_black_albedo;\n"; - else + } else { code += " : hint_albedo;\n"; + } + break; + case TYPE_NORMAL_MAP: + code += " : hint_normal;\n"; + break; + case TYPE_ANISO: + code += " : hint_aniso;\n"; + break; + default: + code += ";\n"; break; - case TYPE_NORMALMAP: code += " : hint_normal;\n"; break; - case TYPE_ANISO: code += " : hint_aniso;\n"; break; } return code; @@ -4030,37 +5348,36 @@ String VisualShaderNodeIf::get_output_port_name(int p_port) const { } String VisualShaderNodeIf::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 += "\tif(abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ")\n"; // abs(a - b) < tolerance eg. a == b - code += "\t{\n"; - code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[3] + ";\n"; - code += "\t}\n"; - code += "\telse if(" + p_input_vars[0] + " < " + p_input_vars[1] + ")\n"; // a < b - code += "\t{\n"; - code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[5] + ";\n"; - code += "\t}\n"; - code += "\telse\n"; // a > b (or a >= b if abs(a - b) < tolerance is false) - code += "\t{\n"; - code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[4] + ";\n"; - code += "\t}\n"; + code += " if(abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ")\n"; // abs(a - b) < tolerance eg. a == b + code += " {\n"; + code += " " + p_output_vars[0] + " = " + p_input_vars[3] + ";\n"; + code += " }\n"; + code += " else if(" + p_input_vars[0] + " < " + p_input_vars[1] + ")\n"; // a < b + code += " {\n"; + code += " " + p_output_vars[0] + " = " + p_input_vars[5] + ";\n"; + code += " }\n"; + code += " else\n"; // a > b (or a >= b if abs(a - b) < tolerance is false) + code += " {\n"; + code += " " + p_output_vars[0] + " = " + p_input_vars[4] + ";\n"; + code += " }\n"; return code; } VisualShaderNodeIf::VisualShaderNodeIf() { + simple_decl = false; set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); set_input_port_default_value(2, CMP_EPSILON); set_input_port_default_value(3, Vector3(0.0, 0.0, 0.0)); set_input_port_default_value(4, Vector3(0.0, 0.0, 0.0)); set_input_port_default_value(5, Vector3(0.0, 0.0, 0.0)); - simple_decl = false; } ////////////// Switch String VisualShaderNodeSwitch::get_caption() const { - return "VectorSwitch"; + return "Switch"; } int VisualShaderNodeSwitch::get_input_port_count() const { @@ -4071,7 +5388,21 @@ VisualShaderNodeSwitch::PortType VisualShaderNodeSwitch::get_input_port_type(int if (p_port == 0) { return PORT_TYPE_BOOLEAN; } - return PORT_TYPE_VECTOR; + if (p_port == 1 || p_port == 2) { + switch (op_type) { + case OP_TYPE_INT: + return PORT_TYPE_SCALAR_INT; + case OP_TYPE_VECTOR: + return PORT_TYPE_VECTOR; + case OP_TYPE_BOOLEAN: + return PORT_TYPE_BOOLEAN; + case OP_TYPE_TRANSFORM: + return PORT_TYPE_TRANSFORM; + default: + break; + } + } + return PORT_TYPE_SCALAR; } String VisualShaderNodeSwitch::get_input_port_name(int p_port) const { @@ -4092,52 +5423,97 @@ int VisualShaderNodeSwitch::get_output_port_count() const { } VisualShaderNodeSwitch::PortType VisualShaderNodeSwitch::get_output_port_type(int p_port) const { - return PORT_TYPE_VECTOR; + switch (op_type) { + case OP_TYPE_INT: + return PORT_TYPE_SCALAR_INT; + case OP_TYPE_VECTOR: + return PORT_TYPE_VECTOR; + case OP_TYPE_BOOLEAN: + return PORT_TYPE_BOOLEAN; + case OP_TYPE_TRANSFORM: + return PORT_TYPE_TRANSFORM; + default: + break; + } + return PORT_TYPE_SCALAR; } String VisualShaderNodeSwitch::get_output_port_name(int p_port) const { return "result"; } -String VisualShaderNodeSwitch::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 { +void VisualShaderNodeSwitch::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX(int(p_op_type), int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; + } + switch (p_op_type) { + case OP_TYPE_FLOAT: + set_input_port_default_value(1, 1.0); + set_input_port_default_value(2, 0.0); + break; + case OP_TYPE_INT: + set_input_port_default_value(1, 1); + set_input_port_default_value(2, 0); + break; + case OP_TYPE_VECTOR: + set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); + set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); + break; + case OP_TYPE_BOOLEAN: + set_input_port_default_value(1, true); + set_input_port_default_value(2, false); + break; + case OP_TYPE_TRANSFORM: + set_input_port_default_value(1, Transform3D()); + set_input_port_default_value(2, Transform3D()); + break; + default: + break; + } + op_type = p_op_type; + emit_changed(); +} - String code; - code += "\tif(" + p_input_vars[0] + ")\n"; - code += "\t{\n"; - code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[1] + ";\n"; - code += "\t}\n"; - code += "\telse\n"; - code += "\t{\n"; - code += "\t\t" + p_output_vars[0] + " = " + p_input_vars[2] + ";\n"; - code += "\t}\n"; - return code; +VisualShaderNodeSwitch::OpType VisualShaderNodeSwitch::get_op_type() const { + return op_type; } -VisualShaderNodeSwitch::VisualShaderNodeSwitch() { - set_input_port_default_value(0, false); - set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); - set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); - simple_decl = false; +Vector<StringName> VisualShaderNodeSwitch::get_editable_properties() const { + Vector<StringName> props; + props.push_back("op_type"); + return props; } -////////////// Switch(scalar) +void VisualShaderNodeSwitch::_bind_methods() { // static + ClassDB::bind_method(D_METHOD("set_op_type", "type"), &VisualShaderNodeSwitch::set_op_type); + ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeSwitch::get_op_type); -String VisualShaderNodeScalarSwitch::get_caption() const { - return "ScalarSwitch"; -} + ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Float,Int,Vector,Boolean,Transform"), "set_op_type", "get_op_type"); -VisualShaderNodeScalarSwitch::PortType VisualShaderNodeScalarSwitch::get_input_port_type(int p_port) const { - if (p_port == 0) { - return PORT_TYPE_BOOLEAN; - } - return PORT_TYPE_SCALAR; + BIND_ENUM_CONSTANT(OP_TYPE_FLOAT); + BIND_ENUM_CONSTANT(OP_TYPE_INT); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR); + BIND_ENUM_CONSTANT(OP_TYPE_BOOLEAN); + BIND_ENUM_CONSTANT(OP_TYPE_TRANSFORM); + BIND_ENUM_CONSTANT(OP_TYPE_MAX); } -VisualShaderNodeScalarSwitch::PortType VisualShaderNodeScalarSwitch::get_output_port_type(int p_port) const { - return PORT_TYPE_SCALAR; +String VisualShaderNodeSwitch::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 += " if(" + p_input_vars[0] + ")\n"; + code += " {\n"; + code += " " + p_output_vars[0] + " = " + p_input_vars[1] + ";\n"; + code += " }\n"; + code += " else\n"; + code += " {\n"; + code += " " + p_output_vars[0] + " = " + p_input_vars[2] + ";\n"; + code += " }\n"; + return code; } -VisualShaderNodeScalarSwitch::VisualShaderNodeScalarSwitch() { +VisualShaderNodeSwitch::VisualShaderNodeSwitch() { + simple_decl = false; set_input_port_default_value(0, false); set_input_port_default_value(1, 1.0); set_input_port_default_value(2, 0.0); @@ -4195,8 +5571,14 @@ String VisualShaderNodeFresnel::get_output_port_name(int p_port) const { return "result"; } -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 { +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; String view; if (p_input_vars[0] == String()) { @@ -4210,7 +5592,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 " " + 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 " " + p_output_vars[0] + " = pow(clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ");\n"; + } else { + return " " + 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 { @@ -4230,72 +5620,64 @@ VisualShaderNodeFresnel::VisualShaderNodeFresnel() { ////////////// Is String VisualShaderNodeIs::get_caption() const { - return "Is"; } int VisualShaderNodeIs::get_input_port_count() const { - return 1; } VisualShaderNodeIs::PortType VisualShaderNodeIs::get_input_port_type(int p_port) const { - return PORT_TYPE_SCALAR; } String VisualShaderNodeIs::get_input_port_name(int p_port) const { - return ""; } int VisualShaderNodeIs::get_output_port_count() const { - return 1; } VisualShaderNodeIs::PortType VisualShaderNodeIs::get_output_port_type(int p_port) const { - return PORT_TYPE_BOOLEAN; } String VisualShaderNodeIs::get_output_port_name(int p_port) const { - return ""; } String VisualShaderNodeIs::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 { - - static const char *funcs[FUNC_IS_NAN + 1] = { + static const char *functions[FUNC_MAX] = { "isinf($)", "isnan($)" }; String code; - code += "\t" + p_output_vars[0] + " = " + String(funcs[func]).replace("$", p_input_vars[0]) + ";\n"; + code += " " + p_output_vars[0] + " = " + String(functions[func]).replace("$", p_input_vars[0]) + ";\n"; return code; } void VisualShaderNodeIs::set_function(Function p_func) { - + ERR_FAIL_INDEX(int(p_func), int(FUNC_MAX)); + if (func == p_func) { + return; + } func = p_func; emit_changed(); } VisualShaderNodeIs::Function VisualShaderNodeIs::get_function() const { - return func; } Vector<StringName> VisualShaderNodeIs::get_editable_properties() const { - Vector<StringName> props; props.push_back("function"); return props; } void VisualShaderNodeIs::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeIs::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeIs::get_function); @@ -4303,34 +5685,28 @@ void VisualShaderNodeIs::_bind_methods() { BIND_ENUM_CONSTANT(FUNC_IS_INF); BIND_ENUM_CONSTANT(FUNC_IS_NAN); + BIND_ENUM_CONSTANT(FUNC_MAX); } VisualShaderNodeIs::VisualShaderNodeIs() { - - func = FUNC_IS_INF; set_input_port_default_value(0, 0.0); } ////////////// Compare String VisualShaderNodeCompare::get_caption() const { - return "Compare"; } int VisualShaderNodeCompare::get_input_port_count() const { - - if (ctype == CTYPE_SCALAR && (func == FUNC_EQUAL || func == FUNC_NOT_EQUAL)) { + if (comparison_type == CTYPE_SCALAR && (func == FUNC_EQUAL || func == FUNC_NOT_EQUAL)) { return 3; } return 2; } VisualShaderNodeCompare::PortType VisualShaderNodeCompare::get_input_port_type(int p_port) const { - - if (p_port == 2) - return PORT_TYPE_SCALAR; - switch (ctype) { + switch (comparison_type) { case CTYPE_SCALAR: return PORT_TYPE_SCALAR; case CTYPE_SCALAR_INT: @@ -4341,17 +5717,19 @@ VisualShaderNodeCompare::PortType VisualShaderNodeCompare::get_input_port_type(i return PORT_TYPE_BOOLEAN; case CTYPE_TRANSFORM: return PORT_TYPE_TRANSFORM; + default: + return PORT_TYPE_SCALAR; } - return PORT_TYPE_VECTOR; } String VisualShaderNodeCompare::get_input_port_name(int p_port) const { - if (p_port == 0) + if (p_port == 0) { return "a"; - else if (p_port == 1) + } else if (p_port == 1) { return "b"; - else if (p_port == 2) + } else if (p_port == 2) { return "tolerance"; + } return ""; } @@ -4364,25 +5742,23 @@ VisualShaderNodeCompare::PortType VisualShaderNodeCompare::get_output_port_type( } String VisualShaderNodeCompare::get_output_port_name(int p_port) const { - if (p_port == 0) + if (p_port == 0) { return "result"; + } return ""; } String VisualShaderNodeCompare::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const { - - if (ctype == CTYPE_BOOLEAN || ctype == CTYPE_TRANSFORM) { + if (comparison_type == CTYPE_BOOLEAN || comparison_type == CTYPE_TRANSFORM) { if (func > FUNC_NOT_EQUAL) { return TTR("Invalid comparison function for that type."); } } - return ""; } String VisualShaderNodeCompare::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 { - - static const char *ops[FUNC_LESS_THAN_EQUAL + 1] = { + static const char *operators[FUNC_MAX] = { "==", "!=", ">", @@ -4391,7 +5767,7 @@ String VisualShaderNodeCompare::generate_code(Shader::Mode p_mode, VisualShader: "<=", }; - static const char *funcs[FUNC_LESS_THAN_EQUAL + 1] = { + static const char *functions[FUNC_MAX] = { "equal($)", "notEqual($)", "greaterThan($)", @@ -4400,44 +5776,46 @@ String VisualShaderNodeCompare::generate_code(Shader::Mode p_mode, VisualShader: "lessThanEqual($)", }; - static const char *conds[COND_ANY + 1] = { + static const char *conditions[COND_MAX] = { "all($)", "any($)", }; String code; - switch (ctype) { + switch (comparison_type) { case CTYPE_SCALAR: if (func == FUNC_EQUAL) { - code += "\t" + p_output_vars[0] + " = (abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ");"; + code += " " + p_output_vars[0] + " = (abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ");"; } else if (func == FUNC_NOT_EQUAL) { - code += "\t" + p_output_vars[0] + " = !(abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ");"; + code += " " + p_output_vars[0] + " = !(abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ");"; } else { - code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n"; + code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", operators[func]) + ";\n"; } break; case CTYPE_SCALAR_INT: - code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n"; + code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", operators[func]) + ";\n"; break; case CTYPE_VECTOR: - code += "\t{\n"; - code += "\t\tbvec3 _bv = " + String(funcs[func]).replace("$", p_input_vars[0] + ", " + p_input_vars[1]) + ";\n"; - code += "\t\t" + p_output_vars[0] + " = " + String(conds[condition]).replace("$", "_bv") + ";\n"; - code += "\t}\n"; + code += " {\n"; + code += " bvec3 _bv = " + String(functions[func]).replace("$", p_input_vars[0] + ", " + p_input_vars[1]) + ";\n"; + code += " " + p_output_vars[0] + " = " + String(conditions[condition]).replace("$", "_bv") + ";\n"; + code += " }\n"; break; case CTYPE_BOOLEAN: - if (func > FUNC_NOT_EQUAL) - return "\t" + p_output_vars[0] + " = false;\n"; - code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n"; + if (func > FUNC_NOT_EQUAL) { + return " " + p_output_vars[0] + " = false;\n"; + } + code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", operators[func]) + ";\n"; break; case CTYPE_TRANSFORM: - if (func > FUNC_NOT_EQUAL) - return "\t" + p_output_vars[0] + " = false;\n"; - code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n"; + if (func > FUNC_NOT_EQUAL) { + return " " + p_output_vars[0] + " = false;\n"; + } + code += " " + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", operators[func]) + ";\n"; break; default: @@ -4446,11 +5824,12 @@ String VisualShaderNodeCompare::generate_code(Shader::Mode p_mode, VisualShader: return code; } -void VisualShaderNodeCompare::set_comparison_type(ComparisonType p_type) { - - ctype = p_type; - - switch (ctype) { +void VisualShaderNodeCompare::set_comparison_type(ComparisonType p_comparison_type) { + ERR_FAIL_INDEX(int(p_comparison_type), int(CTYPE_MAX)); + if (comparison_type == p_comparison_type) { + return; + } + switch (p_comparison_type) { case CTYPE_SCALAR: set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); @@ -4472,38 +5851,44 @@ void VisualShaderNodeCompare::set_comparison_type(ComparisonType p_type) { simple_decl = true; break; case CTYPE_TRANSFORM: - set_input_port_default_value(0, Transform()); - set_input_port_default_value(1, Transform()); + set_input_port_default_value(0, Transform3D()); + set_input_port_default_value(1, Transform3D()); simple_decl = true; break; + default: + break; } + comparison_type = p_comparison_type; emit_changed(); } VisualShaderNodeCompare::ComparisonType VisualShaderNodeCompare::get_comparison_type() const { - - return ctype; + return comparison_type; } void VisualShaderNodeCompare::set_function(Function p_func) { - + ERR_FAIL_INDEX(int(p_func), int(FUNC_MAX)); + if (func == p_func) { + return; + } func = p_func; emit_changed(); } VisualShaderNodeCompare::Function VisualShaderNodeCompare::get_function() const { - return func; } -void VisualShaderNodeCompare::set_condition(Condition p_cond) { - - condition = p_cond; +void VisualShaderNodeCompare::set_condition(Condition p_condition) { + ERR_FAIL_INDEX(int(p_condition), int(COND_MAX)); + if (condition == p_condition) { + return; + } + condition = p_condition; emit_changed(); } VisualShaderNodeCompare::Condition VisualShaderNodeCompare::get_condition() const { - return condition; } @@ -4511,13 +5896,13 @@ Vector<StringName> VisualShaderNodeCompare::get_editable_properties() const { Vector<StringName> props; props.push_back("type"); props.push_back("function"); - if (ctype == CTYPE_VECTOR) + if (comparison_type == CTYPE_VECTOR) { props.push_back("condition"); + } return props; } void VisualShaderNodeCompare::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_comparison_type", "type"), &VisualShaderNodeCompare::set_comparison_type); ClassDB::bind_method(D_METHOD("get_comparison_type"), &VisualShaderNodeCompare::get_comparison_type); @@ -4536,6 +5921,7 @@ void VisualShaderNodeCompare::_bind_methods() { BIND_ENUM_CONSTANT(CTYPE_VECTOR); BIND_ENUM_CONSTANT(CTYPE_BOOLEAN); BIND_ENUM_CONSTANT(CTYPE_TRANSFORM); + BIND_ENUM_CONSTANT(CTYPE_MAX); BIND_ENUM_CONSTANT(FUNC_EQUAL); BIND_ENUM_CONSTANT(FUNC_NOT_EQUAL); @@ -4543,16 +5929,240 @@ void VisualShaderNodeCompare::_bind_methods() { BIND_ENUM_CONSTANT(FUNC_GREATER_THAN_EQUAL); BIND_ENUM_CONSTANT(FUNC_LESS_THAN); BIND_ENUM_CONSTANT(FUNC_LESS_THAN_EQUAL); + BIND_ENUM_CONSTANT(FUNC_MAX); BIND_ENUM_CONSTANT(COND_ALL); BIND_ENUM_CONSTANT(COND_ANY); + BIND_ENUM_CONSTANT(COND_MAX); } VisualShaderNodeCompare::VisualShaderNodeCompare() { - ctype = CTYPE_SCALAR; - func = FUNC_EQUAL; - condition = COND_ALL; set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); set_input_port_default_value(2, CMP_EPSILON); } + +////////////// Fma + +String VisualShaderNodeMultiplyAdd::get_caption() const { + return "MultiplyAdd"; +} + +int VisualShaderNodeMultiplyAdd::get_input_port_count() const { + return 3; +} + +VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_input_port_type(int p_port) const { + if (op_type == OP_TYPE_VECTOR) { + return PORT_TYPE_VECTOR; + } + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeMultiplyAdd::get_input_port_name(int p_port) const { + if (p_port == 0) { + return "a"; + } else if (p_port == 1) { + return "b(*)"; + } else if (p_port == 2) { + return "c(+)"; + } + return ""; +} + +int VisualShaderNodeMultiplyAdd::get_output_port_count() const { + return 1; +} + +VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_output_port_type(int p_port) const { + if (op_type == OP_TYPE_SCALAR) { + return PORT_TYPE_SCALAR; + } else { + return PORT_TYPE_VECTOR; + } +} + +String VisualShaderNodeMultiplyAdd::get_output_port_name(int p_port) const { + return ""; +} + +String VisualShaderNodeMultiplyAdd::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 { + return " " + p_output_vars[0] + " = fma(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; +} + +void VisualShaderNodeMultiplyAdd::set_op_type(OpType p_op_type) { + ERR_FAIL_INDEX((int)p_op_type, int(OP_TYPE_MAX)); + if (op_type == p_op_type) { + return; + } + switch (p_op_type) { + case OP_TYPE_SCALAR: + set_input_port_default_value(0, 0.0); + set_input_port_default_value(1, 0.0); + set_input_port_default_value(2, 0.0); + break; + case OP_TYPE_VECTOR: + set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); + set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); + set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); + break; + default: + break; + } + op_type = p_op_type; + emit_changed(); +} + +VisualShaderNodeMultiplyAdd::OpType VisualShaderNodeMultiplyAdd::get_op_type() const { + return op_type; +} + +Vector<StringName> VisualShaderNodeMultiplyAdd::get_editable_properties() const { + Vector<StringName> props; + props.push_back("op_type"); + return props; +} + +void VisualShaderNodeMultiplyAdd::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_op_type", "type"), &VisualShaderNodeMultiplyAdd::set_op_type); + ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeMultiplyAdd::get_op_type); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector"), "set_op_type", "get_op_type"); + + BIND_ENUM_CONSTANT(OP_TYPE_SCALAR); + BIND_ENUM_CONSTANT(OP_TYPE_VECTOR); + BIND_ENUM_CONSTANT(OP_TYPE_MAX); +} + +VisualShaderNodeMultiplyAdd::VisualShaderNodeMultiplyAdd() { + set_input_port_default_value(0, 0.0); + set_input_port_default_value(1, 0.0); + set_input_port_default_value(2, 0.0); +} + +////////////// Billboard + +String VisualShaderNodeBillboard::get_caption() const { + return "GetBillboardMatrix"; +} + +int VisualShaderNodeBillboard::get_input_port_count() const { + return 0; +} + +VisualShaderNodeBillboard::PortType VisualShaderNodeBillboard::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeBillboard::get_input_port_name(int p_port) const { + return ""; +} + +int VisualShaderNodeBillboard::get_output_port_count() const { + return 1; +} + +VisualShaderNodeBillboard::PortType VisualShaderNodeBillboard::get_output_port_type(int p_port) const { + return PORT_TYPE_TRANSFORM; +} + +String VisualShaderNodeBillboard::get_output_port_name(int p_port) const { + return "model_view_matrix"; +} + +String VisualShaderNodeBillboard::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; + + switch (billboard_type) { + case BILLBOARD_TYPE_ENABLED: + code += " {\n"; + code += " mat4 __mvm = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0], CAMERA_MATRIX[1], CAMERA_MATRIX[2], WORLD_MATRIX[3]);\n"; + if (keep_scale) { + code += " __mvm = __mvm * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, length(WORLD_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; + } + code += " " + p_output_vars[0] + " = __mvm;\n"; + code += " }\n"; + break; + case BILLBOARD_TYPE_FIXED_Y: + code += " {\n"; + code += " mat4 __mvm = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0], WORLD_MATRIX[1], vec4(normalize(cross(CAMERA_MATRIX[0].xyz, WORLD_MATRIX[1].xyz)), 0.0), WORLD_MATRIX[3]);\n"; + if (keep_scale) { + code += " __mvm = __mvm * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; + } else { + code += " __mvm = __mvm * mat4(vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0 / length(WORLD_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; + } + code += " " + p_output_vars[0] + " = __mvm;\n"; + code += " }\n"; + break; + case BILLBOARD_TYPE_PARTICLES: + code += " {\n"; + code += " mat4 __wm = mat4(normalize(CAMERA_MATRIX[0]) * length(WORLD_MATRIX[0]), normalize(CAMERA_MATRIX[1]) * length(WORLD_MATRIX[0]), normalize(CAMERA_MATRIX[2]) * length(WORLD_MATRIX[2]), WORLD_MATRIX[3]);\n"; + code += " __wm = __wm * mat4(vec4(cos(INSTANCE_CUSTOM.x), -sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; + code += " " + p_output_vars[0] + " = INV_CAMERA_MATRIX * __wm;\n"; + code += " }\n"; + break; + default: + code += " " + p_output_vars[0] + " = mat4(1.0);\n"; + break; + } + + return code; +} + +bool VisualShaderNodeBillboard::is_show_prop_names() const { + return true; +} + +void VisualShaderNodeBillboard::set_billboard_type(BillboardType p_billboard_type) { + ERR_FAIL_INDEX(int(p_billboard_type), int(BILLBOARD_TYPE_MAX)); + if (billboard_type == p_billboard_type) { + return; + } + billboard_type = p_billboard_type; + simple_decl = bool(billboard_type == BILLBOARD_TYPE_DISABLED); + set_disabled(simple_decl); + emit_changed(); +} + +VisualShaderNodeBillboard::BillboardType VisualShaderNodeBillboard::get_billboard_type() const { + return billboard_type; +} + +void VisualShaderNodeBillboard::set_keep_scale_enabled(bool p_enabled) { + keep_scale = p_enabled; + emit_changed(); +} + +bool VisualShaderNodeBillboard::is_keep_scale_enabled() const { + return keep_scale; +} + +Vector<StringName> VisualShaderNodeBillboard::get_editable_properties() const { + Vector<StringName> props; + props.push_back("billboard_type"); + if (billboard_type == BILLBOARD_TYPE_ENABLED || billboard_type == BILLBOARD_TYPE_FIXED_Y) { + props.push_back("keep_scale"); + } + return props; +} + +void VisualShaderNodeBillboard::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_billboard_type", "billboard_type"), &VisualShaderNodeBillboard::set_billboard_type); + ClassDB::bind_method(D_METHOD("get_billboard_type"), &VisualShaderNodeBillboard::get_billboard_type); + + ClassDB::bind_method(D_METHOD("set_keep_scale_enabled", "enabled"), &VisualShaderNodeBillboard::set_keep_scale_enabled); + ClassDB::bind_method(D_METHOD("is_keep_scale_enabled"), &VisualShaderNodeBillboard::is_keep_scale_enabled); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "billboard_type", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard,Particles"), "set_billboard_type", "get_billboard_type"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_scale"), "set_keep_scale_enabled", "is_keep_scale_enabled"); + + BIND_ENUM_CONSTANT(BILLBOARD_TYPE_DISABLED); + BIND_ENUM_CONSTANT(BILLBOARD_TYPE_ENABLED); + BIND_ENUM_CONSTANT(BILLBOARD_TYPE_FIXED_Y); + BIND_ENUM_CONSTANT(BILLBOARD_TYPE_PARTICLES); + BIND_ENUM_CONSTANT(BILLBOARD_TYPE_MAX); +} + +VisualShaderNodeBillboard::VisualShaderNodeBillboard() { + simple_decl = false; +} |