mirror of
https://github.com/godotengine/godot.git
synced 2024-11-27 09:16:35 +08:00
Add hint_enum
for uniform int in gdshader
This commit is contained in:
parent
97b8ad1af0
commit
1052985b00
@ -15,6 +15,9 @@
|
||||
<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()">
|
||||
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="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>
|
||||
@ -38,7 +41,10 @@
|
||||
<constant name="HINT_RANGE_STEP" value="2" enum="Hint">
|
||||
The parameter's value must be within the specified range, with the given [member step] between values.
|
||||
</constant>
|
||||
<constant name="HINT_MAX" value="3" enum="Hint">
|
||||
<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">
|
||||
Represents the size of the [enum Hint] enum.
|
||||
</constant>
|
||||
</constants>
|
||||
|
@ -5368,6 +5368,20 @@ 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(";
|
||||
|
||||
bool first = true;
|
||||
for (const String &_name : hint_enum_names) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
code += ", ";
|
||||
}
|
||||
code += "\"" + _name.c_escape() + "\"";
|
||||
}
|
||||
|
||||
code += ")";
|
||||
} else {
|
||||
code += _get_qual_str() + "uniform int " + get_parameter_name();
|
||||
}
|
||||
@ -5439,6 +5453,18 @@ int VisualShaderNodeIntParameter::get_step() const {
|
||||
return hint_range_step;
|
||||
}
|
||||
|
||||
void VisualShaderNodeIntParameter::set_enum_names(const PackedStringArray &p_names) {
|
||||
if (hint_enum_names == p_names) {
|
||||
return;
|
||||
}
|
||||
hint_enum_names = p_names;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
PackedStringArray VisualShaderNodeIntParameter::get_enum_names() const {
|
||||
return hint_enum_names;
|
||||
}
|
||||
|
||||
void VisualShaderNodeIntParameter::set_default_value_enabled(bool p_default_value_enabled) {
|
||||
if (default_value_enabled == p_default_value_enabled) {
|
||||
return;
|
||||
@ -5476,22 +5502,27 @@ 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_default_value_enabled", "enabled"), &VisualShaderNodeIntParameter::set_default_value_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeIntParameter::is_default_value_enabled);
|
||||
|
||||
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"), "set_hint", "get_hint");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range + Step,Enum"), "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::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_ENUM);
|
||||
BIND_ENUM_CONSTANT(HINT_MAX);
|
||||
}
|
||||
|
||||
@ -5513,6 +5544,9 @@ Vector<StringName> VisualShaderNodeIntParameter::get_editable_properties() const
|
||||
if (hint == HINT_RANGE_STEP) {
|
||||
props.push_back("step");
|
||||
}
|
||||
if (hint == HINT_ENUM) {
|
||||
props.push_back("enum_names");
|
||||
}
|
||||
props.push_back("default_value_enabled");
|
||||
if (default_value_enabled) {
|
||||
props.push_back("default_value");
|
||||
|
@ -2115,6 +2115,7 @@ public:
|
||||
HINT_NONE,
|
||||
HINT_RANGE,
|
||||
HINT_RANGE_STEP,
|
||||
HINT_ENUM,
|
||||
HINT_MAX,
|
||||
};
|
||||
|
||||
@ -2123,6 +2124,7 @@ private:
|
||||
int hint_range_min = 0;
|
||||
int hint_range_max = 100;
|
||||
int hint_range_step = 1;
|
||||
PackedStringArray hint_enum_names;
|
||||
bool default_value_enabled = false;
|
||||
int default_value = 0;
|
||||
|
||||
@ -2158,6 +2160,9 @@ public:
|
||||
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_default_value_enabled(bool p_enabled);
|
||||
bool is_default_value_enabled() const;
|
||||
|
||||
|
@ -96,6 +96,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
|
||||
"FLOAT_CONSTANT",
|
||||
"INT_CONSTANT",
|
||||
"UINT_CONSTANT",
|
||||
"STRING_CONSTANT",
|
||||
"TYPE_VOID",
|
||||
"TYPE_BOOL",
|
||||
"TYPE_BVEC2",
|
||||
@ -212,6 +213,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
|
||||
"HINT_ANISOTROPY_TEXTURE",
|
||||
"HINT_SOURCE_COLOR",
|
||||
"HINT_RANGE",
|
||||
"HINT_ENUM",
|
||||
"HINT_INSTANCE_INDEX",
|
||||
"HINT_SCREEN_TEXTURE",
|
||||
"HINT_NORMAL_ROUGHNESS_TEXTURE",
|
||||
@ -365,6 +367,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_INSTANCE_INDEX, "instance_index", CF_UNSPECIFIED, {}, {} },
|
||||
|
||||
// sampler hints
|
||||
@ -512,7 +515,54 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
|
||||
return _make_token(TK_OP_NOT);
|
||||
|
||||
} break;
|
||||
//case '"' //string - no strings in shader
|
||||
case '"': {
|
||||
String _content = "";
|
||||
bool _previous_backslash = false;
|
||||
|
||||
while (true) {
|
||||
bool _ended = false;
|
||||
char32_t c = GETCHAR(0);
|
||||
if (c == 0) {
|
||||
return _make_token(TK_ERROR, "EOF reached before string termination.");
|
||||
}
|
||||
switch (c) {
|
||||
case '"': {
|
||||
if (_previous_backslash) {
|
||||
_content += '"';
|
||||
_previous_backslash = false;
|
||||
} else {
|
||||
_ended = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '\\': {
|
||||
if (_previous_backslash) {
|
||||
_content += '\\';
|
||||
}
|
||||
_previous_backslash = !_previous_backslash;
|
||||
break;
|
||||
}
|
||||
case '\n': {
|
||||
return _make_token(TK_ERROR, "Unexpected end of string.");
|
||||
}
|
||||
default: {
|
||||
if (!_previous_backslash) {
|
||||
_content += c;
|
||||
} else {
|
||||
return _make_token(TK_ERROR, "Only \\\" and \\\\ escape characters supported.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char_idx++;
|
||||
if (_ended) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return _make_token(TK_STRING_CONSTANT, _content);
|
||||
} break;
|
||||
//case '\'' //string - no strings in shader
|
||||
case '{':
|
||||
return _make_token(TK_CURLY_BRACKET_OPEN);
|
||||
@ -1120,6 +1170,9 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) {
|
||||
case ShaderNode::Uniform::HINT_RANGE: {
|
||||
result = "hint_range";
|
||||
} break;
|
||||
case ShaderNode::Uniform::HINT_ENUM: {
|
||||
result = "hint_enum";
|
||||
} break;
|
||||
case ShaderNode::Uniform::HINT_SOURCE_COLOR: {
|
||||
result = "source_color";
|
||||
} break;
|
||||
@ -4139,6 +4192,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) {
|
||||
pi.type = Variant::INT;
|
||||
pi.hint = PROPERTY_HINT_ENUM;
|
||||
String hint_string;
|
||||
pi.hint_string = String(",").join(p_uniform.hint_enum_names);
|
||||
} else {
|
||||
pi.type = Variant::INT;
|
||||
pi.hint = PROPERTY_HINT_RANGE;
|
||||
@ -8937,6 +8995,40 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
|
||||
|
||||
new_hint = ShaderNode::Uniform::HINT_RANGE;
|
||||
} break;
|
||||
case TK_HINT_ENUM: {
|
||||
if (type != TYPE_INT) {
|
||||
_set_error(vformat(RTR("Enum hint is for '%s' only."), "int"));
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
|
||||
tk = _get_token();
|
||||
if (tk.type != TK_PARENTHESIS_OPEN) {
|
||||
_set_expected_after_error("(", "hint_enum");
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
tk = _get_token();
|
||||
|
||||
if (tk.type != TK_STRING_CONSTANT) {
|
||||
_set_error(RTR("Expected a string constant."));
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
|
||||
uniform.hint_enum_names.push_back(tk.text);
|
||||
|
||||
tk = _get_token();
|
||||
|
||||
if (tk.type == TK_PARENTHESIS_CLOSE) {
|
||||
break;
|
||||
} else if (tk.type != TK_COMMA) {
|
||||
_set_error(RTR("Expected ',' or ')' after string constant."));
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
new_hint = ShaderNode::Uniform::HINT_ENUM;
|
||||
} break;
|
||||
case TK_HINT_INSTANCE_INDEX: {
|
||||
if (custom_instance_index != -1) {
|
||||
_set_error(vformat(RTR("Can only specify '%s' once."), "instance_index"));
|
||||
@ -9031,7 +9123,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (((new_filter != FILTER_DEFAULT || new_repeat != REPEAT_DEFAULT) || (new_hint != ShaderNode::Uniform::HINT_NONE && new_hint != ShaderNode::Uniform::HINT_SOURCE_COLOR && new_hint != ShaderNode::Uniform::HINT_RANGE)) && !is_sampler_type(type)) {
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
@ -10730,15 +10824,21 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
|
||||
}
|
||||
} else if ((completion_base == DataType::TYPE_INT || completion_base == DataType::TYPE_FLOAT) && !completion_base_array) {
|
||||
if (current_uniform_hint == ShaderNode::Uniform::HINT_NONE) {
|
||||
ScriptLanguage::CodeCompletionOption option("hint_range", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
|
||||
Vector<String> options;
|
||||
|
||||
if (completion_base == DataType::TYPE_INT) {
|
||||
option.insert_text = "hint_range(0, 100, 1)";
|
||||
options.push_back("hint_range(0, 100, 1)");
|
||||
options.push_back("hint_enum(\"Zero\", \"One\", \"Two\")");
|
||||
} else {
|
||||
option.insert_text = "hint_range(0.0, 1.0, 0.1)";
|
||||
options.push_back("hint_range(0.0, 1.0, 0.1)");
|
||||
}
|
||||
|
||||
r_options->push_back(option);
|
||||
for (const String &option_text : options) {
|
||||
String hint_name = option_text.substr(0, option_text.find_char(char32_t('(')));
|
||||
ScriptLanguage::CodeCompletionOption option(hint_name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
|
||||
option.insert_text = option_text;
|
||||
r_options->push_back(option);
|
||||
}
|
||||
}
|
||||
} else if ((int(completion_base) > int(TYPE_MAT4) && int(completion_base) < int(TYPE_STRUCT))) {
|
||||
Vector<String> options;
|
||||
|
@ -59,6 +59,7 @@ public:
|
||||
TK_FLOAT_CONSTANT,
|
||||
TK_INT_CONSTANT,
|
||||
TK_UINT_CONSTANT,
|
||||
TK_STRING_CONSTANT,
|
||||
TK_TYPE_VOID,
|
||||
TK_TYPE_BOOL,
|
||||
TK_TYPE_BVEC2,
|
||||
@ -175,6 +176,7 @@ public:
|
||||
TK_HINT_ANISOTROPY_TEXTURE,
|
||||
TK_HINT_SOURCE_COLOR,
|
||||
TK_HINT_RANGE,
|
||||
TK_HINT_ENUM,
|
||||
TK_HINT_INSTANCE_INDEX,
|
||||
TK_HINT_SCREEN_TEXTURE,
|
||||
TK_HINT_NORMAL_ROUGHNESS_TEXTURE,
|
||||
@ -659,6 +661,7 @@ public:
|
||||
enum Hint {
|
||||
HINT_NONE,
|
||||
HINT_RANGE,
|
||||
HINT_ENUM,
|
||||
HINT_SOURCE_COLOR,
|
||||
HINT_NORMAL,
|
||||
HINT_ROUGHNESS_NORMAL,
|
||||
@ -696,6 +699,7 @@ public:
|
||||
TextureFilter filter = FILTER_DEFAULT;
|
||||
TextureRepeat repeat = REPEAT_DEFAULT;
|
||||
float hint_range[3];
|
||||
PackedStringArray hint_enum_names;
|
||||
int instance_index = 0;
|
||||
String group;
|
||||
String subgroup;
|
||||
|
Loading…
Reference in New Issue
Block a user