diff options
| -rw-r--r-- | core/variant/variant.h | 4 | ||||
| -rw-r--r-- | core/variant/variant_call.cpp | 12 | ||||
| -rw-r--r-- | core/variant/variant_setget.cpp | 5 | ||||
| -rw-r--r-- | core/variant/variant_utility.cpp | 4 | ||||
| -rw-r--r-- | modules/csg/csg_shape.cpp | 22 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_scene_render_rd.cpp | 1 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shader_compiler_rd.cpp | 13 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/ssao.glsl | 11 | ||||
| -rw-r--r-- | servers/rendering/shader_language.cpp | 306 | ||||
| -rw-r--r-- | servers/rendering/shader_language.h | 4 | 
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);  |