diff options
Diffstat (limited to 'servers/visual/shader_language.cpp')
-rw-r--r-- | servers/visual/shader_language.cpp | 250 |
1 files changed, 214 insertions, 36 deletions
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index d399c548f3..eb0784c6b4 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -123,6 +123,12 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "TYPE_SAMPLER2D", "TYPE_ISAMPLER2D", "TYPE_USAMPLER2D", + "TYPE_SAMPLER2DARRAY", + "TYPE_ISAMPLER2DARRAY", + "TYPE_USAMPLER2DARRAY", + "TYPE_SAMPLER3D", + "TYPE_ISAMPLER3D", + "TYPE_USAMPLER3D", "TYPE_SAMPLERCUBE", "INTERPOLATION_FLAT", "INTERPOLATION_NO_PERSPECTIVE", @@ -257,6 +263,12 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_TYPE_SAMPLER2D, "sampler2D" }, { TK_TYPE_ISAMPLER2D, "isampler2D" }, { TK_TYPE_USAMPLER2D, "usampler2D" }, + { TK_TYPE_SAMPLER2DARRAY, "sampler2DArray" }, + { TK_TYPE_ISAMPLER2DARRAY, "isampler2DArray" }, + { TK_TYPE_USAMPLER2DARRAY, "usampler2DArray" }, + { TK_TYPE_SAMPLER3D, "sampler3D" }, + { TK_TYPE_ISAMPLER3D, "isampler3D" }, + { TK_TYPE_USAMPLER3D, "usampler3D" }, { TK_TYPE_SAMPLERCUBE, "samplerCube" }, { TK_INTERPOLATION_FLAT, "flat" }, { TK_INTERPOLATION_NO_PERSPECTIVE, "noperspective" }, @@ -612,6 +624,8 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { } ERR_PRINT("BUG"); return Token(); + +#undef GETCHAR } String ShaderLanguage::token_debug(const String &p_code) { @@ -658,6 +672,12 @@ bool ShaderLanguage::is_token_datatype(TokenType p_type) { p_type == TK_TYPE_SAMPLER2D || p_type == TK_TYPE_ISAMPLER2D || p_type == TK_TYPE_USAMPLER2D || + p_type == TK_TYPE_SAMPLER2DARRAY || + p_type == TK_TYPE_ISAMPLER2DARRAY || + p_type == TK_TYPE_USAMPLER2DARRAY || + p_type == TK_TYPE_SAMPLER3D || + p_type == TK_TYPE_ISAMPLER3D || + p_type == TK_TYPE_USAMPLER3D || p_type == TK_TYPE_SAMPLERCUBE); } @@ -729,6 +749,12 @@ String ShaderLanguage::get_datatype_name(DataType p_type) { case TYPE_SAMPLER2D: return "sampler2D"; case TYPE_ISAMPLER2D: return "isampler2D"; case TYPE_USAMPLER2D: return "usampler2D"; + case TYPE_SAMPLER2DARRAY: return "sampler2DArray"; + case TYPE_ISAMPLER2DARRAY: return "isampler2DArray"; + case TYPE_USAMPLER2DARRAY: return "usampler2DArray"; + case TYPE_SAMPLER3D: return "sampler3D"; + case TYPE_ISAMPLER3D: return "isampler3D"; + case TYPE_USAMPLER3D: return "usampler3D"; case TYPE_SAMPLERCUBE: return "samplerCube"; } @@ -1376,6 +1402,15 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID } }, { "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID } }, + //conversion between matrixes + + { "mat2", TYPE_MAT2, { TYPE_MAT3, TYPE_VOID } }, + { "mat2", TYPE_MAT2, { TYPE_MAT4, TYPE_VOID } }, + { "mat3", TYPE_MAT3, { TYPE_MAT2, TYPE_VOID } }, + { "mat3", TYPE_MAT3, { TYPE_MAT4, TYPE_VOID } }, + { "mat4", TYPE_MAT4, { TYPE_MAT2, TYPE_VOID } }, + { "mat4", TYPE_MAT4, { TYPE_MAT3, TYPE_VOID } }, + //builtins - trigonometry { "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, @@ -1625,14 +1660,14 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "smoothstep", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC4, TYPE_VOID } }, { "isnan", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID } }, - { "isnan", TYPE_BOOL, { TYPE_VEC2, TYPE_VOID } }, - { "isnan", TYPE_BOOL, { TYPE_VEC3, TYPE_VOID } }, - { "isnan", TYPE_BOOL, { TYPE_VEC4, TYPE_VOID } }, + { "isnan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID } }, + { "isnan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID } }, + { "isnan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID } }, { "isinf", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID } }, - { "isinf", TYPE_BOOL, { TYPE_VEC2, TYPE_VOID } }, - { "isinf", TYPE_BOOL, { TYPE_VEC3, TYPE_VOID } }, - { "isinf", TYPE_BOOL, { TYPE_VEC4, TYPE_VOID } }, + { "isinf", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID } }, + { "isinf", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID } }, + { "isinf", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID } }, { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID } }, { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID } }, @@ -1791,6 +1826,12 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID } }, { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID } }, { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID } }, { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID } }, { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID } }, @@ -1802,6 +1843,24 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID } }, { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + + { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } }, + { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + + { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } }, + { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + + { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID } }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + + { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID } }, + { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + + { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID } }, + { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID } }, { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, @@ -1820,15 +1879,38 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } }, + { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID } }, + { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } }, + + { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID } }, + { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } }, + + { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID } }, + { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } }, { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } }, { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } }, { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } }, { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } }, + { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } }, + { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } }, + { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } }, + + { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } }, + { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } }, + { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } }, + { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } }, @@ -1841,6 +1923,12 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } }, { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } }, { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } }, + { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } }, + { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } }, + { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } }, + { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } }, + { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } }, + { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } }, { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } }, { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } }, @@ -2128,7 +2216,16 @@ bool ShaderLanguage::is_scalar_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_SAMPLERCUBE; + 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; } void ShaderLanguage::get_keyword_list(List<String> *r_keywords) { @@ -2295,24 +2392,54 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const { return false; } -bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types) { +bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message) { if (p_node->type == Node::TYPE_OPERATOR) { OperatorNode *op = static_cast<OperatorNode *>(p_node); - if (op->type == OP_INDEX) { - return _validate_assign(op->arguments[0], p_builtin_types); + + if (op->op == OP_INDEX) { + return _validate_assign(op->arguments[0], p_builtin_types, r_message); + + } else if (_is_operator_assign(op->op)) { + //chained assignment + return _validate_assign(op->arguments[1], p_builtin_types, r_message); + + } else if (op->op == OP_CALL) { + if (r_message) + *r_message = RTR("Assignment to function."); + return false; } - } - if (p_node->type == Node::TYPE_VARIABLE) { + } else if (p_node->type == Node::TYPE_MEMBER) { + + MemberNode *member = static_cast<MemberNode *>(p_node); + return _validate_assign(member->owner, p_builtin_types, r_message); + + } else if (p_node->type == Node::TYPE_VARIABLE) { VariableNode *var = static_cast<VariableNode *>(p_node); - if (p_builtin_types.has(var->name) && p_builtin_types[var->name].constant) { - return false; //ops not valid + + if (shader->uniforms.has(var->name)) { + if (r_message) + *r_message = RTR("Assignment to uniform."); + return false; + } + + if (shader->varyings.has(var->name) && current_function != String("vertex")) { + if (r_message) + *r_message = RTR("Varyings can only be assigned in vertex function."); + return false; + } + + if (!(p_builtin_types.has(var->name) && p_builtin_types[var->name].constant)) { + return true; } } - return true; + + if (r_message) + *r_message = "Assignment to constant expression."; + return false; } ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) { @@ -2460,7 +2587,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons //add to current function as dependency for (int j = 0; j < shader->functions.size(); j++) { if (shader->functions[j].name == current_function) { - shader->functions[j].uses_function.insert(name); + shader->functions.write[j].uses_function.insert(name); break; } } @@ -2545,7 +2672,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons TkPos pos = _get_tkpos(); tk = _get_token(); - if (tk.type == TK_PERIOD) { + if (tk.type == TK_CURSOR) { + //do nothing + } else if (tk.type == TK_PERIOD) { StringName identifier; if (_get_completable_identifier(p_block, COMPLETION_INDEX, identifier)) { @@ -3008,8 +3137,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } op->arguments.push_back(expression[i + 1].node); - expression[i].is_op = false; - expression[i].node = op; + expression.write[i].is_op = false; + expression.write[i].node = op; if (!_validate_operator(op, &op->return_cache)) { @@ -3043,8 +3172,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons op->arguments.push_back(expression[next_op + 1].node); op->arguments.push_back(expression[next_op + 3].node); - expression[next_op - 1].is_op = false; - expression[next_op - 1].node = op; + expression.write[next_op - 1].is_op = false; + expression.write[next_op - 1].node = op; if (!_validate_operator(op, &op->return_cache)) { String at; @@ -3077,10 +3206,14 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons ERR_FAIL_V(NULL); } - if (_is_operator_assign(op->op) && !_validate_assign(expression[next_op - 1].node, p_builtin_types)) { + if (_is_operator_assign(op->op)) { - _set_error("Assignment to constant expression."); - return NULL; + String assign_message; + if (!_validate_assign(expression[next_op - 1].node, p_builtin_types, &assign_message)) { + + _set_error(assign_message); + return NULL; + } } if (expression[next_op + 1].is_op) { @@ -3094,7 +3227,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons op->arguments.push_back(expression[next_op - 1].node); //expression goes as left op->arguments.push_back(expression[next_op + 1].node); //next expression goes as right - expression[next_op - 1].node = op; + expression.write[next_op - 1].node = op; //replace all 3 nodes by this operator and make it an expression @@ -3136,7 +3269,7 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha for (int i = 1; i < op->arguments.size(); i++) { - op->arguments[i] = _reduce_expression(p_block, op->arguments[i]); + op->arguments.write[i] = _reduce_expression(p_block, op->arguments[i]); if (op->arguments[i]->type == Node::TYPE_CONSTANT) { ConstantNode *cn = static_cast<ConstantNode *>(op->arguments[i]); @@ -3176,7 +3309,7 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha return cn; } else if (op->op == OP_NEGATE) { - op->arguments[0] = _reduce_expression(p_block, op->arguments[0]); + op->arguments.write[0] = _reduce_expression(p_block, op->arguments[0]); if (op->arguments[0]->type == Node::TYPE_CONSTANT) { ConstantNode *cn = static_cast<ConstantNode *>(op->arguments[0]); @@ -3583,7 +3716,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui return OK; } -Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types) { +Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) { Token tk = _get_token(); @@ -3642,7 +3775,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - if (!p_render_modes.has(mode)) { + if (p_render_modes.find(mode) == -1) { _set_error("Invalid render mode: '" + String(mode) + "'"); return ERR_PARSE_ERROR; } @@ -4062,13 +4195,58 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return OK; } +// skips over whitespace and /* */ and // comments +static int _get_first_ident_pos(const String &p_code) { + + int idx = 0; + +#define GETCHAR(m_idx) (((idx + m_idx) < p_code.length()) ? p_code[idx + m_idx] : CharType(0)) + + while (true) { + if (GETCHAR(0) == '/' && GETCHAR(1) == '/') { + idx += 2; + while (true) { + if (GETCHAR(0) == 0) return 0; + if (GETCHAR(0) == '\n') { + idx++; + break; // loop + } + idx++; + } + } else if (GETCHAR(0) == '/' && GETCHAR(1) == '*') { + idx += 2; + while (true) { + if (GETCHAR(0) == 0) return 0; + if (GETCHAR(0) == '*' && GETCHAR(1) == '/') { + idx += 2; + break; // loop + } + idx++; + } + } else { + switch (GETCHAR(0)) { + case ' ': + case '\t': + case '\r': + case '\n': { + idx++; + } break; // switch + default: + return idx; + } + } + } + +#undef GETCHAR +} + String ShaderLanguage::get_shader_type(const String &p_code) { bool reading_type = false; String cur_identifier; - for (int i = 0; i < p_code.length(); i++) { + for (int i = _get_first_ident_pos(p_code); i < p_code.length(); i++) { if (p_code[i] == ';') { break; @@ -4097,7 +4275,7 @@ String ShaderLanguage::get_shader_type(const String &p_code) { return String(); } -Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types) { +Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) { clear(); @@ -4114,7 +4292,7 @@ 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 Set<String> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint) { +Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint) { clear(); @@ -4130,13 +4308,13 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct switch (completion_type) { case COMPLETION_NONE: { - //do none - return ERR_PARSE_ERROR; + //do nothing + return OK; } break; case COMPLETION_RENDER_MODE: { - for (const Set<String>::Element *E = p_render_modes.front(); E; E = E->next()) { + for (int i = 0; i < p_render_modes.size(); i++) { - r_options->push_back(E->get()); + r_options->push_back(p_render_modes[i]); } return OK; |