diff options
Diffstat (limited to 'servers/rendering/shader_language.cpp')
-rw-r--r-- | servers/rendering/shader_language.cpp | 318 |
1 files changed, 211 insertions, 107 deletions
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 9c38bf7606..ca911d995a 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -88,7 +88,8 @@ String ShaderLanguage::get_operator_text(Operator p_op) { "--", "()", "construct", - "index" }; + "index", + "empty" }; return op_names[p_op]; } @@ -474,6 +475,10 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { case ':': return _make_token(TK_COLON); case '^': + if (GETCHAR(0) == '=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_BIT_XOR); + } return _make_token(TK_OP_BIT_XOR); case '~': return _make_token(TK_OP_BIT_INVERT); @@ -909,8 +914,10 @@ void ShaderLanguage::clear() { completion_type = COMPLETION_NONE; completion_block = nullptr; completion_function = StringName(); - completion_class = SubClassTag::TAG_GLOBAL; + completion_class = TAG_GLOBAL; completion_struct = StringName(); + completion_base = TYPE_VOID; + completion_base_array = false; unknown_varying_usages.clear(); @@ -2763,6 +2770,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI bool is_const = false; ConstantNode::Value value; + value.sint = -1; _find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, &is_const, nullptr, nullptr, &value); if (!is_const || value.sint < min || value.sint > max) { @@ -2993,7 +3001,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI } FunctionNode *pfunc = shader->functions[i].function; - if (arg_list == "") { + if (arg_list.is_empty()) { for (int j = 0; j < pfunc->arguments.size(); j++) { if (j > 0) { arg_list += ", "; @@ -3229,6 +3237,10 @@ bool ShaderLanguage::is_token_operator_assign(TokenType p_type) { p_type == TK_OP_ASSIGN_BIT_XOR); } +bool ShaderLanguage::is_token_hint(TokenType p_type) { + return int(p_type) > int(TK_RENDER_MODE) && int(p_type) < int(TK_SHADER_TYPE); +} + bool ShaderLanguage::convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value) { if (p_constant->datatype == p_to_type) { if (p_value) { @@ -3295,16 +3307,16 @@ bool ShaderLanguage::is_float_type(DataType p_type) { } bool ShaderLanguage::is_sampler_type(DataType p_type) { return p_type == TYPE_SAMPLER2D || - p_type == TYPE_ISAMPLER2D || - p_type == TYPE_USAMPLER2D || - p_type == TYPE_SAMPLER2DARRAY || - p_type == TYPE_ISAMPLER2DARRAY || - p_type == TYPE_USAMPLER2DARRAY || - p_type == TYPE_SAMPLER3D || - p_type == TYPE_ISAMPLER3D || - p_type == TYPE_USAMPLER3D || - p_type == TYPE_SAMPLERCUBE || - p_type == TYPE_SAMPLERCUBEARRAY; + p_type == TYPE_ISAMPLER2D || + p_type == TYPE_USAMPLER2D || + p_type == TYPE_SAMPLER2DARRAY || + p_type == TYPE_ISAMPLER2DARRAY || + p_type == TYPE_USAMPLER2DARRAY || + p_type == TYPE_SAMPLER3D || + p_type == TYPE_ISAMPLER3D || + p_type == TYPE_USAMPLER3D || + p_type == TYPE_SAMPLERCUBE || + p_type == TYPE_SAMPLERCUBEARRAY; } Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, int p_array_size, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) { @@ -3872,16 +3884,16 @@ void ShaderLanguage::get_keyword_list(List<String> *r_keywords) { bool ShaderLanguage::is_control_flow_keyword(String p_keyword) { return p_keyword == "break" || - p_keyword == "case" || - p_keyword == "continue" || - p_keyword == "default" || - p_keyword == "do" || - p_keyword == "else" || - p_keyword == "for" || - p_keyword == "if" || - p_keyword == "return" || - p_keyword == "switch" || - p_keyword == "while"; + p_keyword == "case" || + p_keyword == "continue" || + p_keyword == "default" || + p_keyword == "do" || + p_keyword == "else" || + p_keyword == "for" || + p_keyword == "if" || + p_keyword == "return" || + p_keyword == "switch" || + p_keyword == "while"; } void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) { @@ -4292,7 +4304,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_size(BlockNode *p_block, cons return n; } -Error ShaderLanguage::_parse_global_array_size(int &r_array_size) { +Error ShaderLanguage::_parse_global_array_size(int &r_array_size, const FunctionInfo &p_function_info) { if (r_array_size > 0) { _set_error("Array size is already defined!"); return ERR_PARSE_ERROR; @@ -4304,7 +4316,7 @@ Error ShaderLanguage::_parse_global_array_size(int &r_array_size) { if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) { _set_tkpos(pos); - Node *n = _parse_array_size(nullptr, FunctionInfo(), array_size); + Node *n = _parse_array_size(nullptr, p_function_info, array_size); if (!n) { return ERR_PARSE_ERROR; } @@ -4919,7 +4931,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons bool error = false; Node *n = func->arguments[argidx]; if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR) { - error = true; + if (!call_function->arguments[i].is_const) { + error = true; + } } else if (n->type == Node::TYPE_ARRAY) { ArrayNode *an = static_cast<ArrayNode *>(n); if (an->call_expression != nullptr || an->is_const) { @@ -5205,9 +5219,21 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expression.push_back(e); continue; } else { - _set_error("Expected expression, found: " + get_token_text(tk)); - return nullptr; - //nothing + if (tk.type != TK_SEMICOLON) { + _set_error("Expected expression, found: " + get_token_text(tk)); + return nullptr; + } else { +#if DEBUG_ENABLED + if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) { + _add_line_warning(ShaderWarning::FORMATTING_ERROR, "Empty statement. Remove ';' to fix this warning."); + } +#endif // DEBUG_ENABLED + _set_tkpos(prepos); + + OperatorNode *func = alloc_node<OperatorNode>(); + func->op = OP_EMPTY; + expr = func; + } } ERR_FAIL_COND_V(!expr, nullptr); @@ -6070,7 +6096,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons _set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at); return nullptr; } - expression.remove(i + 1); + expression.remove_at(i + 1); } } else if (is_ternary) { @@ -6110,7 +6136,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } for (int i = 0; i < 4; i++) { - expression.remove(next_op); + expression.remove_at(next_op); } } else { @@ -6171,8 +6197,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons return nullptr; } - expression.remove(next_op); - expression.remove(next_op); + expression.remove_at(next_op); + expression.remove_at(next_op); } } @@ -6383,7 +6409,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun ArrayDeclarationNode::Declaration adecl; if (tk.type != TK_IDENTIFIER && tk.type != TK_BRACKET_OPEN) { - _set_error("Expected identifier or '[' after type."); + _set_error("Expected identifier or '[' after datatype."); return ERR_PARSE_ERROR; } @@ -7187,11 +7213,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun //check return type BlockNode *b = p_block; - if (b && b->parent_function && p_function_info.main_function) { - _set_error(vformat("Using 'return' in '%s' processor function results in undefined behavior!", b->parent_function->name)); - return ERR_PARSE_ERROR; - } - while (b && !b->parent_function) { b = b->parent_block; } @@ -7201,6 +7222,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun return ERR_BUG; } + if (b && b->parent_function && p_function_info.main_function) { + _set_error(vformat("Using 'return' in '%s' processor function results in undefined behavior!", b->parent_function->name)); + return ERR_PARSE_ERROR; + } + String return_struct_name = String(b->parent_function->return_struct_name); String array_size_string; @@ -7216,7 +7242,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun if (tk.type == TK_SEMICOLON) { //all is good if (b->parent_function->return_type != TYPE_VOID) { - _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'"); + _set_error("Expected return with an expression of type '" + (!return_struct_name.is_empty() ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'"); return ERR_PARSE_ERROR; } } else { @@ -7228,7 +7254,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } if (b->parent_function->return_type != expr->get_datatype() || b->parent_function->return_array_size != expr->get_array_size() || return_struct_name != expr->get_datatype_name()) { - _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'"); + _set_error("Expected return with an expression of type '" + (!return_struct_name.is_empty() ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'"); return ERR_PARSE_ERROR; } @@ -7350,7 +7376,7 @@ String ShaderLanguage::_get_shader_type_list(const Set<String> &p_shader_types) // Return a list of shader types as an human-readable string String valid_types; for (const Set<String>::Element *E = p_shader_types.front(); E; E = E->next()) { - if (valid_types != String()) { + if (!valid_types.is_empty()) { valid_types += ", "; } @@ -7443,6 +7469,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL; stages = &p_functions; + const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo(); while (tk.type != TK_EOF) { switch (tk.type) { @@ -7486,7 +7513,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_IDENTIFIER) { st.name = tk.text; - if (shader->structs.has(st.name)) { + if (shader->constants.has(st.name) || shader->structs.has(st.name)) { _set_error("Redefinition of '" + String(st.name) + "'"); return ERR_PARSE_ERROR; } @@ -7558,7 +7585,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct int array_size = 0; if (tk.type == TK_BRACKET_OPEN) { - Error error = _parse_global_array_size(array_size); + Error error = _parse_global_array_size(array_size, constants); if (error != OK) { return error; } @@ -7585,7 +7612,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { - Error error = _parse_global_array_size(member->array_size); + Error error = _parse_global_array_size(member->array_size, constants); if (error != OK) { return error; } @@ -7644,7 +7671,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct bool uniform = tk.type == TK_UNIFORM; if (!uniform) { - if (shader_type_identifier == "particles" || shader_type_identifier == "sky") { + if (shader_type_identifier == "particles" || shader_type_identifier == "sky" || shader_type_identifier == "fog") { _set_error(vformat("Varyings cannot be used in '%s' shaders!", shader_type_identifier)); return ERR_PARSE_ERROR; } @@ -7712,7 +7739,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } if (tk.type == TK_BRACKET_OPEN) { - Error error = _parse_global_array_size(array_size); + Error error = _parse_global_array_size(array_size, constants); if (error != OK) { return error; } @@ -7727,7 +7754,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct prev_pos = _get_tkpos(); name = tk.text; - if (_find_identifier(nullptr, false, FunctionInfo(), name)) { + if (_find_identifier(nullptr, false, constants, name)) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; } @@ -7760,7 +7787,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { - Error error = _parse_global_array_size(uniform2.array_size); + Error error = _parse_global_array_size(uniform2.array_size, constants); if (error != OK) { return error; } @@ -7808,9 +7835,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct int custom_instance_index = -1; if (tk.type == TK_COLON) { + completion_type = COMPLETION_HINT; + completion_base = type; + completion_base_array = uniform2.array_size > 0; + //hint do { tk = _get_token(); + completion_line = tk.line; + + if (!is_token_hint(tk.type)) { + _set_error("Expected valid type hint after ':'."); + return ERR_PARSE_ERROR; + } if (uniform2.array_size > 0) { if (tk.type != TK_HINT_COLOR) { @@ -7980,8 +8017,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct uniform2.repeat = REPEAT_DISABLE; } else if (tk.type == TK_REPEAT_ENABLE) { uniform2.repeat = REPEAT_ENABLE; - } else { - _set_error("Expected valid type hint after ':'."); } if (uniform2.hint != ShaderNode::Uniform::HINT_RANGE && uniform2.hint != ShaderNode::Uniform::HINT_NONE && uniform2.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) { @@ -8014,7 +8049,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo()); + Node *expr = _parse_and_reduce_expression(nullptr, constants); if (!expr) { return ERR_PARSE_ERROR; } @@ -8048,6 +8083,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct _set_error("Expected ';'"); return ERR_PARSE_ERROR; } + + completion_type = COMPLETION_NONE; } else { // varying ShaderNode::Varying varying; varying.type = type; @@ -8110,7 +8147,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct DataPrecision precision = PRECISION_DEFAULT; DataType type; StringName name; - int return_array_size = 0; + int array_size = 0; if (tk.type == TK_CONST) { is_constant = true; @@ -8149,13 +8186,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct prev_pos = _get_tkpos(); tk = _get_token(); + bool unknown_size = false; + if (tk.type == TK_BRACKET_OPEN) { + if (is_constant && RenderingServer::get_singleton()->is_low_end()) { + _set_error("Global const arrays are only supported on high-end platform!"); + return ERR_PARSE_ERROR; + } bool error = false; tk = _get_token(); if (tk.type == TK_INT_CONSTANT) { - return_array_size = (int)tk.constant; - if (return_array_size > 0) { + array_size = (int)tk.constant; + if (array_size > 0) { tk = _get_token(); if (tk.type != TK_BRACKET_CLOSE) { _set_error("Expected ']'"); @@ -8164,11 +8207,13 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { error = true; } + } else if (tk.type == TK_BRACKET_CLOSE) { + unknown_size = true; } else { error = true; } if (error) { - _set_error("Expected integer constant > 0"); + _set_error("Expected integer constant > 0 or ']'"); return ERR_PARSE_ERROR; } @@ -8180,16 +8225,15 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct _get_completable_identifier(nullptr, COMPLETION_MAIN_FUNCTION, name); if (name == StringName()) { - _set_error("Expected function name after datatype"); - return ERR_PARSE_ERROR; - } - - if (_find_identifier(nullptr, false, FunctionInfo(), name)) { - _set_error("Redefinition of '" + String(name) + "'"); + if (is_constant) { + _set_error("Expected identifier or '[' after datatype."); + } else { + _set_error("Expected function name after datatype."); + } return ERR_PARSE_ERROR; } - if (has_builtin(p_functions, name)) { + if (shader->structs.has(name) || _find_identifier(nullptr, false, constants, name) || has_builtin(p_functions, name)) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; } @@ -8202,7 +8246,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } //variable - + bool first = true; while (true) { ShaderNode::Constant constant; constant.name = name; @@ -8210,16 +8254,18 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct constant.type_str = struct_name; constant.precision = precision; constant.initializer = nullptr; - constant.array_size = 0; - - bool unknown_size = false; + constant.array_size = (first ? array_size : 0); + first = false; if (tk.type == TK_BRACKET_OPEN) { if (RenderingServer::get_singleton()->is_low_end()) { - _set_error("Global const arrays are supported only on high-end platform!"); + _set_error("Global const arrays are only supported on high-end platform!"); + return ERR_PARSE_ERROR; + } + if (constant.array_size > 0 || unknown_size) { + _set_error("Array size is already defined!"); return ERR_PARSE_ERROR; } - tk = _get_token(); if (tk.type == TK_BRACKET_CLOSE) { unknown_size = true; @@ -8297,7 +8343,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { _set_tkpos(prev_pos); - Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo()); + Node *n = _parse_and_reduce_expression(nullptr, constants); if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { _set_error("Expected single integer constant > 0"); return ERR_PARSE_ERROR; @@ -8378,7 +8424,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization while (true) { - Node *n = _parse_and_reduce_expression(nullptr, FunctionInfo()); + Node *n = _parse_and_reduce_expression(nullptr, constants); if (!n) { return ERR_PARSE_ERROR; } @@ -8433,7 +8479,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct constant.initializer = static_cast<ConstantNode *>(expr); } else { //variable created with assignment! must parse an expression - Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo()); + Node *expr = _parse_and_reduce_expression(nullptr, constants); if (!expr) { return ERR_PARSE_ERROR; } @@ -8449,7 +8495,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct constant.initializer = static_cast<ConstantNode *>(expr); - if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), 0)) { + if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), expr->get_array_size())) { return ERR_PARSE_ERROR; } } @@ -8480,7 +8526,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } name = tk.text; - if (_find_identifier(nullptr, false, FunctionInfo(), name)) { + if (_find_identifier(nullptr, false, constants, name)) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; } @@ -8514,6 +8560,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } } + if (p_functions.has("constants")) { // Adds global constants: 'PI', 'TAU', 'E' + for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["constants"].built_ins) { + builtins.built_ins.insert(E.key, E.value); + } + } + ShaderNode::Function function; function.callable = !p_functions.has(name); @@ -8529,7 +8581,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct func_node->return_type = type; func_node->return_struct_name = struct_name; func_node->return_precision = precision; - func_node->return_array_size = return_array_size; + func_node->return_array_size = array_size; if (p_functions.has(name)) { func_node->can_discard = p_functions[name].can_discard; @@ -8583,7 +8635,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct StringName param_struct_name; DataPrecision pprecision = PRECISION_DEFAULT; bool use_precision = false; - int array_size = 0; + int arg_array_size = 0; if (is_token_precision(tk.type)) { pprecision = get_token_precision(tk.type); @@ -8634,9 +8686,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_INT_CONSTANT) { - array_size = (int)tk.constant; + arg_array_size = (int)tk.constant; - if (array_size > 0) { + if (arg_array_size > 0) { tk = _get_token(); if (tk.type != TK_BRACKET_CLOSE) { _set_error("Expected ']'"); @@ -8688,7 +8740,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_BRACKET_OPEN) { - if (array_size > 0) { + if (arg_array_size > 0) { _set_error("Array size is already defined!"); return ERR_PARSE_ERROR; } @@ -8696,9 +8748,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); if (tk.type == TK_INT_CONSTANT) { - array_size = (int)tk.constant; + arg_array_size = (int)tk.constant; - if (array_size > 0) { + if (arg_array_size > 0) { tk = _get_token(); if (tk.type != TK_BRACKET_CLOSE) { _set_error("Expected ']'"); @@ -8718,7 +8770,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); } - arg.array_size = array_size; + arg.array_size = arg_array_size; func_node->arguments.push_back(arg); if (tk.type == TK_COMMA) { @@ -8897,7 +8949,7 @@ String ShaderLanguage::get_shader_type(const String &p_code) { break; } else if (p_code[i] <= 32) { - if (cur_identifier != String()) { + if (!cur_identifier.is_empty()) { if (!reading_type) { if (cur_identifier != "shader_type") { return String(); @@ -8957,17 +9009,17 @@ uint32_t ShaderLanguage::get_warning_flags() const { } #endif // DEBUG_ENABLED -Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func) { +Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_info) { clear(); code = p_code; - global_var_get_type_func = p_global_variable_type_func; - varying_function_names = p_varying_function_names; + global_var_get_type_func = p_info.global_variable_type_func; + varying_function_names = p_info.varying_function_names; nodes = nullptr; shader = alloc_node<ShaderNode>(); - Error err = _parse_shader(p_functions, p_render_modes, p_shader_types); + Error err = _parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types); #ifdef DEBUG_ENABLED if (check_warnings) { @@ -8981,17 +9033,17 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Functi return OK; } -Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) { +Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) { clear(); code = p_code; - varying_function_names = p_varying_function_names; + varying_function_names = p_info.varying_function_names; nodes = nullptr; - global_var_get_type_func = p_global_variable_type_func; + global_var_get_type_func = p_info.global_variable_type_func; shader = alloc_node<ShaderNode>(); - _parse_shader(p_functions, p_render_modes, p_shader_types); + _parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types); switch (completion_type) { case COMPLETION_NONE: { @@ -8999,8 +9051,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct return OK; } break; case COMPLETION_RENDER_MODE: { - for (int i = 0; i < p_render_modes.size(); i++) { - ScriptCodeCompletionOption option(p_render_modes[i], ScriptCodeCompletionOption::KIND_ENUM); + for (int i = 0; i < p_info.render_modes.size(); i++) { + ScriptCodeCompletionOption option(p_info.render_modes[i], ScriptCodeCompletionOption::KIND_ENUM); r_options->push_back(option); } @@ -9018,7 +9070,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct return OK; } break; case COMPLETION_MAIN_FUNCTION: { - for (const KeyValue<StringName, FunctionInfo> &E : p_functions) { + for (const KeyValue<StringName, FunctionInfo> &E : p_info.functions) { ScriptCodeCompletionOption option(E.key, ScriptCodeCompletionOption::KIND_FUNCTION); r_options->push_back(option); } @@ -9054,8 +9106,8 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct } if (comp_ident) { - if (p_functions.has("global")) { - for (const KeyValue<StringName, BuiltInInfo> &E : p_functions["global"].built_ins) { + if (p_info.functions.has("global")) { + for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) { ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER; if (E.value.constant) { kind = ScriptCodeCompletionOption::KIND_CONSTANT; @@ -9064,8 +9116,18 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct } } - if (skip_function != StringName() && p_functions.has(skip_function)) { - for (const KeyValue<StringName, BuiltInInfo> &E : p_functions[skip_function].built_ins) { + if (p_info.functions.has("constants")) { + for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) { + ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER; + if (E.value.constant) { + kind = ScriptCodeCompletionOption::KIND_CONSTANT; + } + matches.insert(E.key, kind); + } + } + + if (skip_function != StringName() && p_info.functions.has(skip_function)) { + for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) { ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER; if (E.value.constant) { kind = ScriptCodeCompletionOption::KIND_CONSTANT; @@ -9369,15 +9431,6 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct limit = 4; } break; - case TYPE_MAT2: - limit = 2; - break; - case TYPE_MAT3: - limit = 3; - break; - case TYPE_MAT4: - limit = 4; - break; default: { } } @@ -9389,6 +9442,57 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct } } break; + case COMPLETION_HINT: { + if (completion_base == DataType::TYPE_VEC4) { + ScriptCodeCompletionOption option("hint_color", ScriptCodeCompletionOption::KIND_PLAIN_TEXT); + r_options->push_back(option); + } else if ((completion_base == DataType::TYPE_INT || completion_base == DataType::TYPE_FLOAT) && !completion_base_array) { + ScriptCodeCompletionOption option("hint_range", ScriptCodeCompletionOption::KIND_PLAIN_TEXT); + + if (completion_base == DataType::TYPE_INT) { + option.insert_text = "hint_range(0, 100, 1)"; + } else { + option.insert_text = "hint_range(0.0, 1.0, 0.1)"; + } + + r_options->push_back(option); + } else if ((int(completion_base) > int(TYPE_MAT4) && int(completion_base) < int(TYPE_STRUCT)) && !completion_base_array) { + static Vector<String> options; + + if (options.is_empty()) { + options.push_back("filter_linear"); + options.push_back("filter_linear_mipmap"); + options.push_back("filter_linear_mipmap_aniso"); + options.push_back("filter_nearest"); + options.push_back("filter_nearest_mipmap"); + options.push_back("filter_nearest_mipmap_aniso"); + options.push_back("hint_albedo"); + options.push_back("hint_aniso"); + options.push_back("hint_black"); + options.push_back("hint_black_albedo"); + options.push_back("hint_normal"); + options.push_back("hint_roughness_a"); + options.push_back("hint_roughness_b"); + options.push_back("hint_roughness_g"); + options.push_back("hint_roughness_gray"); + options.push_back("hint_roughness_normal"); + options.push_back("hint_roughness_r"); + options.push_back("hint_white"); + options.push_back("repeat_enable"); + options.push_back("repeat_disable"); + } + + for (int i = 0; i < options.size(); i++) { + ScriptCodeCompletionOption option(options[i], ScriptCodeCompletionOption::KIND_PLAIN_TEXT); + r_options->push_back(option); + } + } + if (!completion_base_array) { + ScriptCodeCompletionOption option("instance_index", ScriptCodeCompletionOption::KIND_PLAIN_TEXT); + option.insert_text = "instance_index(0)"; + r_options->push_back(option); + } + } break; } return ERR_PARSE_ERROR; |