|
@@ -3102,6 +3102,72 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const {
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message) {
|
|
|
|
+ if (current_function == String("light")) {
|
|
|
|
+ *r_message = RTR("Varying may not be assigned in the 'light' function.");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ switch (p_varying.stage) {
|
|
|
|
+ case ShaderNode::Varying::STAGE_UNKNOWN: // first assign
|
|
|
|
+ if (current_function == String("vertex")) {
|
|
|
|
+ p_varying.stage = ShaderNode::Varying::STAGE_VERTEX;
|
|
|
|
+ } else if (current_function == String("fragment")) {
|
|
|
|
+ p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case ShaderNode::Varying::STAGE_VERTEX:
|
|
|
|
+ if (current_function == String("fragment")) {
|
|
|
|
+ *r_message = RTR("Varyings which assigned in 'vertex' function may not be reassigned in 'fragment' or 'light'.");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case ShaderNode::Varying::STAGE_FRAGMENT:
|
|
|
|
+ if (current_function == String("vertex")) {
|
|
|
|
+ *r_message = RTR("Varyings which assigned in 'fragment' function may not be reassigned in 'vertex' or 'light'.");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool ShaderLanguage::_validate_varying_using(ShaderNode::Varying &p_varying, String *r_message) {
|
|
|
|
+ switch (p_varying.stage) {
|
|
|
|
+ case ShaderNode::Varying::STAGE_UNKNOWN:
|
|
|
|
+ *r_message = RTR("Varying must be assigned before using!");
|
|
|
|
+ return false;
|
|
|
|
+ case ShaderNode::Varying::STAGE_VERTEX:
|
|
|
|
+ if (current_function == String("fragment")) {
|
|
|
|
+ p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT;
|
|
|
|
+ } else if (current_function == String("light")) {
|
|
|
|
+ p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case ShaderNode::Varying::STAGE_FRAGMENT:
|
|
|
|
+ if (current_function == String("light")) {
|
|
|
|
+ p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT:
|
|
|
|
+ if (current_function == String("light")) {
|
|
|
|
+ *r_message = RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT:
|
|
|
|
+ if (current_function == String("fragment")) {
|
|
|
|
+ *r_message = RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_function_info, String *r_message) {
|
|
bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_function_info, String *r_message) {
|
|
if (p_node->type == Node::TYPE_OPERATOR) {
|
|
if (p_node->type == Node::TYPE_OPERATOR) {
|
|
OperatorNode *op = static_cast<OperatorNode *>(p_node);
|
|
OperatorNode *op = static_cast<OperatorNode *>(p_node);
|
|
@@ -3142,13 +3208,6 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi
|
|
return false;
|
|
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 (shader->constants.has(var->name) || var->is_const) {
|
|
if (shader->constants.has(var->name) || var->is_const) {
|
|
if (r_message) {
|
|
if (r_message) {
|
|
*r_message = RTR("Constants cannot be modified.");
|
|
*r_message = RTR("Constants cannot be modified.");
|
|
@@ -3169,13 +3228,6 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
- if (shader->varyings.has(arr->name) && current_function != String("vertex")) {
|
|
|
|
- if (r_message) {
|
|
|
|
- *r_message = RTR("Varyings can only be assigned in vertex function.");
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3761,6 +3813,23 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
|
_set_error("Unknown identifier in expression: " + String(identifier));
|
|
_set_error("Unknown identifier in expression: " + String(identifier));
|
|
return nullptr;
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
+ if (ident_type == IDENTIFIER_VARYING) {
|
|
|
|
+ TkPos prev_pos = _get_tkpos();
|
|
|
|
+ Token next_token = _get_token();
|
|
|
|
+ _set_tkpos(prev_pos);
|
|
|
|
+ String error;
|
|
|
|
+ if (next_token.type == TK_OP_ASSIGN) {
|
|
|
|
+ if (!_validate_varying_assign(shader->varyings[identifier], &error)) {
|
|
|
|
+ _set_error(error);
|
|
|
|
+ return nullptr;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ if (!_validate_varying_using(shader->varyings[identifier], &error)) {
|
|
|
|
+ _set_error(error);
|
|
|
|
+ return nullptr;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
last_const = is_const;
|
|
last_const = is_const;
|
|
|
|
|
|
if (ident_type == IDENTIFIER_FUNCTION) {
|
|
if (ident_type == IDENTIFIER_FUNCTION) {
|
|
@@ -3786,10 +3855,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
|
_set_error("Constants cannot be modified.");
|
|
_set_error("Constants cannot be modified.");
|
|
return nullptr;
|
|
return nullptr;
|
|
}
|
|
}
|
|
- if (shader->varyings.has(identifier) && current_function != String("vertex")) {
|
|
|
|
- _set_error("Varyings can only be assigned in vertex function.");
|
|
|
|
- return nullptr;
|
|
|
|
- }
|
|
|
|
assign_expression = _parse_array_constructor(p_block, p_function_info, data_type, struct_name, array_size);
|
|
assign_expression = _parse_array_constructor(p_block, p_function_info, data_type, struct_name, array_size);
|
|
if (!assign_expression) {
|
|
if (!assign_expression) {
|
|
return nullptr;
|
|
return nullptr;
|
|
@@ -6260,6 +6325,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
|
return ERR_PARSE_ERROR;
|
|
return ERR_PARSE_ERROR;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ TkPos name_pos = _get_tkpos();
|
|
name = tk.text;
|
|
name = tk.text;
|
|
|
|
|
|
if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
|
|
if (_find_identifier(nullptr, false, FunctionInfo(), name)) {
|
|
@@ -6541,11 +6607,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
|
_set_error("Expected ';'");
|
|
_set_error("Expected ';'");
|
|
return ERR_PARSE_ERROR;
|
|
return ERR_PARSE_ERROR;
|
|
}
|
|
}
|
|
- } else {
|
|
|
|
|
|
+ } else { // varying
|
|
ShaderNode::Varying varying;
|
|
ShaderNode::Varying varying;
|
|
varying.type = type;
|
|
varying.type = type;
|
|
varying.precision = precision;
|
|
varying.precision = precision;
|
|
varying.interpolation = interpolation;
|
|
varying.interpolation = interpolation;
|
|
|
|
+ varying.tkpos = name_pos;
|
|
|
|
|
|
tk = _get_token();
|
|
tk = _get_token();
|
|
if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) {
|
|
if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) {
|
|
@@ -7158,6 +7225,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
|
tk = _get_token();
|
|
tk = _get_token();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ for (Map<StringName, ShaderNode::Varying>::Element *E = shader->varyings.front(); E; E = E->next()) {
|
|
|
|
+ if (E->get().stage == ShaderNode::Varying::STAGE_VERTEX || E->get().stage == ShaderNode::Varying::STAGE_FRAGMENT) {
|
|
|
|
+ _set_tkpos(E->get().tkpos);
|
|
|
|
+ _set_error(RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'"));
|
|
|
|
+ return ERR_PARSE_ERROR;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
return OK;
|
|
return OK;
|
|
}
|
|
}
|
|
|
|
|