diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 1783ef45255..d4fb8d98b05 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -2306,24 +2306,54 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const { return false; } -bool ShaderLanguage::_validate_assign(Node *p_node, const Map &p_builtin_types) { +bool ShaderLanguage::_validate_assign(Node *p_node, const Map &p_builtin_types, String *r_message) { if (p_node->type == Node::TYPE_OPERATOR) { OperatorNode *op = static_cast(p_node); - if (op->op == OP_INDEX) { - return _validate_assign(op->arguments[0], p_builtin_types); - } - } - if (p_node->type == Node::TYPE_VARIABLE) { + 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; + } + + } else if (p_node->type == Node::TYPE_MEMBER) { + + MemberNode *member = static_cast(p_node); + return _validate_assign(member->owner, p_builtin_types, r_message); + + } else if (p_node->type == Node::TYPE_VARIABLE) { VariableNode *var = static_cast(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 &p_builtin_types) { @@ -3090,10 +3120,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) { diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 9b84c5f195b..b5fd567c07a 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -617,7 +617,7 @@ private: bool _find_identifier(const BlockNode *p_block, const Map &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL); bool _is_operator_assign(Operator p_op) const; - bool _validate_assign(Node *p_node, const Map &p_builtin_types); + bool _validate_assign(Node *p_node, const Map &p_builtin_types, String *r_message = NULL); bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL);