diff options
-rw-r--r-- | doc/classes/VisualInstance3D.xml | 2 | ||||
-rw-r--r-- | editor/project_converter_3_to_4.cpp | 30 | ||||
-rw-r--r-- | editor/renames_map_3_to_4.cpp | 12 | ||||
-rw-r--r-- | modules/gdscript/gdscript_analyzer.cpp | 2 | ||||
-rw-r--r-- | modules/gdscript/gdscript_compiler.cpp | 36 | ||||
-rw-r--r-- | modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.gd | 20 | ||||
-rw-r--r-- | modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.out | 2 | ||||
-rw-r--r-- | modules/theora/video_stream_theora.cpp | 10 | ||||
-rw-r--r-- | servers/rendering/shader_preprocessor.cpp | 5 |
9 files changed, 84 insertions, 35 deletions
diff --git a/doc/classes/VisualInstance3D.xml b/doc/classes/VisualInstance3D.xml index 3781045c02..b2bc6709a0 100644 --- a/doc/classes/VisualInstance3D.xml +++ b/doc/classes/VisualInstance3D.xml @@ -62,7 +62,7 @@ For [Light3D]s, this can be used to control which [VisualInstance3D]s are affected by a specific light. For [GPUParticles3D], this can be used to control which particles are effected by a specific attractor. For [Decal]s, this can be used to control which [VisualInstance3D]s are affected by a specific decal. </member> <member name="sorting_offset" type="float" setter="set_sorting_offset" getter="get_sorting_offset" default="0.0"> - The sorting offset used by this [VisualInstance3D]. Adjusting it to a higher value will make the [VisualInstance3D] reliably draw on top of other [VisualInstance3D]s that are otherwise positioned at the same spot. + The amount by which the depth of this [VisualInstance3D] will be adjusted when sorting by depth. Uses the same units as the engine (which are typically meters). Adjusting it to a higher value will make the [VisualInstance3D] reliably draw on top of other [VisualInstance3D]s that are otherwise positioned at the same spot. To ensure it always draws on top of other objects around it (not positioned at the same spot), set the value to be greater than the distance between this [VisualInstance3D] and the other nearby [VisualInstance3D]s. </member> <member name="sorting_use_aabb_center" type="bool" setter="set_sorting_use_aabb_center" getter="is_sorting_use_aabb_center"> If [code]true[/code], the object is sorted based on the [AABB] center. The object will be sorted based on the global position otherwise. diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp index 0e7476d045..b7c01c061f 100644 --- a/editor/project_converter_3_to_4.cpp +++ b/editor/project_converter_3_to_4.cpp @@ -78,11 +78,11 @@ public: RegEx reg_image_unlock = RegEx("([a-zA-Z0-9_\\.]+)\\.unlock\\(\\)"); RegEx reg_instantiate = RegEx("\\.instance\\(([^\\)]*)\\)"); // Simple OS properties with getters/setters. - RegEx reg_os_current_screen = RegEx("\\bOS\\.(set_|get_)?current_screen\\b"); - RegEx reg_os_min_window_size = RegEx("\\bOS\\.(set_|get_)?min_window_size\\b"); - RegEx reg_os_max_window_size = RegEx("\\bOS\\.(set_|get_)?max_window_size\\b"); - RegEx reg_os_window_position = RegEx("\\bOS\\.(set_|get_)?window_position\\b"); - RegEx reg_os_window_size = RegEx("\\bOS\\.(set_|get_)?window_size\\b"); + RegEx reg_os_current_screen = RegEx("\\bOS\\.((set_|get_)?)current_screen\\b"); + RegEx reg_os_min_window_size = RegEx("\\bOS\\.((set_|get_)?)min_window_size\\b"); + RegEx reg_os_max_window_size = RegEx("\\bOS\\.((set_|get_)?)max_window_size\\b"); + RegEx reg_os_window_position = RegEx("\\bOS\\.((set_|get_)?)window_position\\b"); + RegEx reg_os_window_size = RegEx("\\bOS\\.((set_|get_)?)window_size\\b"); RegEx reg_os_getset_screen_orient = RegEx("\\bOS\\.(s|g)et_screen_orientation\\b"); // OS property getters/setters for non trivial replacements. RegEx reg_os_set_window_resizable = RegEx(make_regex_gds_os_property_set("set_window_resizable")); @@ -1055,20 +1055,20 @@ bool ProjectConverter3To4::test_array_names() { // List of excluded functions from builtin types and global namespace, because currently it is not possible to get list of functions from them. // This will be available when https://github.com/godotengine/godot/pull/49053 or similar will be included into Godot. - static const char *builtin_types_excluded_functions[] = { "dict_to_inst", "inst_to_dict", "bytes_to_var", "bytes_to_var_with_objects", "db_to_linear", "deg_to_rad", "linear_to_db", "rad_to_deg", "randf_range", "snapped", "str_to_var", "var_to_str", "var_to_bytes", "var_to_bytes_with_objects", "move_toward", "uri_encode", "uri_decode", "remove_at", "get_rotation_quaternion", "clamp", "grow_side", "is_absolute_path", "is_valid_int", "lerp", "to_ascii_buffer", "to_utf8_buffer", "to_utf32_buffer", "snapped", "remap", "rfind", nullptr }; + static const char *builtin_types_excluded_functions[] = { "dict_to_inst", "inst_to_dict", "bytes_to_var", "bytes_to_var_with_objects", "db_to_linear", "deg_to_rad", "linear_to_db", "rad_to_deg", "randf_range", "snapped", "str_to_var", "var_to_str", "var_to_bytes", "var_to_bytes_with_objects", "move_toward", "uri_encode", "uri_decode", "remove_at", "get_rotation_quaternion", "limit_length", "grow_side", "is_absolute_path", "is_valid_int", "lerp", "to_ascii_buffer", "to_utf8_buffer", "to_utf32_buffer", "snapped", "remap", "rfind", nullptr }; for (int current_index = 0; builtin_types_excluded_functions[current_index]; current_index++) { all_functions.insert(builtin_types_excluded_functions[current_index]); } - // for (int type = Variant::Type::NIL + 1; type < Variant::Type::VARIANT_MAX; type++) { - // List<MethodInfo> method_list; - // Variant::get_method_list_by_type(&method_list, Variant::Type(type)); - // for (MethodInfo &function_data : method_list) { - // if (!all_functions.has(function_data.name)) { - // all_functions.insert(function_data.name); - // } - // } - // } + //for (int type = Variant::Type::NIL + 1; type < Variant::Type::VARIANT_MAX; type++) { + // List<MethodInfo> method_list; + // Variant::get_method_list_by_type(&method_list, Variant::Type(type)); + // for (MethodInfo &function_data : method_list) { + // if (!all_functions.has(function_data.name)) { + // all_functions.insert(function_data.name); + // } + // } + //} List<StringName> classes_list; ClassDB::get_class_list(&classes_list); diff --git a/editor/renames_map_3_to_4.cpp b/editor/renames_map_3_to_4.cpp index d7cac9a2b9..1c212642ce 100644 --- a/editor/renames_map_3_to_4.cpp +++ b/editor/renames_map_3_to_4.cpp @@ -577,9 +577,9 @@ const char *RenamesMap3To4::gdscript_function_renames[][2] = { // Builtin types // Remember to add them to the builtin_types_excluded_functions variable, because for now these functions cannot be listed. - // { "empty", "is_empty" }, // Array -- Used as custom rule. Be careful, this will be used everywhere. - // { "remove", "remove_at" }, // Array -- Breaks Directory and several more. - { "clamped", "clamp" }, // Vector2 -- Be careful, this will be used everywhere. + //{ "empty", "is_empty" }, // Array -- Used as custom rule. Be careful, this will be used everywhere. + //{ "remove", "remove_at" }, // Array -- Breaks Directory and several more. + { "clamped", "limit_length" }, // Vector2 { "get_rotation_quat", "get_rotation_quaternion" }, // Basis { "grow_margin", "grow_side" }, // Rect2 { "invert", "reverse" }, // Array -- Give it a check. Be careful, this will be used everywhere. @@ -1024,9 +1024,9 @@ const char *RenamesMap3To4::csharp_function_renames[][2] = { { "GetUniformName", "GetParameterName" }, // ParameterRef // Builtin types - // { "Empty", "IsEmpty" }, // Array -- Used as custom rule. Be careful, this will be used everywhere. - // { "Remove", "RemoveAt" }, // Array -- Breaks Directory and several more. - { "Clamped", "Clamp" }, // Vector2 -- Be careful, this will be used everywhere. + // { "Empty", "IsEmpty" }, // Array -- Used as custom rule. Be careful, this will be used everywhere. + // { "Remove", "RemoveAt" }, // Array -- Breaks Directory and several more. + { "Clamped", "LimitLength" }, // Vector2 { "GetRotationQuat", "GetRotationQuaternion" }, // Basis { "GrowMargin", "GrowSide" }, // Rect2 { "Invert", "Reverse" }, // Array -- Give it a check. Be careful, this will be used everywhere. diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index e058187860..38d5ae6b77 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -2618,7 +2618,7 @@ void GDScriptAnalyzer::reduce_binary_op(GDScriptParser::BinaryOpNode *p_binary_o result = get_operation_type(p_binary_op->variant_op, left_type, right_type, valid, p_binary_op); if (!valid) { push_error(vformat(R"(Invalid operands "%s" and "%s" for "%s" operator.)", left_type.to_string(), right_type.to_string(), Variant::get_operator_name(p_binary_op->variant_op)), p_binary_op); - } else if (result.type_source != GDScriptParser::DataType::ANNOTATED_EXPLICIT) { + } else if (!result.is_hard_type()) { mark_node_unsafe(p_binary_op); } } else { diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 60b8c8f880..9e1dca16ac 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -2018,6 +2018,32 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ bool is_initializer = p_func && !p_for_lambda && p_func->identifier->name == GDScriptLanguage::get_singleton()->strings._init; bool is_implicit_ready = !p_func && p_for_ready; + if (!p_for_lambda && is_implicit_initializer) { + // Initialize the default values for type variables before anything. + // This avoids crashes if they are accessed with validated calls before being properly initialized. + // It may happen with out-of-order access or with `@onready` variables. + for (const GDScriptParser::ClassNode::Member &member : p_class->members) { + if (member.type != GDScriptParser::ClassNode::Member::VARIABLE) { + continue; + } + + const GDScriptParser::VariableNode *field = member.variable; + GDScriptDataType field_type = _gdtype_from_datatype(field->get_datatype(), codegen.script); + GDScriptCodeGenerator::Address dst_address(GDScriptCodeGenerator::Address::MEMBER, codegen.script->member_indices[field->identifier->name].index, field_type); + + if (field_type.has_type) { + codegen.generator->write_newline(field->start_line); + + if (field_type.has_container_element_type()) { + codegen.generator->write_construct_typed_array(dst_address, field_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>()); + } else if (field_type.kind == GDScriptDataType::BUILTIN) { + codegen.generator->write_construct(dst_address, field_type.builtin_type, Vector<GDScriptCodeGenerator::Address>()); + } + // The `else` branch is for objects, in such case we leave it as `null`. + } + } + } + if (!p_for_lambda && (is_implicit_initializer || is_implicit_ready)) { // Initialize class fields. for (int i = 0; i < p_class->members.size(); i++) { @@ -2051,16 +2077,6 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ if (src_address.mode == GDScriptCodeGenerator::Address::TEMPORARY) { codegen.generator->pop_temporary(); } - } else if (field_type.has_type) { - codegen.generator->write_newline(field->start_line); - - // Initialize with default for type. - if (field_type.has_container_element_type()) { - codegen.generator->write_construct_typed_array(dst_address, field_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>()); - } else if (field_type.kind == GDScriptDataType::BUILTIN) { - codegen.generator->write_construct(dst_address, field_type.builtin_type, Vector<GDScriptCodeGenerator::Address>()); - } - // The `else` branch is for objects, in such case we leave it as `null`. } } } diff --git a/modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.gd b/modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.gd new file mode 100644 index 0000000000..03278e453f --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.gd @@ -0,0 +1,20 @@ +extends Node + +@onready var later_inferred := [1] +@onready var later_static : Array +@onready var later_static_with_init : Array = [1] +@onready var later_untyped = [1] + +func test(): + assert(typeof(later_inferred) == TYPE_ARRAY) + assert(later_inferred.size() == 0) + + assert(typeof(later_static) == TYPE_ARRAY) + assert(later_static.size() == 0) + + assert(typeof(later_static_with_init) == TYPE_ARRAY) + assert(later_static_with_init.size() == 0) + + assert(typeof(later_untyped) == TYPE_NIL) + + print("ok") diff --git a/modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.out b/modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.out new file mode 100644 index 0000000000..1b47ed10dc --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/default_set_beforehand.out @@ -0,0 +1,2 @@ +GDTEST_OK +ok diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index b38f7225a2..6c961813b4 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -251,8 +251,12 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { /* we're expecting more header packets. */ while ((theora_p && theora_p < 3) || (vorbis_p && vorbis_p < 3)) { + int ret = 0; + /* look for further theora headers */ - int ret = ogg_stream_packetout(&to, &op); + if (theora_p && theora_p < 3) { + ret = ogg_stream_packetout(&to, &op); + } while (theora_p && theora_p < 3 && ret) { if (ret < 0) { fprintf(stderr, "Error parsing Theora stream headers; corrupt stream?\n"); @@ -269,7 +273,9 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { } /* look for more vorbis header packets */ - ret = ogg_stream_packetout(&vo, &op); + if (vorbis_p && vorbis_p < 3) { + ret = ogg_stream_packetout(&vo, &op); + } while (vorbis_p && vorbis_p < 3 && ret) { if (ret < 0) { fprintf(stderr, "Error parsing Vorbis stream headers; corrupt stream?\n"); diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp index b45a7c0db3..ff1d55f905 100644 --- a/servers/rendering/shader_preprocessor.cpp +++ b/servers/rendering/shader_preprocessor.cpp @@ -679,6 +679,11 @@ void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) { path = state->current_filename.get_base_dir().path_join(path); } + if (!ResourceLoader::exists(path)) { + set_error(RTR("Shader include file does not exist: ") + path, line); + return; + } + Ref<Resource> res = ResourceLoader::load(path); if (res.is_null()) { set_error(RTR("Shader include load failed. Does the shader include exist? Is there a cyclic dependency?"), line); |