diff options
30 files changed, 321 insertions, 140 deletions
diff --git a/.github/actions/godot-deps/action.yml b/.github/actions/godot-deps/action.yml index e99167ff2b..38731db5d6 100644 --- a/.github/actions/godot-deps/action.yml +++ b/.github/actions/godot-deps/action.yml @@ -23,5 +23,5 @@ runs: shell: bash run: | python -c "import sys; print(sys.version)" - python -m pip install scons + python -m pip install scons==4.4.0 scons --version diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h index fe40e7f76a..cc22b23b70 100644 --- a/core/math/random_pcg.h +++ b/core/math/random_pcg.h @@ -126,10 +126,18 @@ public: } _FORCE_INLINE_ double randfn(double p_mean, double p_deviation) { - return p_mean + p_deviation * (cos(Math_TAU * randd()) * sqrt(-2.0 * log(randd()))); // Box-Muller transform + double temp = randd(); + if (temp < CMP_EPSILON) { + temp += CMP_EPSILON; // To prevent generating of INF value in log function, resulting to return NaN value from this function. + } + return p_mean + p_deviation * (cos(Math_TAU * randd()) * sqrt(-2.0 * log(temp))); // Box-Muller transform. } _FORCE_INLINE_ float randfn(float p_mean, float p_deviation) { - return p_mean + p_deviation * (cos((float)Math_TAU * randf()) * sqrt(-2.0 * log(randf()))); // Box-Muller transform + float temp = randf(); + if (temp < CMP_EPSILON) { + temp += CMP_EPSILON; // To prevent generating of INF value in log function, resulting to return NaN value from this function. + } + return p_mean + p_deviation * (cos((float)Math_TAU * randf()) * sqrt(-2.0 * log(temp))); // Box-Muller transform. } double random(double p_from, double p_to); diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 6ad4d94d15..3146b9d3af 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -188,6 +188,7 @@ GetTree().CreateTween().BindNode(this); [/csharp] [/codeblocks] + The Tween will start automatically on the next process frame or physics frame (depending on [enum Tween.TweenProcessMode]). </description> </method> <method name="duplicate" qualifiers="const"> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 6ac1d2ca56..1dce0b1632 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -634,6 +634,7 @@ - [code]OS.shell_open("https://godotengine.org")[/code] opens the default web browser on the official Godot website. - [code]OS.shell_open("mailto:example@example.com")[/code] opens the default email client with the "To" field set to [code]example@example.com[/code]. See [url=https://datatracker.ietf.org/doc/html/rfc2368]RFC 2368 - The [code]mailto[/code] URL scheme[/url] for a list of fields that can be added. Use [method ProjectSettings.globalize_path] to convert a [code]res://[/code] or [code]user://[/code] path into a system path for use with this method. + [b]Note:[/b] Use [method String.uri_encode] to encode characters within URLs in a URL-safe, portable way. This is especially required for line breaks. Otherwise, [method shell_open] may not work correctly in a project exported to the Web platform. [b]Note:[/b] This method is implemented on Android, iOS, Web, Linux, macOS and Windows. </description> </method> diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index 1adf17f10e..c88acd8950 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -88,7 +88,7 @@ <method name="create_tween"> <return type="Tween" /> <description> - Creates and returns a new [Tween]. + Creates and returns a new [Tween]. The Tween will start automatically on the next process frame or physics frame (depending on [enum Tween.TweenProcessMode]). </description> </method> <method name="get_first_node_in_group"> diff --git a/doc/classes/String.xml b/doc/classes/String.xml index dba1cbb052..d629a31bca 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -970,7 +970,7 @@ <method name="uri_decode" qualifiers="const"> <return type="String" /> <description> - Decodes the string from its URL-encoded format. This method is meant to properly decode the parameters in a URL when receiving an HTTP request. + Decodes the string from its URL-encoded format. This method is meant to properly decode the parameters in a URL when receiving an HTTP request. See also [method uri_encode]. [codeblocks] [gdscript] var url = "$DOCS_URL/?highlight=Godot%20Engine%3%docs" @@ -986,7 +986,7 @@ <method name="uri_encode" qualifiers="const"> <return type="String" /> <description> - Encodes the string to URL-friendly format. This method is meant to properly encode the parameters in a URL when sending an HTTP request. + Encodes the string to URL-friendly format. This method is meant to properly encode the parameters in a URL when sending an HTTP request. See also [method uri_decode]. [codeblocks] [gdscript] var prefix = "$DOCS_URL/?highlight=" diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml index 31cff3f64a..f091ce66f8 100644 --- a/doc/classes/Tween.xml +++ b/doc/classes/Tween.xml @@ -89,8 +89,8 @@ [/codeblocks] Some [Tweener]s use transitions and eases. The first accepts a [enum TransitionType] constant, and refers to the way the timing of the animation is handled (see [url=https://easings.net/]easings.net[/url] for some examples). The second accepts an [enum EaseType] constant, and controls where the [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transition and easing to pick, you can try different [enum TransitionType] constants with [constant EASE_IN_OUT], and use the one that looks best. [url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/tween_cheatsheet.png]Tween easing and transition types cheatsheet[/url] - [b]Note:[/b] All [Tween]s will automatically start by default. To prevent a [Tween] from autostarting, you can call [method stop] immediately after it is created. - [b]Note:[/b] [Tween]s are processing after all of nodes in the current frame, i.e. after [method Node._process] or [method Node._physics_process] (depending on [enum TweenProcessMode]). + [b]Note:[/b] Tweens are not designed to be re-used and trying to do so results in an undefined behavior. Create a new Tween for each animation and every time you replay an animation from start. Keep in mind that Tweens start immediately, so only create a Tween when you want to start animating. + [b]Note:[/b] Tweens are processing after all of nodes in the current frame, i.e. after [method Node._process] or [method Node._physics_process] (depending on [enum TweenProcessMode]). </description> <tutorials> </tutorials> @@ -129,7 +129,6 @@ <description> Processes the [Tween] by the given [param delta] value, in seconds. This is mostly useful for manual control when the [Tween] is paused. It can also be used to end the [Tween] animation immediately, by setting [param delta] longer than the whole duration of the [Tween] animation. Returns [code]true[/code] if the [Tween] still has [Tweener]s that haven't finished. - [b]Note:[/b] The [Tween] will become invalid in the next processing frame after its animation finishes. Calling [method stop] after performing [method custom_step] instead keeps and resets the [Tween]. </description> </method> <method name="get_total_elapsed_time" qualifiers="const"> @@ -432,7 +431,6 @@ <signal name="finished"> <description> Emitted when the [Tween] has finished all tweening. Never emitted when the [Tween] is set to infinite looping (see [method set_loops]). - [b]Note:[/b] The [Tween] is removed (invalidated) in the next processing frame after this signal is emitted. Calling [method stop] inside the signal callback will prevent the [Tween] from being removed. </description> </signal> <signal name="loop_finished"> diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 6379c9bd4a..1736ad1d42 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1066,6 +1066,12 @@ static const RS::CanvasItemTextureRepeat repeat_from_uniform[ShaderLanguage::REP RS::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED, // ShaderLanguage::TextureRepeat::REPEAT_DEFAULT, }; +static const RS::CanvasItemTextureRepeat repeat_from_uniform_canvas[ShaderLanguage::REPEAT_DEFAULT + 1] = { + RS::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, // ShaderLanguage::TextureRepeat::REPEAT_DISABLE, + RS::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED, // ShaderLanguage::TextureRepeat::REPEAT_ENABLE, + RS::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, // ShaderLanguage::TextureRepeat::REPEAT_DEFAULT, +}; + static const RS::CanvasItemTextureFilter filter_from_uniform[ShaderLanguage::FILTER_DEFAULT + 1] = { RS::CanvasItemTextureFilter::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, // ShaderLanguage::TextureFilter::FILTER_NEAREST, RS::CanvasItemTextureFilter::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, // ShaderLanguage::TextureFilter::FILTER_LINEAR, @@ -1076,6 +1082,16 @@ static const RS::CanvasItemTextureFilter filter_from_uniform[ShaderLanguage::FIL RS::CanvasItemTextureFilter::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, // ShaderLanguage::TextureFilter::FILTER_DEFAULT, }; +static const RS::CanvasItemTextureFilter filter_from_uniform_canvas[ShaderLanguage::FILTER_DEFAULT + 1] = { + RS::CanvasItemTextureFilter::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, // ShaderLanguage::TextureFilter::FILTER_NEAREST, + RS::CanvasItemTextureFilter::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, // ShaderLanguage::TextureFilter::FILTER_LINEAR, + RS::CanvasItemTextureFilter::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, // ShaderLanguage::TextureFilter::FILTER_NEAREST_MIPMAP, + RS::CanvasItemTextureFilter::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, // ShaderLanguage::TextureFilter::FILTER_LINEAR_MIPMAP, + RS::CanvasItemTextureFilter::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, // ShaderLanguage::TextureFilter::FILTER_NEAREST_MIPMAP_ANISOTROPIC, + RS::CanvasItemTextureFilter::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, // ShaderLanguage::TextureFilter::FILTER_LINEAR_MIPMAP_ANISOTROPIC, + RS::CanvasItemTextureFilter::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, // ShaderLanguage::TextureFilter::FILTER_DEFAULT, +}; + void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { MaterialStorage *material_storage = MaterialStorage::get_singleton(); bool uses_global_buffer = false; @@ -3061,8 +3077,8 @@ void CanvasMaterialData::bind_uniforms() { texture->render_target->used_in_frame = true; } - texture->gl_set_filter(filter_from_uniform[int(texture_uniforms[ti].filter)]); - texture->gl_set_repeat(repeat_from_uniform[int(texture_uniforms[ti].repeat)]); + texture->gl_set_filter(filter_from_uniform_canvas[int(texture_uniforms[ti].filter)]); + texture->gl_set_repeat(repeat_from_uniform_canvas[int(texture_uniforms[ti].repeat)]); } } diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp index 16fd025d52..5a45fd9c4b 100644 --- a/editor/project_converter_3_to_4.cpp +++ b/editor/project_converter_3_to_4.cpp @@ -122,6 +122,9 @@ public: RegEx keyword_gdscript_master = RegEx("^master func"); RegEx keyword_gdscript_mastersync = RegEx("^mastersync func"); + RegEx gdscript_comment = RegEx("^\\s*#"); + RegEx csharp_comment = RegEx("^\\s*\\/\\/"); + // CSharp keywords. RegEx keyword_csharp_remote = RegEx("\\[Remote(Attribute)?(\\(\\))?\\]"); RegEx keyword_csharp_remotesync = RegEx("\\[(Remote)?Sync(Attribute)?(\\(\\))?\\]"); @@ -337,17 +340,21 @@ bool ProjectConverter3To4::convert() { // Check file by file. for (int i = 0; i < collected_files.size(); i++) { String file_name = collected_files[i]; - Vector<String> lines; + Vector<SourceLine> source_lines; uint32_t ignored_lines = 0; { Ref<FileAccess> file = FileAccess::open(file_name, FileAccess::READ); ERR_CONTINUE_MSG(file.is_null(), vformat("Unable to read content of \"%s\".", file_name)); while (!file->eof_reached()) { String line = file->get_line(); - lines.append(line); + + SourceLine source_line; + source_line.line = line; + source_line.is_comment = reg_container.gdscript_comment.search_all(line).size() > 0 || reg_container.csharp_comment.search_all(line).size() > 0; + source_lines.append(source_line); } } - String file_content_before = collect_string_from_vector(lines); + String file_content_before = collect_string_from_vector(source_lines); uint64_t hash_before = file_content_before.hash(); uint64_t file_size = file_content_before.size(); print_line(vformat("Trying to convert\t%d/%d file - \"%s\" with size - %d KB", i + 1, collected_files.size(), file_name.trim_prefix("res://"), file_size / 1024)); @@ -364,68 +371,69 @@ bool ProjectConverter3To4::convert() { if (file_size < uint64_t(maximum_file_size)) { // ".tscn" must work exactly the same as ".gd" files because they may contain built-in Scripts. if (file_name.ends_with(".gd")) { - rename_classes(lines, reg_container); // Using only specialized function. + rename_classes(source_lines, reg_container); // Using only specialized function. - rename_common(RenamesMap3To4::enum_renames, reg_container.enum_regexes, lines); - rename_colors(lines, reg_container); // Require to additional rename. + rename_common(RenamesMap3To4::enum_renames, reg_container.enum_regexes, source_lines); + rename_colors(source_lines, reg_container); // Require to additional rename. - rename_common(RenamesMap3To4::gdscript_function_renames, reg_container.gdscript_function_regexes, lines); - rename_gdscript_functions(lines, reg_container, false); // Require to additional rename. + rename_common(RenamesMap3To4::gdscript_function_renames, reg_container.gdscript_function_regexes, source_lines); + rename_gdscript_functions(source_lines, reg_container, false); // Require to additional rename. - rename_common(RenamesMap3To4::project_settings_renames, reg_container.project_settings_regexes, lines); - rename_gdscript_keywords(lines, reg_container); - rename_common(RenamesMap3To4::gdscript_properties_renames, reg_container.gdscript_properties_regexes, lines); - rename_common(RenamesMap3To4::gdscript_signals_renames, reg_container.gdscript_signals_regexes, lines); - rename_common(RenamesMap3To4::shaders_renames, reg_container.shaders_regexes, lines); - rename_common(RenamesMap3To4::builtin_types_renames, reg_container.builtin_types_regexes, lines); + rename_common(RenamesMap3To4::project_settings_renames, reg_container.project_settings_regexes, source_lines); + rename_gdscript_keywords(source_lines, reg_container); + rename_common(RenamesMap3To4::gdscript_properties_renames, reg_container.gdscript_properties_regexes, source_lines); + rename_common(RenamesMap3To4::gdscript_signals_renames, reg_container.gdscript_signals_regexes, source_lines); + rename_common(RenamesMap3To4::shaders_renames, reg_container.shaders_regexes, source_lines); + rename_common(RenamesMap3To4::builtin_types_renames, reg_container.builtin_types_regexes, source_lines); - custom_rename(lines, "\\.shader", ".gdshader"); + custom_rename(source_lines, "\\.shader", ".gdshader"); } else if (file_name.ends_with(".tscn")) { - rename_classes(lines, reg_container); // Using only specialized function. + rename_classes(source_lines, reg_container); // Using only specialized function. - rename_common(RenamesMap3To4::enum_renames, reg_container.enum_regexes, lines); - rename_colors(lines, reg_container); // Require to do additional renames. + rename_common(RenamesMap3To4::enum_renames, reg_container.enum_regexes, source_lines); + rename_colors(source_lines, reg_container); // Require to do additional renames. - rename_common(RenamesMap3To4::gdscript_function_renames, reg_container.gdscript_function_regexes, lines); - rename_gdscript_functions(lines, reg_container, true); // Require to do additional renames. + rename_common(RenamesMap3To4::gdscript_function_renames, reg_container.gdscript_function_regexes, source_lines); + rename_gdscript_functions(source_lines, reg_container, true); // Require to do additional renames. - rename_common(RenamesMap3To4::project_settings_renames, reg_container.project_settings_regexes, lines); - rename_gdscript_keywords(lines, reg_container); - rename_common(RenamesMap3To4::gdscript_properties_renames, reg_container.gdscript_properties_regexes, lines); - rename_common(RenamesMap3To4::gdscript_signals_renames, reg_container.gdscript_signals_regexes, lines); - rename_common(RenamesMap3To4::shaders_renames, reg_container.shaders_regexes, lines); - rename_common(RenamesMap3To4::builtin_types_renames, reg_container.builtin_types_regexes, lines); + rename_common(RenamesMap3To4::project_settings_renames, reg_container.project_settings_regexes, source_lines); + rename_gdscript_keywords(source_lines, reg_container); + rename_common(RenamesMap3To4::gdscript_properties_renames, reg_container.gdscript_properties_regexes, source_lines); + rename_common(RenamesMap3To4::gdscript_signals_renames, reg_container.gdscript_signals_regexes, source_lines); + rename_common(RenamesMap3To4::shaders_renames, reg_container.shaders_regexes, source_lines); + rename_common(RenamesMap3To4::builtin_types_renames, reg_container.builtin_types_regexes, source_lines); - custom_rename(lines, "\\.shader", ".gdshader"); + custom_rename(source_lines, "\\.shader", ".gdshader"); } else if (file_name.ends_with(".cs")) { // TODO, C# should use different methods. - rename_classes(lines, reg_container); // Using only specialized function. - rename_common(RenamesMap3To4::csharp_function_renames, reg_container.csharp_function_regexes, lines); - rename_common(RenamesMap3To4::builtin_types_renames, reg_container.builtin_types_regexes, lines); - rename_common(RenamesMap3To4::csharp_properties_renames, reg_container.csharp_properties_regexes, lines); - rename_common(RenamesMap3To4::csharp_signals_renames, reg_container.csharp_signal_regexes, lines); - rename_csharp_functions(lines, reg_container); - rename_csharp_attributes(lines, reg_container); - custom_rename(lines, "public class ", "public partial class "); + rename_classes(source_lines, reg_container); // Using only specialized function. + rename_common(RenamesMap3To4::csharp_function_renames, reg_container.csharp_function_regexes, source_lines); + rename_common(RenamesMap3To4::builtin_types_renames, reg_container.builtin_types_regexes, source_lines); + rename_common(RenamesMap3To4::csharp_properties_renames, reg_container.csharp_properties_regexes, source_lines); + rename_common(RenamesMap3To4::csharp_signals_renames, reg_container.csharp_signal_regexes, source_lines); + rename_csharp_functions(source_lines, reg_container); + rename_csharp_attributes(source_lines, reg_container); + custom_rename(source_lines, "public class ", "public partial class "); } else if (file_name.ends_with(".gdshader") || file_name.ends_with(".shader")) { - rename_common(RenamesMap3To4::shaders_renames, reg_container.shaders_regexes, lines); + rename_common(RenamesMap3To4::shaders_renames, reg_container.shaders_regexes, source_lines); } else if (file_name.ends_with("tres")) { - rename_classes(lines, reg_container); // Using only specialized function. + rename_classes(source_lines, reg_container); // Using only specialized function. - rename_common(RenamesMap3To4::shaders_renames, reg_container.shaders_regexes, lines); - rename_common(RenamesMap3To4::builtin_types_renames, reg_container.builtin_types_regexes, lines); + rename_common(RenamesMap3To4::shaders_renames, reg_container.shaders_regexes, source_lines); + rename_common(RenamesMap3To4::builtin_types_renames, reg_container.builtin_types_regexes, source_lines); - custom_rename(lines, "\\.shader", ".gdshader"); + custom_rename(source_lines, "\\.shader", ".gdshader"); } else if (file_name.ends_with("project.godot")) { - rename_common(RenamesMap3To4::project_godot_renames, reg_container.project_godot_regexes, lines); - rename_common(RenamesMap3To4::builtin_types_renames, reg_container.builtin_types_regexes, lines); - rename_input_map_scancode(lines, reg_container); - rename_common(RenamesMap3To4::input_map_renames, reg_container.input_map_regexes, lines); + rename_common(RenamesMap3To4::project_godot_renames, reg_container.project_godot_regexes, source_lines); + rename_common(RenamesMap3To4::builtin_types_renames, reg_container.builtin_types_regexes, source_lines); + rename_input_map_scancode(source_lines, reg_container); + rename_common(RenamesMap3To4::input_map_renames, reg_container.input_map_regexes, source_lines); } else if (file_name.ends_with(".csproj")) { // TODO } else if (file_name.ends_with(".import")) { - for (int x = 0; x < lines.size(); x++) { - if (lines[x].contains("nodes/root_type=\"Spatial\"")) { - lines.set(x, "nodes/root_type=\"Node3D\""); + for (SourceLine &source_line : source_lines) { + String &line = source_line.line; + if (line.contains("nodes/root_type=\"Spatial\"")) { + line = "nodes/root_type=\"Node3D\""; } } } else { @@ -433,7 +441,12 @@ bool ProjectConverter3To4::convert() { continue; } - for (String &line : lines) { + for (SourceLine &source_line : source_lines) { + if (source_line.is_comment) { + continue; + } + + String &line = source_line.line; if (uint64_t(line.length()) > maximum_line_length) { ignored_lines += 1; } @@ -448,7 +461,7 @@ bool ProjectConverter3To4::convert() { String end_message = vformat(" Checking file took %d ms.", end_time - start_time); print_line(end_message); } else { - String file_content_after = collect_string_from_vector(lines); + String file_content_after = collect_string_from_vector(source_lines); uint64_t hash_after = file_content_after.hash64(); // Don't need to save file without any changes. // Save if this is a shader, because it was renamed. @@ -679,9 +692,23 @@ Vector<String> ProjectConverter3To4::check_for_files() { return collected_files; } +Vector<SourceLine> ProjectConverter3To4::split_lines(const String &text) { + Vector<String> lines = text.split("\n"); + Vector<SourceLine> source_lines; + for (String &line : lines) { + SourceLine source_line; + source_line.line = line; + source_line.is_comment = false; + + source_lines.append(source_line); + } + return source_lines; +} + // Test expected results of gdscript -bool ProjectConverter3To4::test_conversion_gdscript_builtin(String name, String expected, void (ProjectConverter3To4::*func)(Vector<String> &, const RegExContainer &, bool), String what, const RegExContainer ®_container, bool builtin_script) { - Vector<String> got = name.split("\n"); +bool ProjectConverter3To4::test_conversion_gdscript_builtin(String name, String expected, void (ProjectConverter3To4::*func)(Vector<SourceLine> &, const RegExContainer &, bool), String what, const RegExContainer ®_container, bool builtin_script) { + Vector<SourceLine> got = split_lines(name); + (this->*func)(got, reg_container, builtin_script); String got_str = collect_string_from_vector(got); ERR_FAIL_COND_V_MSG(expected != got_str, false, vformat("Failed to convert %s \"%s\" to \"%s\", got instead \"%s\"", what, name, expected, got_str)); @@ -689,8 +716,9 @@ bool ProjectConverter3To4::test_conversion_gdscript_builtin(String name, String return true; } -bool ProjectConverter3To4::test_conversion_with_regex(String name, String expected, void (ProjectConverter3To4::*func)(Vector<String> &, const RegExContainer &), String what, const RegExContainer ®_container) { - Vector<String> got = name.split("\n"); +bool ProjectConverter3To4::test_conversion_with_regex(String name, String expected, void (ProjectConverter3To4::*func)(Vector<SourceLine> &, const RegExContainer &), String what, const RegExContainer ®_container) { + Vector<SourceLine> got = split_lines(name); + (this->*func)(got, reg_container); String got_str = collect_string_from_vector(got); ERR_FAIL_COND_V_MSG(expected != got_str, false, vformat("Failed to convert %s \"%s\" to \"%s\", got instead \"%s\"", what, name, expected, got_str)); @@ -699,7 +727,8 @@ bool ProjectConverter3To4::test_conversion_with_regex(String name, String expect } bool ProjectConverter3To4::test_conversion_basic(String name, String expected, const char *array[][2], LocalVector<RegEx *> ®ex_cache, String what) { - Vector<String> got = name.split("\n"); + Vector<SourceLine> got = split_lines(name); + rename_common(array, regex_cache, got); String got_str = collect_string_from_vector(got); ERR_FAIL_COND_V_MSG(expected != got_str, false, vformat("Failed to convert %s \"%s\" to \"%s\", got instead \"%s\"", what, name, expected, got_str)); @@ -889,7 +918,10 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { valid = valid && test_conversion_gdscript_builtin("(tween_callback(A,B,[C,D]).foo())", "(tween_callback(Callable(A, B).bind(C,D)).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("func _init(", "func _init(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("func _init(p_x:int)->void:", "func _init(p_x:int):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("func _init(a,b,c).(d,e,f):", "func _init(a,b,c):\n\tsuper(d,e,f)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("func _init(a,b,c).(a.b(),c.d()):", "func _init(a,b,c):\n\tsuper(a.b(),c.d())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("func _init(p_x:int)->void:", "func _init(p_x:int)->void:", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("func _init(a: int).(d,e,f) -> void:", "func _init(a: int) -> void:\n\tsuper(d,e,f)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("q_PackedDataContainer._iter_init(variable1)", "q_PackedDataContainer._iter_init(variable1)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("assert(speed < 20, str(randi()%10))", "assert(speed < 20) #,str(randi()%10))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); @@ -927,7 +959,9 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { String from = "instance"; String to = "instantiate"; String name = "AA.instance()"; - Vector<String> got = String("AA.instance()").split("\n"); + + Vector<SourceLine> got = split_lines(name); + String expected = "AA.instantiate()"; custom_rename(got, from, to); String got_str = collect_string_from_vector(got); @@ -1351,8 +1385,13 @@ String ProjectConverter3To4::get_object_of_execution(const String &line) const { return line.substr(variable_start, (end - variable_start)); } -void ProjectConverter3To4::rename_colors(Vector<String> &lines, const RegExContainer ®_container) { - for (String &line : lines) { +void ProjectConverter3To4::rename_colors(Vector<SourceLine> &source_lines, const RegExContainer ®_container) { + for (SourceLine &source_line : source_lines) { + if (source_line.is_comment) { + continue; + } + + String &line = source_line.line; if (uint64_t(line.length()) <= maximum_line_length) { if (line.contains("Color.")) { for (unsigned int current_index = 0; RenamesMap3To4::color_renames[current_index][0]; current_index++) { @@ -1384,8 +1423,13 @@ Vector<String> ProjectConverter3To4::check_for_rename_colors(Vector<String> &lin return found_renames; } -void ProjectConverter3To4::rename_classes(Vector<String> &lines, const RegExContainer ®_container) { - for (String &line : lines) { +void ProjectConverter3To4::rename_classes(Vector<SourceLine> &source_lines, const RegExContainer ®_container) { + for (SourceLine &source_line : source_lines) { + if (source_line.is_comment) { + continue; + } + + String &line = source_line.line; if (uint64_t(line.length()) <= maximum_line_length) { for (unsigned int current_index = 0; RenamesMap3To4::class_renames[current_index][0]; current_index++) { if (line.contains(RenamesMap3To4::class_renames[current_index][0])) { @@ -1452,8 +1496,13 @@ Vector<String> ProjectConverter3To4::check_for_rename_classes(Vector<String> &li return found_renames; } -void ProjectConverter3To4::rename_gdscript_functions(Vector<String> &lines, const RegExContainer ®_container, bool builtin) { - for (String &line : lines) { +void ProjectConverter3To4::rename_gdscript_functions(Vector<SourceLine> &source_lines, const RegExContainer ®_container, bool builtin) { + for (SourceLine &source_line : source_lines) { + if (source_line.is_comment) { + continue; + } + + String &line = source_line.line; if (uint64_t(line.length()) <= maximum_line_length) { process_gdscript_line(line, reg_container, builtin); } @@ -1943,17 +1992,18 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai } } } - // -- func _init(p_x:int)->void: -> func _init(p_x:int): Object # https://github.com/godotengine/godot/issues/50589 - if (line.contains(" _init(")) { - int start = line.find(" _init("); - if (line.contains(":")) { - int end = line.rfind(":") + 1; - if (end > -1) { - Vector<String> parts = parse_arguments(line.substr(start, end)); - line = line.substr(0, start) + " _init(" + connect_arguments(parts, 0) + "):" + line.substr(end + start); - } + // -- func _init(p_x:int).(p_x): -> func _init(p_x:int):\n\tsuper(p_x) Object # https://github.com/godotengine/godot/issues/70542 + if (line.contains(" _init(") && line.rfind(":") > 0) { + // func _init(p_arg1).(super4, super5, super6)->void: + // ^--^indent ^super_start super_end^ + int indent = line.count("\t", 0, line.find("func")); + int super_start = line.find(".("); + int super_end = line.rfind(")"); + if (super_start > 0 && super_end > super_start) { + line = line.substr(0, super_start) + line.substr(super_end + 1) + "\n" + String("\t").repeat(indent + 1) + "super" + line.substr(super_start + 1, super_end - super_start); } } + // assert(speed < 20, str(randi()%10)) -> assert(speed < 20) #,str(randi()%10)) GDScript - GDScript bug constant message if (line.contains("assert(")) { int start = line.find("assert("); @@ -2258,8 +2308,13 @@ void ProjectConverter3To4::process_csharp_line(String &line, const RegExContaine } } -void ProjectConverter3To4::rename_csharp_functions(Vector<String> &lines, const RegExContainer ®_container) { - for (String &line : lines) { +void ProjectConverter3To4::rename_csharp_functions(Vector<SourceLine> &source_lines, const RegExContainer ®_container) { + for (SourceLine &source_line : source_lines) { + if (source_line.is_comment) { + continue; + } + + String &line = source_line.line; if (uint64_t(line.length()) <= maximum_line_length) { process_csharp_line(line, reg_container); } @@ -2284,10 +2339,15 @@ Vector<String> ProjectConverter3To4::check_for_rename_csharp_functions(Vector<St return found_renames; } -void ProjectConverter3To4::rename_csharp_attributes(Vector<String> &lines, const RegExContainer ®_container) { +void ProjectConverter3To4::rename_csharp_attributes(Vector<SourceLine> &source_lines, const RegExContainer ®_container) { static String error_message = "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using Multiplayer.GetRemoteSenderId()\n"; - for (String &line : lines) { + for (SourceLine &source_line : source_lines) { + if (source_line.is_comment) { + continue; + } + + String &line = source_line.line; if (uint64_t(line.length()) <= maximum_line_length) { line = reg_container.keyword_csharp_remote.sub(line, "[RPC(MultiplayerAPI.RPCMode.AnyPeer)]", true); line = reg_container.keyword_csharp_remotesync.sub(line, "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", true); @@ -2349,10 +2409,15 @@ Vector<String> ProjectConverter3To4::check_for_rename_csharp_attributes(Vector<S return found_renames; } -void ProjectConverter3To4::rename_gdscript_keywords(Vector<String> &lines, const RegExContainer ®_container) { +void ProjectConverter3To4::rename_gdscript_keywords(Vector<SourceLine> &source_lines, const RegExContainer ®_container) { static String error_message = "The master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n"; - for (String &line : lines) { + for (SourceLine &source_line : source_lines) { + if (source_line.is_comment) { + continue; + } + + String &line = source_line.line; if (uint64_t(line.length()) <= maximum_line_length) { if (line.contains("tool")) { line = reg_container.keyword_gdscript_tool.sub(line, "@tool", true); @@ -2504,11 +2569,16 @@ Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<S return found_renames; } -void ProjectConverter3To4::rename_input_map_scancode(Vector<String> &lines, const RegExContainer ®_container) { +void ProjectConverter3To4::rename_input_map_scancode(Vector<SourceLine> &source_lines, const RegExContainer ®_container) { // The old Special Key, now colliding with CMD_OR_CTRL. const int old_spkey = (1 << 24); - for (String &line : lines) { + for (SourceLine &source_line : source_lines) { + if (source_line.is_comment) { + continue; + } + + String &line = source_line.line; if (uint64_t(line.length()) <= maximum_line_length) { TypedArray<RegExMatch> reg_match = reg_container.input_map_keycode.search_all(line); @@ -2557,10 +2627,15 @@ Vector<String> ProjectConverter3To4::check_for_rename_input_map_scancode(Vector< return found_renames; } -void ProjectConverter3To4::custom_rename(Vector<String> &lines, String from, String to) { +void ProjectConverter3To4::custom_rename(Vector<SourceLine> &source_lines, String from, String to) { RegEx reg = RegEx(String("\\b") + from + "\\b"); CRASH_COND(!reg.is_valid()); - for (String &line : lines) { + for (SourceLine &source_line : source_lines) { + if (source_line.is_comment) { + continue; + } + + String &line = source_line.line; if (uint64_t(line.length()) <= maximum_line_length) { line = reg.sub(line, to, true); } @@ -2586,8 +2661,13 @@ Vector<String> ProjectConverter3To4::check_for_custom_rename(Vector<String> &lin return found_renames; } -void ProjectConverter3To4::rename_common(const char *array[][2], LocalVector<RegEx *> &cached_regexes, Vector<String> &lines) { - for (String &line : lines) { +void ProjectConverter3To4::rename_common(const char *array[][2], LocalVector<RegEx *> &cached_regexes, Vector<SourceLine> &source_lines) { + for (SourceLine &source_line : source_lines) { + if (source_line.is_comment) { + continue; + } + + String &line = source_line.line; if (uint64_t(line.length()) <= maximum_line_length) { for (unsigned int current_index = 0; current_index < cached_regexes.size(); current_index++) { if (line.contains(array[current_index][0])) { @@ -2657,10 +2737,10 @@ String ProjectConverter3To4::simple_line_formatter(int current_line, String old_ } // Collects string from vector strings -String ProjectConverter3To4::collect_string_from_vector(Vector<String> &vector) { +String ProjectConverter3To4::collect_string_from_vector(Vector<SourceLine> &vector) { String string = ""; for (int i = 0; i < vector.size(); i++) { - string += vector[i]; + string += vector[i].line; if (i != vector.size() - 1) { string += "\n"; diff --git a/editor/project_converter_3_to_4.h b/editor/project_converter_3_to_4.h index 90c05c22d2..b2adfac395 100644 --- a/editor/project_converter_3_to_4.h +++ b/editor/project_converter_3_to_4.h @@ -58,6 +58,11 @@ public: #include "core/templates/local_vector.h" #include "core/templates/vector.h" +struct SourceLine { + String line; + bool is_comment; +}; + class RegEx; class ProjectConverter3To4 { @@ -66,33 +71,33 @@ class ProjectConverter3To4 { uint64_t maximum_file_size; uint64_t maximum_line_length; - void rename_colors(Vector<String> &lines, const RegExContainer ®_container); + void rename_colors(Vector<SourceLine> &source_lines, const RegExContainer ®_container); Vector<String> check_for_rename_colors(Vector<String> &lines, const RegExContainer ®_container); - void rename_classes(Vector<String> &lines, const RegExContainer ®_container); + void rename_classes(Vector<SourceLine> &source_lines, const RegExContainer ®_container); Vector<String> check_for_rename_classes(Vector<String> &lines, const RegExContainer ®_container); - void rename_gdscript_functions(Vector<String> &lines, const RegExContainer ®_container, bool builtin); + void rename_gdscript_functions(Vector<SourceLine> &source_lines, const RegExContainer ®_container, bool builtin); Vector<String> check_for_rename_gdscript_functions(Vector<String> &lines, const RegExContainer ®_container, bool builtin); void process_gdscript_line(String &line, const RegExContainer ®_container, bool builtin); - void rename_csharp_functions(Vector<String> &lines, const RegExContainer ®_container); + void rename_csharp_functions(Vector<SourceLine> &source_lines, const RegExContainer ®_container); Vector<String> check_for_rename_csharp_functions(Vector<String> &lines, const RegExContainer ®_container); void process_csharp_line(String &line, const RegExContainer ®_container); - void rename_csharp_attributes(Vector<String> &lines, const RegExContainer ®_container); + void rename_csharp_attributes(Vector<SourceLine> &source_lines, const RegExContainer ®_container); Vector<String> check_for_rename_csharp_attributes(Vector<String> &lines, const RegExContainer ®_container); - void rename_gdscript_keywords(Vector<String> &lines, const RegExContainer ®_container); + void rename_gdscript_keywords(Vector<SourceLine> &source_lines, const RegExContainer ®_container); Vector<String> check_for_rename_gdscript_keywords(Vector<String> &lines, const RegExContainer ®_container); - void rename_input_map_scancode(Vector<String> &lines, const RegExContainer ®_container); + void rename_input_map_scancode(Vector<SourceLine> &source_lines, const RegExContainer ®_container); Vector<String> check_for_rename_input_map_scancode(Vector<String> &lines, const RegExContainer ®_container); - void custom_rename(Vector<String> &lines, String from, String to); + void custom_rename(Vector<SourceLine> &source_lines, String from, String to); Vector<String> check_for_custom_rename(Vector<String> &lines, String from, String to); - void rename_common(const char *array[][2], LocalVector<RegEx *> &cached_regexes, Vector<String> &lines); + void rename_common(const char *array[][2], LocalVector<RegEx *> &cached_regexes, Vector<SourceLine> &source_lines); Vector<String> check_for_rename_common(const char *array[][2], LocalVector<RegEx *> &cached_regexes, Vector<String> &lines); Vector<String> check_for_files(); @@ -105,11 +110,12 @@ class ProjectConverter3To4 { String line_formatter(int current_line, String from, String to, String line); String simple_line_formatter(int current_line, String old_line, String line); - String collect_string_from_vector(Vector<String> &vector); + String collect_string_from_vector(Vector<SourceLine> &vector); + Vector<SourceLine> split_lines(const String &text); bool test_single_array(const char *array[][2], bool ignore_second_check = false); - bool test_conversion_gdscript_builtin(String name, String expected, void (ProjectConverter3To4::*func)(Vector<String> &, const RegExContainer &, bool), String what, const RegExContainer ®_container, bool builtin); - bool test_conversion_with_regex(String name, String expected, void (ProjectConverter3To4::*func)(Vector<String> &, const RegExContainer &), String what, const RegExContainer ®_container); + bool test_conversion_gdscript_builtin(String name, String expected, void (ProjectConverter3To4::*func)(Vector<SourceLine> &, const RegExContainer &, bool), String what, const RegExContainer ®_container, bool builtin); + bool test_conversion_with_regex(String name, String expected, void (ProjectConverter3To4::*func)(Vector<SourceLine> &, const RegExContainer &), String what, const RegExContainer ®_container); bool test_conversion_basic(String name, String expected, const char *array[][2], LocalVector<RegEx *> ®ex_cache, String what); bool test_array_names(); bool test_conversion(RegExContainer ®_container); diff --git a/editor/renames_map_3_to_4.cpp b/editor/renames_map_3_to_4.cpp index 90c8709c3b..3c61b81e5d 100644 --- a/editor/renames_map_3_to_4.cpp +++ b/editor/renames_map_3_to_4.cpp @@ -721,7 +721,7 @@ const char *RenamesMap3To4::csharp_function_renames[][2] = { { "GetEndianSwap", "IsBigEndian" }, // File { "GetErrorString", "GetErrorMessage" }, // JSON { "GetFocusNeighbour", "GetFocusNeighbor" }, // Control - { "GetFollowSmoothing", "GetFollowSmoothingSpeed" }, // Camera2D + { "GetFollowSmoothing", "GetPositionSmoothingSpeed" }, // Camera2D { "GetFontTypes", "GetFontTypeList" }, // Theme { "GetFrameColor", "GetColor" }, // ColorRect { "GetGlobalRateScale", "GetPlaybackSpeedScale" }, // AudioServer @@ -907,12 +907,12 @@ const char *RenamesMap3To4::csharp_function_renames[][2] = { { "SetDepthBiasEnable", "SetDepthBiasEnabled" }, // RDPipelineRasterizationState { "SetDevice", "SetOutputDevice" }, // AudioServer { "SetDoubleclick", "SetDoubleClick" }, // InputEventMouseButton - { "SetEnableFollowSmoothing", "SetFollowSmoothingEnabled" }, // Camera2D + { "SetEnableFollowSmoothing", "SetPositionSmoothingEnabled" }, // Camera2D { "SetEnabledFocusMode", "SetFocusMode" }, // BaseButton { "SetEndianSwap", "SetBigEndian" }, // File { "SetExpandToTextLength", "SetExpandToTextLengthEnabled" }, // LineEdit { "SetFocusNeighbour", "SetFocusNeighbor" }, // Control - { "SetFollowSmoothing", "SetFollowSmoothingSpeed" }, // Camera2D + { "SetFollowSmoothing", "SetPositionSmoothingSpeed" }, // Camera2D { "SetFrameColor", "SetColor" }, // ColorRect { "SetGlobalRateScale", "SetPlaybackSpeedScale" }, // AudioServer { "SetGravityDistanceScale", "SetGravityPointDistanceScale" }, // Area2D @@ -1122,7 +1122,7 @@ const char *RenamesMap3To4::gdscript_properties_renames[][2] = { { "selectedframe", "selected_frame" }, // Theme { "size_override_stretch", "size_2d_override_stretch" }, // SubViewport { "slips_on_slope", "slide_on_slope" }, // SeparationRayShape2D - { "smoothing_enabled", "follow_smoothing_enabled" }, // Camera2D + { "smoothing_enabled", "position_smoothing_enabled" }, // Camera2D { "smoothing_speed", "position_smoothing_speed" }, // Camera2D { "ss_reflections_depth_tolerance", "ssr_depth_tolerance" }, // Environment { "ss_reflections_enabled", "ssr_enabled" }, // Environment @@ -1215,8 +1215,8 @@ const char *RenamesMap3To4::csharp_properties_renames[][2] = { { "Selectedframe", "SelectedFrame" }, // Theme { "SizeOverrideStretch", "Size2dOverrideStretch" }, // SubViewport { "SlipsOnSlope", "SlideOnSlope" }, // SeparationRayShape2D - { "SmoothingEnabled", "FollowSmoothingEnabled" }, // Camera2D - { "SmoothingSpeed", "FollowSmoothingSpeed" }, // Camera2D + { "SmoothingEnabled", "PositionSmoothingEnabled" }, // Camera2D + { "SmoothingSpeed", "PositionSmoothingSpeed" }, // Camera2D { "SsReflectionsDepthTolerance", "SsrDepthTolerance" }, // Environment { "SsReflectionsEnabled", "SsrEnabled" }, // Environment { "SsReflectionsFadeIn", "SsrFadeIn" }, // Environment diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index d0c2cb43a6..e27b977e9d 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -511,6 +511,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code } break; case GDScriptParser::Node::CALL: { const GDScriptParser::CallNode *call = static_cast<const GDScriptParser::CallNode *>(p_expression); + bool is_awaited = p_expression == awaited_node; GDScriptDataType type = _gdtype_from_datatype(call->get_datatype(), codegen.script); GDScriptCodeGenerator::Address result; if (p_root) { @@ -565,13 +566,13 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code } else if ((codegen.function_node && codegen.function_node->is_static) || call->function_name == "new") { GDScriptCodeGenerator::Address self; self.mode = GDScriptCodeGenerator::Address::CLASS; - if (within_await) { + if (is_awaited) { gen->write_call_async(result, self, call->function_name, arguments); } else { gen->write_call(result, self, call->function_name, arguments); } } else { - if (within_await) { + if (is_awaited) { gen->write_call_self_async(result, call->function_name, arguments); } else { gen->write_call_self(result, call->function_name, arguments); @@ -593,7 +594,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code if (r_error) { return GDScriptCodeGenerator::Address(); } - if (within_await) { + if (is_awaited) { gen->write_call_async(result, base, call->function_name, arguments); } else if (base.type.has_type && base.type.kind != GDScriptDataType::BUILTIN) { // Native method, use faster path. @@ -666,9 +667,10 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code const GDScriptParser::AwaitNode *await = static_cast<const GDScriptParser::AwaitNode *>(p_expression); GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(p_expression->get_datatype(), codegen.script)); - within_await = true; + GDScriptParser::ExpressionNode *previous_awaited_node = awaited_node; + awaited_node = await->to_await; GDScriptCodeGenerator::Address argument = _parse_expression(codegen, r_error, await->to_await); - within_await = false; + awaited_node = previous_awaited_node; if (r_error) { return GDScriptCodeGenerator::Address(); } diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h index 17c6cc8d2f..5328c17c73 100644 --- a/modules/gdscript/gdscript_compiler.h +++ b/modules/gdscript/gdscript_compiler.h @@ -137,7 +137,7 @@ class GDScriptCompiler { int err_column = 0; StringName source; String error; - bool within_await = false; + GDScriptParser::ExpressionNode *awaited_node = nullptr; public: static void convert_to_initializer_type(Variant &p_variant, const GDScriptParser::VariableNode *p_node); diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index e3ba290eb2..d93485a800 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -3748,6 +3748,14 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) { d["alphaMode"] = "BLEND"; } + Dictionary extensions; + if (base_material->get_shading_mode() == BaseMaterial3D::SHADING_MODE_UNSHADED) { + Dictionary mat_unlit; + extensions["KHR_materials_unlit"] = mat_unlit; + p_state->add_used_extension("KHR_materials_unlit"); + } + d["extensions"] = extensions; + materials.push_back(d); } if (!materials.size()) { @@ -3780,6 +3788,11 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> p_state) { if (d.has("extensions")) { pbr_spec_gloss_extensions = d["extensions"]; } + + if (pbr_spec_gloss_extensions.has("KHR_materials_unlit")) { + material->set_shading_mode(BaseMaterial3D::SHADING_MODE_UNSHADED); + } + if (pbr_spec_gloss_extensions.has("KHR_materials_pbrSpecularGlossiness")) { WARN_PRINT("Material uses a specular and glossiness workflow. Textures will be converted to roughness and metallic workflow, which may not be 100% accurate."); Dictionary sgm = pbr_spec_gloss_extensions["KHR_materials_pbrSpecularGlossiness"]; @@ -7440,6 +7453,7 @@ Error GLTFDocument::_parse_gltf_extensions(Ref<GLTFState> p_state) { supported_extensions.insert("KHR_lights_punctual"); supported_extensions.insert("KHR_materials_pbrSpecularGlossiness"); supported_extensions.insert("KHR_texture_transform"); + supported_extensions.insert("KHR_materials_unlit"); for (Ref<GLTFDocumentExtension> ext : document_extensions) { ERR_CONTINUE(ext.is_null()); Vector<String> ext_supported_extensions = ext->get_supported_extensions(); diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index d3c2415755..932e97c46b 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -58,6 +58,7 @@ #include "godotsharp_dirs.h" #include "managed_callable.h" #include "mono_gd/gd_mono_cache.h" +#include "servers/text_server.h" #include "signal_awaiter_utils.h" #include "utils/macros.h" #include "utils/naming_utils.h" @@ -374,6 +375,10 @@ String CSharpLanguage::validate_path(const String &p_path) const { if (keywords.find(class_name)) { return RTR("Class name can't be a reserved keyword"); } + if (!TS->is_valid_identifier(class_name)) { + return RTR("Class name must be a valid identifier"); + } + return ""; } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props index 0d0889c491..eea7520b05 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props @@ -14,6 +14,7 @@ <GodotProjectDir Condition=" '$(GodotProjectDir)' == '' ">$(MSBuildProjectDirectory)</GodotProjectDir> <GodotProjectDir>$([MSBuild]::EnsureTrailingSlash('$(GodotProjectDir)'))</GodotProjectDir> + <GodotProjectDirBase64>$([MSBuild]::ConvertToBase64('$(GodotProjectDir)'))</GodotProjectDirBase64> <!-- Custom output paths for Godot projects. In brief, 'bin\' and 'obj\' are moved to '$(GodotProjectDir)\.godot\mono\temp\'. --> <BaseOutputPath>$(GodotProjectDir).godot\mono\temp\bin\</BaseOutputPath> diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj index 8e78e0385d..2df838cfb8 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj @@ -7,6 +7,7 @@ <PropertyGroup> <!-- $(GodotProjectDir) would normally be defined by the Godot.NET.Sdk --> <GodotProjectDir>$(MSBuildProjectDirectory)</GodotProjectDir> + <GodotProjectDirBase64>$([MSBuild]::ConvertToBase64('$(GodotProjectDir)'))</GodotProjectDirBase64> <!-- For compiling GetGodotPropertyDefaultValues. --> <DefineConstants>$(DefineConstants);TOOLS</DefineConstants> </PropertyGroup> diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs index 41bf89e6d8..8be1151142 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs @@ -194,6 +194,32 @@ namespace Godot.SourceGenerators location?.SourceTree?.FilePath)); } + public static void ReportExportedMemberIsExplicitInterfaceImplementation( + GeneratorExecutionContext context, + ISymbol exportedMemberSymbol + ) + { + var locations = exportedMemberSymbol.Locations; + var location = locations.FirstOrDefault(l => l.SourceTree != null) ?? locations.FirstOrDefault(); + + string message = $"Attempted to export explicit interface property implementation: " + + $"'{exportedMemberSymbol.ToDisplayString()}'"; + + string description = $"{message}. Explicit interface implementations can't be exported." + + " Remove the '[Export]' attribute."; + + context.ReportDiagnostic(Diagnostic.Create( + new DiagnosticDescriptor(id: "GD0106", + title: message, + messageFormat: message, + category: "Usage", + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description), + location, + location?.SourceTree?.FilePath)); + } + public static void ReportSignalDelegateMissingSuffix( GeneratorExecutionContext context, INamedTypeSymbol delegateSymbol) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props index 7881ed0a8c..2a8ae7f958 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.props @@ -2,6 +2,7 @@ <ItemGroup> <!-- $(GodotProjectDir) is defined by Godot.NET.Sdk --> <CompilerVisibleProperty Include="GodotProjectDir" /> + <CompilerVisibleProperty Include="GodotProjectDirBase64" /> <CompilerVisibleProperty Include="GodotSourceGenerators" /> <CompilerVisibleProperty Include="IsGodotToolsProject" /> </ItemGroup> diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs index eae7e41da8..d14e3c3781 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs @@ -22,10 +22,17 @@ namespace Godot.SourceGenerators // NOTE: NotNullWhen diagnostics don't work on projects targeting .NET Standard 2.0 // ReSharper disable once ReplaceWithStringIsNullOrEmpty - if (!context.TryGetGlobalAnalyzerProperty("GodotProjectDir", out string? godotProjectDir) - || godotProjectDir!.Length == 0) + if (!context.TryGetGlobalAnalyzerProperty("GodotProjectDirBase64", out string? godotProjectDir) || godotProjectDir!.Length == 0) { - throw new InvalidOperationException("Property 'GodotProjectDir' is null or empty."); + if (!context.TryGetGlobalAnalyzerProperty("GodotProjectDir", out godotProjectDir) || godotProjectDir!.Length == 0) + { + throw new InvalidOperationException("Property 'GodotProjectDir' is null or empty."); + } + } + else + { + // Workaround for https://github.com/dotnet/roslyn/issues/51692 + godotProjectDir = Encoding.UTF8.GetString(Convert.FromBase64String(godotProjectDir)); } Dictionary<INamedTypeSymbol, IEnumerable<ClassDeclarationSyntax>> godotClasses = context diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs index b720fb93a3..d333c24451 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs @@ -113,7 +113,7 @@ namespace Godot.SourceGenerators var propertySymbols = members .Where(s => !s.IsStatic && s.Kind == SymbolKind.Property) .Cast<IPropertySymbol>() - .Where(s => !s.IsIndexer); + .Where(s => !s.IsIndexer && s.ExplicitInterfaceImplementations.Length == 0); var fieldSymbols = members .Where(s => !s.IsStatic && s.Kind == SymbolKind.Field && !s.IsImplicitlyDeclared) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs index 99a4c95e73..089ee3f196 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs @@ -151,6 +151,12 @@ namespace Godot.SourceGenerators continue; } + if (property.ExplicitInterfaceImplementations.Length > 0) + { + Common.ReportExportedMemberIsExplicitInterfaceImplementation(context, property); + continue; + } + var propertyType = property.Type; var marshalType = MarshalUtils.ConvertManagedTypeToMarshalType(propertyType, typeCache); diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs index 821f3af75f..d8c6f3a196 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs @@ -113,7 +113,7 @@ namespace Godot.SourceGenerators var propertySymbols = members .Where(s => !s.IsStatic && s.Kind == SymbolKind.Property) .Cast<IPropertySymbol>() - .Where(s => !s.IsIndexer); + .Where(s => !s.IsIndexer && s.ExplicitInterfaceImplementations.Length == 0); var fieldSymbols = members .Where(s => !s.IsStatic && s.Kind == SymbolKind.Field && !s.IsImplicitlyDeclared) diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index cbe5266f7e..83101c1443 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -1483,9 +1483,9 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output << MEMBER_BEGIN "public static GodotObject " CS_PROPERTY_SINGLETON "\n" INDENT1 "{\n" << INDENT2 "get\n" INDENT2 "{\n" INDENT3 "if (singleton == null)\n" - << INDENT4 "singleton = " C_METHOD_ENGINE_GET_SINGLETON "(typeof(" - << itype.proxy_name - << ").Name);\n" INDENT3 "return singleton;\n" INDENT2 "}\n" INDENT1 "}\n"; + << INDENT4 "singleton = " C_METHOD_ENGINE_GET_SINGLETON "(\"" + << itype.name + << "\");\n" INDENT3 "return singleton;\n" INDENT2 "}\n" INDENT1 "}\n"; output.append(MEMBER_BEGIN "private static readonly StringName " BINDINGS_NATIVE_NAME_FIELD " = \""); output.append(itype.name); diff --git a/platform/ios/godot_view.mm b/platform/ios/godot_view.mm index fafec79bf6..67e47092d8 100644 --- a/platform/ios/godot_view.mm +++ b/platform/ios/godot_view.mm @@ -39,7 +39,7 @@ #import <CoreMotion/CoreMotion.h> -static const int max_touches = 8; +static const int max_touches = 32; static const float earth_gravity = 9.80665; @interface GodotView () { diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index 3f713d2db3..e203dca005 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -277,11 +277,10 @@ def configure(env: "Environment"): env.Prepend(CPPPATH=["/usr/include/recastnavigation"]) env.Append(LIBS=["Recast"]) - if not env["builtin_embree"]: + if not env["builtin_embree"] and env["arch"] in ["x86_64", "arm64"]: # No pkgconfig file so far, hardcode expected lib name. env.Append(LIBS=["embree3"]) - ## Flags if env["fontconfig"]: if not env["use_sowrap"]: if os.system("pkg-config --exists fontconfig") == 0: # 0 means found diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp index 60b344b002..4cae1affc3 100644 --- a/scene/2d/back_buffer_copy.cpp +++ b/scene/2d/back_buffer_copy.cpp @@ -62,6 +62,7 @@ Rect2 BackBufferCopy::get_anchorable_rect() const { void BackBufferCopy::set_rect(const Rect2 &p_rect) { rect = p_rect; _update_copy_mode(); + item_rect_changed(); } Rect2 BackBufferCopy::get_rect() const { diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 2b90a3702f..fdd709c3cb 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -158,7 +158,7 @@ Transform2D Camera2D::get_camera_transform() { } } - if (follow_smoothing_enabled && !Engine::get_singleton()->is_editor_hint()) { + if (position_smoothing_enabled && !Engine::get_singleton()->is_editor_hint()) { real_t c = position_smoothing_speed * (process_callback == CAMERA2D_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time()); smoothed_camera_pos = ((camera_pos - smoothed_camera_pos) * c) + smoothed_camera_pos; ret_camera_pos = smoothed_camera_pos; @@ -186,7 +186,7 @@ Transform2D Camera2D::get_camera_transform() { Rect2 screen_rect(-screen_offset + ret_camera_pos, screen_size * zoom_scale); - if (!follow_smoothing_enabled || !limit_smoothing_enabled) { + if (!position_smoothing_enabled || !limit_smoothing_enabled) { if (screen_rect.position.x < limit[SIDE_LEFT]) { screen_rect.position.x = limit[SIDE_LEFT]; } @@ -617,18 +617,18 @@ real_t Camera2D::get_drag_horizontal_offset() const { void Camera2D::_set_old_smoothing(real_t p_enable) { //compatibility if (p_enable > 0) { - follow_smoothing_enabled = true; + position_smoothing_enabled = true; set_position_smoothing_speed(p_enable); } } void Camera2D::set_position_smoothing_enabled(bool p_enabled) { - follow_smoothing_enabled = p_enabled; + position_smoothing_enabled = p_enabled; notify_property_list_changed(); } bool Camera2D::is_position_smoothing_enabled() const { - return follow_smoothing_enabled; + return position_smoothing_enabled; } void Camera2D::set_custom_viewport(Node *p_viewport) { @@ -699,7 +699,7 @@ bool Camera2D::is_margin_drawing_enabled() const { } void Camera2D::_validate_property(PropertyInfo &p_property) const { - if (!follow_smoothing_enabled && p_property.name == "smoothing_speed") { + if (!position_smoothing_enabled && p_property.name == "position_smoothing_speed") { p_property.usage = PROPERTY_USAGE_NO_EDITOR; } if (!rotation_smoothing_enabled && p_property.name == "rotation_smoothing_speed") { @@ -801,7 +801,7 @@ void Camera2D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_bottom", PROPERTY_HINT_NONE, "suffix:px"), "set_limit", "get_limit", SIDE_BOTTOM); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "limit_smoothed"), "set_limit_smoothing_enabled", "is_limit_smoothing_enabled"); - ADD_GROUP("Follow Smoothing", "follow_smoothing_"); + ADD_GROUP("Position Smoothing", "position_smoothing_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "position_smoothing_enabled"), "set_position_smoothing_enabled", "is_position_smoothing_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "position_smoothing_speed", PROPERTY_HINT_NONE, "suffix:px/s"), "set_position_smoothing_speed", "get_position_smoothing_speed"); diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h index 2417953691..808529b0fb 100644 --- a/scene/2d/camera_2d.h +++ b/scene/2d/camera_2d.h @@ -67,7 +67,7 @@ protected: bool ignore_rotation = true; bool enabled = true; real_t position_smoothing_speed = 5.0; - bool follow_smoothing_enabled = false; + bool position_smoothing_enabled = false; real_t camera_angle = 0.0; real_t rotation_smoothing_speed = 5.0; diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 958e960ab2..084fb64a53 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -8798,11 +8798,19 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f _set_error(RTR("'hint_normal_roughness_texture' is not supported in gl_compatibility shaders.")); return ERR_PARSE_ERROR; } + if (String(shader_type_identifier) != "spatial") { + _set_error(vformat(RTR("'hint_normal_roughness_texture' is not supported in '%s' shaders."), shader_type_identifier)); + return ERR_PARSE_ERROR; + } } break; case TK_HINT_DEPTH_TEXTURE: { new_hint = ShaderNode::Uniform::HINT_DEPTH_TEXTURE; --texture_uniforms; --texture_binding; + if (String(shader_type_identifier) != "spatial") { + _set_error(vformat(RTR("'hint_depth_texture' is not supported in '%s' shaders."), shader_type_identifier)); + return ERR_PARSE_ERROR; + } } break; case TK_FILTER_NEAREST: { new_filter = FILTER_NEAREST; |
