summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/variant/variant.h4
-rw-r--r--core/variant/variant_call.cpp12
-rw-r--r--core/variant/variant_setget.cpp5
-rw-r--r--core/variant/variant_utility.cpp4
-rw-r--r--modules/csg/csg_shape.cpp22
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp1
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.cpp13
-rw-r--r--servers/rendering/renderer_rd/shaders/ssao.glsl11
-rw-r--r--servers/rendering/shader_language.cpp306
-rw-r--r--servers/rendering/shader_language.h4
10 files changed, 218 insertions, 164 deletions
diff --git a/core/variant/variant.h b/core/variant/variant.h
index b22488a877..d5649f8256 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -497,6 +497,7 @@ public:
static bool is_builtin_method_const(Variant::Type p_type, const StringName &p_method);
static bool is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method);
static void get_builtin_method_list(Variant::Type p_type, List<StringName> *p_list);
+ static int get_builtin_method_count(Variant::Type p_type);
void call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
Variant call(const StringName &p_method, const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant());
@@ -535,6 +536,7 @@ public:
static bool has_member(Variant::Type p_type, const StringName &p_member);
static Variant::Type get_member_type(Variant::Type p_type, const StringName &p_member);
static void get_member_list(Type p_type, List<StringName> *r_members);
+ static int get_member_count(Type p_type);
static ValidatedSetter get_member_validated_setter(Variant::Type p_type, const StringName &p_member);
static ValidatedGetter get_member_validated_getter(Variant::Type p_type, const StringName &p_member);
@@ -628,6 +630,7 @@ public:
static bool is_utility_function_vararg(const StringName &p_name);
static void get_utility_function_list(List<StringName> *r_functions);
+ static int get_utility_function_count();
//argsVariant call()
@@ -642,6 +645,7 @@ public:
void static_assign(const Variant &p_variant);
static void get_constants_for_type(Variant::Type p_type, List<StringName> *p_constants);
+ static int get_constants_count_for_type(Variant::Type p_type);
static bool has_constant(Variant::Type p_type, const StringName &p_value);
static Variant get_constant_value(Variant::Type p_type, const StringName &p_value, bool *r_valid = nullptr);
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index afe4f2702e..854c0c01ef 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -705,6 +705,11 @@ void Variant::get_builtin_method_list(Variant::Type p_type, List<StringName> *p_
}
}
+int Variant::get_builtin_method_count(Variant::Type p_type) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1);
+ return builtin_method_names[p_type].size();
+}
+
Variant::Type Variant::get_builtin_method_return_type(Variant::Type p_type, const StringName &p_method) {
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::NIL);
const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
@@ -799,6 +804,13 @@ void Variant::get_constants_for_type(Variant::Type p_type, List<StringName> *p_c
}
}
+int Variant::get_constants_count_for_type(Variant::Type p_type) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1);
+ _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type];
+
+ return cd.value.size() + cd.variant_value.size();
+}
+
bool Variant::has_constant(Variant::Type p_type, const StringName &p_value) {
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
_VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type];
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index 28cf8ef967..dd3e70fc6a 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -437,6 +437,11 @@ void Variant::get_member_list(Variant::Type p_type, List<StringName> *r_members)
}
}
+int Variant::get_member_count(Type p_type) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1);
+ return variant_setters_getters_names[p_type].size();
+}
+
Variant::ValidatedSetter Variant::get_member_validated_setter(Variant::Type p_type, const StringName &p_member) {
ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index d54e223a99..46359b80ce 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -1379,3 +1379,7 @@ void Variant::get_utility_function_list(List<StringName> *r_functions) {
r_functions->push_back(E->get());
}
}
+
+int Variant::get_utility_function_count() {
+ return utility_function_name_table.size();
+}
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 8f2ebc7232..376dfe5031 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -701,7 +701,7 @@ CSGPrimitive3D::CSGPrimitive3D() {
CSGBrush *CSGMesh3D::_build_brush() {
if (!mesh.is_valid()) {
- return nullptr;
+ return memnew(CSGBrush);
}
Vector<Vector3> vertices;
@@ -719,7 +719,7 @@ CSGBrush *CSGMesh3D::_build_brush() {
if (arrays.size() == 0) {
_make_dirty();
- ERR_FAIL_COND_V(arrays.size() == 0, nullptr);
+ ERR_FAIL_COND_V(arrays.size() == 0, memnew(CSGBrush));
}
Vector<Vector3> avertices = arrays[Mesh::ARRAY_VERTEX];
@@ -840,7 +840,7 @@ CSGBrush *CSGMesh3D::_build_brush() {
}
if (vertices.size() == 0) {
- return nullptr;
+ return memnew(CSGBrush);
}
return _create_brush_from_arrays(vertices, uvs, smooth, materials);
@@ -1502,7 +1502,7 @@ CSGBrush *CSGTorus3D::_build_brush() {
float max_radius = outer_radius;
if (min_radius == max_radius) {
- return nullptr; //sorry, can't
+ return memnew(CSGBrush); //sorry, can't
}
if (min_radius > max_radius) {
@@ -1721,7 +1721,7 @@ CSGBrush *CSGPolygon3D::_build_brush() {
// set our bounding box
if (polygon.size() < 3) {
- return nullptr;
+ return memnew(CSGBrush);
}
Vector<Point2> final_polygon = polygon;
@@ -1733,7 +1733,7 @@ CSGBrush *CSGPolygon3D::_build_brush() {
Vector<int> triangles = Geometry2D::triangulate_polygon(final_polygon);
if (triangles.size() < 3) {
- return nullptr;
+ return memnew(CSGBrush);
}
Path3D *path = nullptr;
@@ -1767,15 +1767,15 @@ CSGBrush *CSGPolygon3D::_build_brush() {
if (mode == MODE_PATH) {
if (!has_node(path_node)) {
- return nullptr;
+ return memnew(CSGBrush);
}
Node *n = get_node(path_node);
if (!n) {
- return nullptr;
+ return memnew(CSGBrush);
}
path = Object::cast_to<Path3D>(n);
if (!path) {
- return nullptr;
+ return memnew(CSGBrush);
}
if (path != path_cache) {
@@ -1793,10 +1793,10 @@ CSGBrush *CSGPolygon3D::_build_brush() {
}
curve = path->get_curve();
if (curve.is_null()) {
- return nullptr;
+ return memnew(CSGBrush);
}
if (curve->get_baked_length() <= 0) {
- return nullptr;
+ return memnew(CSGBrush);
}
}
CSGBrush *brush = memnew(CSGBrush);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index c9edaa3d37..e9bc67b053 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -5208,7 +5208,6 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
RENDER_TIMESTAMP("Process SSAO");
- //TODO clear when settings chenge to or from ultra
if (rb->ssao.ao_final.is_valid() && ssao_using_half_size != ssao_half_size) {
RD::get_singleton()->free(rb->ssao.depth);
RD::get_singleton()->free(rb->ssao.ao_deinterleaved);
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
index c6ea906ea9..ae392b7586 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
@@ -920,7 +920,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
if (adnode->datatype == SL::TYPE_STRUCT) {
declaration += _mkid(adnode->struct_name);
} else {
- declaration = _prestr(adnode->precision) + _typestr(adnode->datatype);
+ declaration += _prestr(adnode->precision) + _typestr(adnode->datatype);
}
for (int i = 0; i < adnode->declarations.size(); i++) {
if (i > 0) {
@@ -990,12 +990,13 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
if (anode->call_expression != nullptr) {
code += ".";
code += _dump_node_code(anode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning, false);
- }
-
- if (anode->index_expression != nullptr) {
+ } else if (anode->index_expression != nullptr) {
code += "[";
code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += "]";
+ } else if (anode->assign_expression != nullptr) {
+ code += "=";
+ code += _dump_node_code(anode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false);
}
if (anode->name == time_name) {
@@ -1233,8 +1234,10 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
code += "[";
code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += "]";
+ } else if (mnode->assign_expression != nullptr) {
+ code += "=";
+ code += _dump_node_code(mnode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false);
}
-
} break;
}
diff --git a/servers/rendering/renderer_rd/shaders/ssao.glsl b/servers/rendering/renderer_rd/shaders/ssao.glsl
index f67965ab49..315ef8fa13 100644
--- a/servers/rendering/renderer_rd/shaders/ssao.glsl
+++ b/servers/rendering/renderer_rd/shaders/ssao.glsl
@@ -249,7 +249,6 @@ void SSAOTap(const int p_quality_level, inout float r_obscurance_sum, inout floa
SSAO_tap_inner(p_quality_level, r_obscurance_sum, r_weight_sum, sampling_mirrored_uv, mip_level, p_pix_center_pos, p_pixel_normal, p_fallof_sq, p_weight_mod);
}
-// this function is designed to only work with half/half depth at the moment - there's a couple of hardcoded paths that expect pixel/texel size, so it will not work for full res
void generate_SSAO_shadows_internal(out float r_shadow_term, out vec4 r_edges, out float r_weight, const vec2 p_pos, int p_quality_level, bool p_adaptive_base) {
vec2 pos_rounded = trunc(p_pos);
uvec2 upos = uvec2(pos_rounded);
@@ -257,8 +256,8 @@ void generate_SSAO_shadows_internal(out float r_shadow_term, out vec4 r_edges, o
const int number_of_taps = (p_adaptive_base) ? (SSAO_ADAPTIVE_TAP_BASE_COUNT) : (num_taps[p_quality_level]);
float pix_z, pix_left_z, pix_top_z, pix_right_z, pix_bottom_z;
- vec4 valuesUL = textureGather(source_depth_mipmaps, vec3(pos_rounded * params.half_screen_pixel_size, params.pass)); // g_ViewspaceDepthSource.GatherRed(g_PointMirrorSampler, pos_rounded * params.half_screen_pixel_size);
- vec4 valuesBR = textureGather(source_depth_mipmaps, vec3((pos_rounded + vec2(1.0)) * params.half_screen_pixel_size, params.pass)); // g_ViewspaceDepthSource.GatherRed(g_PointMirrorSampler, pos_rounded * params.half_screen_pixel_size, ivec2(1, 1));
+ vec4 valuesUL = textureGather(source_depth_mipmaps, vec3(pos_rounded * params.half_screen_pixel_size, params.pass));
+ vec4 valuesBR = textureGather(source_depth_mipmaps, vec3((pos_rounded + vec2(1.0)) * params.half_screen_pixel_size, params.pass));
// get this pixel's viewspace depth
pix_z = valuesUL.y;
@@ -276,8 +275,7 @@ void generate_SSAO_shadows_internal(out float r_shadow_term, out vec4 r_edges, o
uvec2 full_res_coord = upos * 2 * params.size_multiplier + params.pass_coord_offset.xy;
vec3 pixel_normal = load_normal(ivec2(full_res_coord));
- //const vec2 pixel_size_at_center = pix_center_pos.z * params.NDC_to_view_mul * params.half_screen_pixel_size; // optimized approximation of:
- vec2 pixel_size_at_center = NDC_to_view_space(normalized_screen_pos.xy + params.half_screen_pixel_size * 0.5, pix_center_pos.z).xy - pix_center_pos.xy;
+ const vec2 pixel_size_at_center = NDC_to_view_space(normalized_screen_pos.xy + params.half_screen_pixel_size, pix_center_pos.z).xy - pix_center_pos.xy;
float pixel_lookup_radius;
float fallof_sq;
@@ -440,9 +438,6 @@ void generate_SSAO_shadows_internal(out float r_shadow_term, out vec4 r_edges, o
fade_out *= clamp(1.0 - edge_fadeout_factor, 0.0, 1.0);
}
- // same as a bove, but a lot more conservative version
- // fade_out *= clamp( dot( edgesLRTB, vec4( 0.9, 0.9, 0.9, 0.9 ) ) - 2.6 , 0.0, 1.0);
-
// strength
obscurance = params.intensity * obscurance;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 3b73f6a8d6..c6eef48dfa 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -913,6 +913,7 @@ void ShaderLanguage::clear() {
char_idx = 0;
error_set = false;
error_str = "";
+ last_const = false;
while (nodes) {
Node *n = nodes;
nodes = nodes->next;
@@ -3252,6 +3253,137 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa
ERR_FAIL_V(false); //bug? function not found
}
+ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size) {
+ DataType type = TYPE_VOID;
+ String struct_name = "";
+ int array_size = 0;
+ bool auto_size = false;
+ Token tk = _get_token();
+
+ if (tk.type == TK_CURLY_BRACKET_OPEN) {
+ auto_size = true;
+ } else {
+ if (shader->structs.has(tk.text)) {
+ type = TYPE_STRUCT;
+ struct_name = tk.text;
+ } else {
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_error("Invalid data type for array");
+ return nullptr;
+ }
+ type = get_token_datatype(tk.type);
+ }
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ TkPos pos = _get_tkpos();
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_CLOSE) {
+ array_size = p_array_size;
+ tk = _get_token();
+ } else {
+ _set_tkpos(pos);
+
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+
+ ConstantNode *cnode = (ConstantNode *)n;
+ if (cnode->values.size() == 1) {
+ array_size = cnode->values[0].sint;
+ if (array_size <= 0) {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+ } else {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return nullptr;
+ } else {
+ tk = _get_token();
+ }
+ }
+ } else {
+ _set_error("Expected '['");
+ return nullptr;
+ }
+
+ if (type != p_type || struct_name != p_struct_name || array_size != p_array_size) {
+ String error_str = "Cannot convert from '";
+ if (type == TYPE_STRUCT) {
+ error_str += struct_name;
+ } else {
+ error_str += get_datatype_name(type);
+ }
+ error_str += "[";
+ error_str += itos(array_size);
+ error_str += "]'";
+ error_str += " to '";
+ if (type == TYPE_STRUCT) {
+ error_str += p_struct_name;
+ } else {
+ error_str += get_datatype_name(p_type);
+ }
+ error_str += "[";
+ error_str += itos(p_array_size);
+ error_str += "]'";
+ _set_error(error_str);
+ return nullptr;
+ }
+ }
+
+ ArrayConstructNode *an = alloc_node<ArrayConstructNode>();
+ an->datatype = p_type;
+ an->struct_name = p_struct_name;
+
+ if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization
+ while (true) {
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n) {
+ return nullptr;
+ }
+
+ if (p_type != n->get_datatype() || p_struct_name != n->get_datatype_name()) {
+ _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (type == TYPE_STRUCT ? struct_name : get_datatype_name(type)) + "'");
+ return nullptr;
+ }
+
+ tk = _get_token();
+ if (tk.type == TK_COMMA) {
+ an->initializer.push_back(n);
+ } else if (!auto_size && tk.type == TK_PARENTHESIS_CLOSE) {
+ an->initializer.push_back(n);
+ break;
+ } else if (auto_size && tk.type == TK_CURLY_BRACKET_CLOSE) {
+ an->initializer.push_back(n);
+ break;
+ } else {
+ if (auto_size) {
+ _set_error("Expected '}' or ','");
+ } else {
+ _set_error("Expected ')' or ','");
+ }
+ return nullptr;
+ }
+ }
+ if (an->initializer.size() != p_array_size) {
+ _set_error("Array size mismatch");
+ return nullptr;
+ }
+ } else {
+ _set_error("Expected array initialization!");
+ return nullptr;
+ }
+
+ return an;
+}
+
ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info) {
Vector<Expression> expression;
@@ -3395,142 +3527,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
Node *nexpr;
if (pstruct->members[i]->array_size != 0) {
- DataType type = pstruct->members[i]->get_datatype();
- String struct_name = pstruct->members[i]->struct_name;
- int array_size = pstruct->members[i]->array_size;
-
- DataType type2;
- String struct_name2 = "";
- int array_size2 = 0;
-
- bool auto_size = false;
-
- tk = _get_token();
-
- if (tk.type == TK_CURLY_BRACKET_OPEN) {
- auto_size = true;
- } else {
- if (shader->structs.has(tk.text)) {
- type2 = TYPE_STRUCT;
- struct_name2 = tk.text;
- } else {
- if (!is_token_variable_datatype(tk.type)) {
- _set_error("Invalid data type for array");
- return nullptr;
- }
- type2 = get_token_datatype(tk.type);
- }
-
- tk = _get_token();
- if (tk.type == TK_BRACKET_OPEN) {
- TkPos pos2 = _get_tkpos();
- tk = _get_token();
- if (tk.type == TK_BRACKET_CLOSE) {
- array_size2 = array_size;
- tk = _get_token();
- } else {
- _set_tkpos(pos2);
-
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
- _set_error("Expected single integer constant > 0");
- return nullptr;
- }
-
- ConstantNode *cnode = (ConstantNode *)n;
- if (cnode->values.size() == 1) {
- array_size2 = cnode->values[0].sint;
- if (array_size2 <= 0) {
- _set_error("Expected single integer constant > 0");
- return nullptr;
- }
- } else {
- _set_error("Expected single integer constant > 0");
- return nullptr;
- }
-
- tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return nullptr;
- } else {
- tk = _get_token();
- }
- }
- } else {
- _set_error("Expected '['");
- return nullptr;
- }
-
- if (type != type2 || struct_name != struct_name2 || array_size != array_size2) {
- String error_str = "Cannot convert from '";
- if (type2 == TYPE_STRUCT) {
- error_str += struct_name2;
- } else {
- error_str += get_datatype_name(type2);
- }
- error_str += "[";
- error_str += itos(array_size2);
- error_str += "]'";
- error_str += " to '";
- if (type == TYPE_STRUCT) {
- error_str += struct_name;
- } else {
- error_str += get_datatype_name(type);
- }
- error_str += "[";
- error_str += itos(array_size);
- error_str += "]'";
- _set_error(error_str);
- return nullptr;
- }
- }
-
- ArrayConstructNode *an = alloc_node<ArrayConstructNode>();
- an->datatype = type;
- an->struct_name = struct_name;
-
- if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization
- while (true) {
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (!n) {
- return nullptr;
- }
-
- if (type != n->get_datatype() || struct_name != n->get_datatype_name()) {
- _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (type == TYPE_STRUCT ? struct_name : get_datatype_name(type)) + "'");
- return nullptr;
- }
-
- tk = _get_token();
- if (tk.type == TK_COMMA) {
- an->initializer.push_back(n);
- continue;
- } else if (!auto_size && tk.type == TK_PARENTHESIS_CLOSE) {
- an->initializer.push_back(n);
- break;
- } else if (auto_size && tk.type == TK_CURLY_BRACKET_CLOSE) {
- an->initializer.push_back(n);
- break;
- } else {
- if (auto_size) {
- _set_error("Expected '}' or ','");
- } else {
- _set_error("Expected ')' or ','");
- }
- return nullptr;
- }
- }
- if (an->initializer.size() != array_size) {
- _set_error("Array size mismatch");
- return nullptr;
- }
- } else {
- _set_error("Expected array initialization!");
+ nexpr = _parse_array_constructor(p_block, p_function_info, pstruct->members[i]->get_datatype(), pstruct->members[i]->struct_name, pstruct->members[i]->array_size);
+ if (!nexpr) {
return nullptr;
}
-
- nexpr = an;
} else {
nexpr = _parse_and_reduce_expression(p_block, p_function_info);
if (!nexpr) {
@@ -3733,6 +3733,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
} else {
//an identifier
+ last_const = false;
_set_tkpos(pos);
DataType data_type;
@@ -3760,6 +3761,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("Unknown identifier in expression: " + String(identifier));
return nullptr;
}
+ last_const = is_const;
if (ident_type == IDENTIFIER_FUNCTION) {
_set_error("Can't use function as identifier: " + String(identifier));
@@ -3769,16 +3771,30 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
Node *index_expression = nullptr;
Node *call_expression = nullptr;
+ Node *assign_expression = nullptr;
if (array_size > 0) {
tk = _get_token();
- if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD) {
- _set_error("Expected '[' or '.'");
+ if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD && tk.type != TK_OP_ASSIGN) {
+ _set_error("Expected '[','.' or '='");
return nullptr;
}
- if (tk.type == TK_PERIOD) {
+ if (tk.type == TK_OP_ASSIGN) {
+ if (is_const) {
+ _set_error("Constants cannot be modified.");
+ 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);
+ if (!assign_expression) {
+ return nullptr;
+ }
+ } else if (tk.type == TK_PERIOD) {
completion_class = TAG_ARRAY;
p_block->block_tag = SubClassTag::TAG_ARRAY;
call_expression = _parse_and_reduce_expression(p_block, p_function_info);
@@ -3825,6 +3841,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
arrname->struct_name = struct_name;
arrname->index_expression = index_expression;
arrname->call_expression = call_expression;
+ arrname->assign_expression = assign_expression;
arrname->is_const = is_const;
expr = arrname;
@@ -4165,7 +4182,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (array_size > 0) {
tk = _get_token();
- if (tk.type == TK_PERIOD) {
+ if (tk.type == TK_OP_ASSIGN) {
+ if (last_const) {
+ last_const = false;
+ _set_error("Constants cannot be modified.");
+ return nullptr;
+ }
+ Node *assign_expression = _parse_array_constructor(p_block, p_function_info, member_type, member_struct_name, array_size);
+ if (!assign_expression) {
+ return nullptr;
+ }
+ mn->assign_expression = assign_expression;
+ } else if (tk.type == TK_PERIOD) {
_set_error("Nested array length() is not yet implemented");
return nullptr;
} else if (tk.type == TK_BRACKET_OPEN) {
@@ -4200,7 +4228,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
mn->index_expression = index_expression;
} else {
- _set_error("Expected '[' or '.'");
+ _set_error("Expected '[','.' or '='");
return nullptr;
}
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 61bd83bc72..d8fc316f47 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -414,6 +414,7 @@ public:
StringName name;
Node *index_expression = nullptr;
Node *call_expression = nullptr;
+ Node *assign_expression = nullptr;
bool is_const = false;
virtual DataType get_datatype() const { return datatype_cache; }
@@ -528,6 +529,7 @@ public:
StringName name;
Node *owner = nullptr;
Node *index_expression = nullptr;
+ Node *assign_expression = nullptr;
bool has_swizzling_duplicates = false;
virtual DataType get_datatype() const { return datatype; }
@@ -776,6 +778,7 @@ private:
int tk_line;
StringName current_function;
+ bool last_const = false;
struct TkPos {
int char_idx;
@@ -863,6 +866,7 @@ private:
bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin);
Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info);
+ Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size);
ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node);
Node *_parse_and_reduce_expression(BlockNode *p_block, const FunctionInfo &p_function_info);