diff --git a/doc/classes/VisualShaderNodeIntParameter.xml b/doc/classes/VisualShaderNodeIntParameter.xml index ba17da49a821..d3d77f040fa1 100644 --- a/doc/classes/VisualShaderNodeIntParameter.xml +++ b/doc/classes/VisualShaderNodeIntParameter.xml @@ -15,9 +15,12 @@ <member name="default_value_enabled" type="bool" setter="set_default_value_enabled" getter="is_default_value_enabled" default="false"> If [code]true[/code], the node will have a custom default value. </member> - <member name="enum_names" type="PackedStringArray" setter="set_enum_names" getter="get_enum_names" default="PackedStringArray()"> + <member name="enum_names" type="PackedStringArray" setter="set_hint_names" getter="get_hint_names" default="PackedStringArray()"> The names used for the enum select in the editor. [member hint] must be [constant HINT_ENUM] for this to take effect. </member> + <member name="flag_names" type="PackedStringArray" setter="set_hint_names" getter="get_hint_names" default="PackedStringArray()"> + The names used for the bit flags in the editor. [member hint] must be [constant HINT_FLAGS] for this to take effect. + </member> <member name="hint" type="int" setter="set_hint" getter="get_hint" enum="VisualShaderNodeIntParameter.Hint" default="0"> Range hint of this node. Use it to customize valid parameter range. </member> @@ -44,7 +47,10 @@ <constant name="HINT_ENUM" value="3" enum="Hint"> The parameter uses an enum to associate preset values to names in the editor. </constant> - <constant name="HINT_MAX" value="4" enum="Hint"> + <constant name="HINT_FLAGS" value="4" enum="Hint"> + The parameter is configured using named bit flags in the editor. + </constant> + <constant name="HINT_MAX" value="5" enum="Hint"> Represents the size of the [enum Hint] enum. </constant> </constants> diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 5e148c9276da..d431163fffc5 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -5368,11 +5368,12 @@ String VisualShaderNodeIntParameter::generate_global(Shader::Mode p_mode, Visual code += _get_qual_str() + "uniform int " + get_parameter_name() + " : hint_range(" + itos(hint_range_min) + ", " + itos(hint_range_max) + ")"; } else if (hint == HINT_RANGE_STEP) { code += _get_qual_str() + "uniform int " + get_parameter_name() + " : hint_range(" + itos(hint_range_min) + ", " + itos(hint_range_max) + ", " + itos(hint_range_step) + ")"; - } else if (hint == HINT_ENUM) { - code += _get_qual_str() + "uniform int " + get_parameter_name() + " : hint_enum("; + } else if (hint == HINT_ENUM || hint == HINT_FLAGS) { + const char *hint_gdshader_name = hint == HINT_ENUM ? "hint_enum" : "hint_flags"; + code += _get_qual_str() + "uniform int " + get_parameter_name() + " : " + hint_gdshader_name + "("; bool first = true; - for (const String &_name : hint_enum_names) { + for (const String &_name : hint_names) { if (first) { first = false; } else { @@ -5453,16 +5454,16 @@ int VisualShaderNodeIntParameter::get_step() const { return hint_range_step; } -void VisualShaderNodeIntParameter::set_enum_names(const PackedStringArray &p_names) { - if (hint_enum_names == p_names) { +void VisualShaderNodeIntParameter::set_hint_names(const PackedStringArray &p_names) { + if (hint_names == p_names) { return; } - hint_enum_names = p_names; + hint_names = p_names; emit_changed(); } -PackedStringArray VisualShaderNodeIntParameter::get_enum_names() const { - return hint_enum_names; +PackedStringArray VisualShaderNodeIntParameter::get_hint_names() const { + return hint_names; } void VisualShaderNodeIntParameter::set_default_value_enabled(bool p_default_value_enabled) { @@ -5502,8 +5503,8 @@ void VisualShaderNodeIntParameter::_bind_methods() { ClassDB::bind_method(D_METHOD("set_step", "value"), &VisualShaderNodeIntParameter::set_step); ClassDB::bind_method(D_METHOD("get_step"), &VisualShaderNodeIntParameter::get_step); - ClassDB::bind_method(D_METHOD("set_enum_names", "names"), &VisualShaderNodeIntParameter::set_enum_names); - ClassDB::bind_method(D_METHOD("get_enum_names"), &VisualShaderNodeIntParameter::get_enum_names); + ClassDB::bind_method(D_METHOD("set_hint_names", "names"), &VisualShaderNodeIntParameter::set_hint_names); + ClassDB::bind_method(D_METHOD("get_hint_names"), &VisualShaderNodeIntParameter::get_hint_names); ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeIntParameter::set_default_value_enabled); ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeIntParameter::is_default_value_enabled); @@ -5511,11 +5512,12 @@ void VisualShaderNodeIntParameter::_bind_methods() { ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeIntParameter::set_default_value); ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeIntParameter::get_default_value); - ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range + Step,Enum"), "set_hint", "get_hint"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range + Step,Enum,Flags"), "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::PACKED_STRING_ARRAY, "enum_names"), "set_enum_names", "get_enum_names"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "enum_names"), "set_hint_names", "get_hint_names"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "flag_names"), "set_hint_names", "get_hint_names"); 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"); @@ -5523,6 +5525,7 @@ void VisualShaderNodeIntParameter::_bind_methods() { BIND_ENUM_CONSTANT(HINT_RANGE); BIND_ENUM_CONSTANT(HINT_RANGE_STEP); BIND_ENUM_CONSTANT(HINT_ENUM); + BIND_ENUM_CONSTANT(HINT_FLAGS); BIND_ENUM_CONSTANT(HINT_MAX); } @@ -5547,6 +5550,9 @@ Vector<StringName> VisualShaderNodeIntParameter::get_editable_properties() const if (hint == HINT_ENUM) { props.push_back("enum_names"); } + if (hint == HINT_FLAGS) { + props.push_back("flag_names"); + } props.push_back("default_value_enabled"); if (default_value_enabled) { props.push_back("default_value"); diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index 279599ef9c70..5ab063431e69 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -2116,6 +2116,7 @@ class VisualShaderNodeIntParameter : public VisualShaderNodeParameter { HINT_RANGE, HINT_RANGE_STEP, HINT_ENUM, + HINT_FLAGS, HINT_MAX, }; @@ -2124,7 +2125,7 @@ class VisualShaderNodeIntParameter : public VisualShaderNodeParameter { int hint_range_min = 0; int hint_range_max = 100; int hint_range_step = 1; - PackedStringArray hint_enum_names; + PackedStringArray hint_names; bool default_value_enabled = false; int default_value = 0; @@ -2160,8 +2161,8 @@ class VisualShaderNodeIntParameter : public VisualShaderNodeParameter { void set_step(int p_value); int get_step() const; - void set_enum_names(const PackedStringArray &p_names); - PackedStringArray get_enum_names() const; + void set_hint_names(const PackedStringArray &p_names); + PackedStringArray get_hint_names() const; void set_default_value_enabled(bool p_enabled); bool is_default_value_enabled() const; diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index f8d00ba7ecbc..f53b0c696e61 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -214,6 +214,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "HINT_SOURCE_COLOR", "HINT_RANGE", "HINT_ENUM", + "HINT_FLAGS", "HINT_INSTANCE_INDEX", "HINT_SCREEN_TEXTURE", "HINT_NORMAL_ROUGHNESS_TEXTURE", @@ -368,6 +369,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_HINT_SOURCE_COLOR, "source_color", CF_UNSPECIFIED, {}, {} }, { TK_HINT_RANGE, "hint_range", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ENUM, "hint_enum", CF_UNSPECIFIED, {}, {} }, + { TK_HINT_FLAGS, "hint_flags", CF_UNSPECIFIED, {}, {} }, { TK_HINT_INSTANCE_INDEX, "instance_index", CF_UNSPECIFIED, {}, {} }, // sampler hints @@ -1180,6 +1182,9 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) { case ShaderNode::Uniform::HINT_ENUM: { result = "hint_enum"; } break; + case ShaderNode::Uniform::HINT_FLAGS: { + result = "hint_flags"; + } break; case ShaderNode::Uniform::HINT_SOURCE_COLOR: { result = "source_color"; } break; @@ -4199,11 +4204,11 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform if (p_uniform.array_size > 0) { pi.type = Variant::PACKED_INT32_ARRAY; // TODO: Handle range and encoding for for unsigned values. - } else if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_ENUM) { + } else if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_ENUM || p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_FLAGS) { pi.type = Variant::INT; - pi.hint = PROPERTY_HINT_ENUM; + pi.hint = p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_ENUM ? PROPERTY_HINT_ENUM : PROPERTY_HINT_FLAGS; String hint_string; - pi.hint_string = String(",").join(p_uniform.hint_enum_names); + pi.hint_string = String(",").join(p_uniform.hint_names); } else { pi.type = Variant::INT; pi.hint = PROPERTY_HINT_RANGE; @@ -9046,15 +9051,24 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f new_hint = ShaderNode::Uniform::HINT_RANGE; } break; - case TK_HINT_ENUM: { + case TK_HINT_ENUM: + case TK_HINT_FLAGS: { + bool is_hint_enum = tk.type == TK_HINT_ENUM; + if (type != TYPE_INT) { - _set_error(vformat(RTR("Enum hint is for '%s' only."), "int")); + String err; + if (is_hint_enum) { + err = RTR("Enum hint is for '%s' only."); + } else { + err = RTR("Flags hint is for '%s' only."); + } + _set_error(vformat(err, "int")); return ERR_PARSE_ERROR; } tk = _get_token(); if (tk.type != TK_PARENTHESIS_OPEN) { - _set_expected_after_error("(", "hint_enum"); + _set_expected_after_error("(", is_hint_enum ? "hint_enum" : "hint_flags"); return ERR_PARSE_ERROR; } @@ -9066,7 +9080,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f return ERR_PARSE_ERROR; } - uniform.hint_enum_names.push_back(tk.text); + uniform.hint_names.push_back(tk.text); tk = _get_token(); @@ -9078,7 +9092,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f } } - new_hint = ShaderNode::Uniform::HINT_ENUM; + new_hint = is_hint_enum ? ShaderNode::Uniform::HINT_ENUM : ShaderNode::Uniform::HINT_FLAGS; } break; case TK_HINT_INSTANCE_INDEX: { if (custom_instance_index != -1) { @@ -9175,7 +9189,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f break; } - bool is_sampler_hint = new_hint != ShaderNode::Uniform::HINT_NONE && new_hint != ShaderNode::Uniform::HINT_SOURCE_COLOR && new_hint != ShaderNode::Uniform::HINT_RANGE && new_hint != ShaderNode::Uniform::HINT_ENUM; + bool is_sampler_hint = new_hint != ShaderNode::Uniform::HINT_NONE && new_hint != ShaderNode::Uniform::HINT_SOURCE_COLOR && new_hint != ShaderNode::Uniform::HINT_RANGE && new_hint != ShaderNode::Uniform::HINT_ENUM && new_hint != ShaderNode::Uniform::HINT_FLAGS; if (((new_filter != FILTER_DEFAULT || new_repeat != REPEAT_DEFAULT) || is_sampler_hint) && !is_sampler_type(type)) { _set_error(RTR("This hint is only for sampler types.")); return ERR_PARSE_ERROR; @@ -10884,6 +10898,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ if (completion_base == DataType::TYPE_INT) { options.push_back("hint_range(0, 100, 1)"); options.push_back("hint_enum(\"Zero\", \"One\", \"Two\")"); + options.push_back("hint_flags(\"Flag1\", \"Flag2\")"); } else { options.push_back("hint_range(0.0, 1.0, 0.1)"); } diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 1b5df7e90f3c..ff1abb2b65ca 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -177,6 +177,7 @@ class ShaderLanguage { TK_HINT_SOURCE_COLOR, TK_HINT_RANGE, TK_HINT_ENUM, + TK_HINT_FLAGS, TK_HINT_INSTANCE_INDEX, TK_HINT_SCREEN_TEXTURE, TK_HINT_NORMAL_ROUGHNESS_TEXTURE, @@ -626,6 +627,7 @@ class ShaderLanguage { HINT_NONE, HINT_RANGE, HINT_ENUM, + HINT_FLAGS, HINT_SOURCE_COLOR, HINT_NORMAL, HINT_ROUGHNESS_NORMAL, @@ -664,7 +666,7 @@ class ShaderLanguage { TextureFilter filter = FILTER_DEFAULT; TextureRepeat repeat = REPEAT_DEFAULT; float hint_range[3]; - PackedStringArray hint_enum_names; + PackedStringArray hint_names; int instance_index = 0; String group; String subgroup;