diff options
39 files changed, 562 insertions, 226 deletions
diff --git a/SConstruct b/SConstruct index 2763f3f578..8b39f120b4 100644 --- a/SConstruct +++ b/SConstruct @@ -645,7 +645,7 @@ if selected_platform in platform_list: print( "Detected mingw version is not using posix threads. Only posix " "version of mingw is supported. " - 'Use "update-alternatives --config <platform>-w64-mingw32-[gcc|g++]" ' + 'Use "update-alternatives --config x86_64-w64-mingw32-g++" ' "to switch to posix threads." ) Exit(255) diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 99ec1e1ed8..847ae14041 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/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 2519928ea3..c91d653692 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -2952,6 +2952,10 @@ void ThemeTypeEditor::_item_remove_cbk(int p_data_type, String p_item_name) { ur->add_undo_method(*edited_theme, "set_font", p_item_name, edited_type, Ref<Font>()); } } break; + case Theme::DATA_TYPE_FONT_SIZE: { + ur->add_do_method(*edited_theme, "clear_font_size", p_item_name, edited_type); + ur->add_undo_method(*edited_theme, "set_font_size", p_item_name, edited_type, edited_theme->get_font_size(p_item_name, edited_type)); + } break; case Theme::DATA_TYPE_ICON: { ur->add_do_method(*edited_theme, "clear_icon", p_item_name, edited_type); if (edited_theme->has_icon(p_item_name, edited_type)) { diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp index 6aa403de17..6abf0ccacc 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)?(\\(\\))?\\]"); @@ -139,6 +142,9 @@ public: LocalVector<RegEx *> class_gd_regexes; LocalVector<RegEx *> class_shader_regexes; + // Keycode. + RegEx input_map_keycode = RegEx("\\b,\"((physical_)?)scancode\":(\\d+)\\b"); + LocalVector<RegEx *> class_regexes; RegEx class_temp_tscn = RegEx("\\bTEMP_RENAMED_CLASS.tscn\\b"); @@ -304,7 +310,7 @@ bool ProjectConverter3To4::convert() { maximum_line_length = 10000; // Use only for tests bigger value, to not break them. ERR_FAIL_COND_V_MSG(!test_array_names(), false, "Cannot start converting due to problems with data in arrays."); - ERR_FAIL_COND_V_MSG(!test_conversion(reg_container), false, "Cannot start converting due to problems with converting arrays."); + ERR_FAIL_COND_V_MSG(!test_conversion(reg_container), false, "Aborting conversion due to validation tests failing"); maximum_line_length = cached_maximum_line_length; @@ -334,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)); @@ -361,67 +371,71 @@ 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. + fix_tool_declaration(source_lines, reg_container); + + 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_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 { @@ -429,7 +443,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; } @@ -444,7 +463,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. @@ -483,7 +502,7 @@ bool ProjectConverter3To4::validate_conversion() { maximum_line_length = 10000; // To avoid breaking the tests, only use this for the their larger value. ERR_FAIL_COND_V_MSG(!test_array_names(), false, "Cannot start converting due to problems with data in arrays."); - ERR_FAIL_COND_V_MSG(!test_conversion(reg_container), false, "Cannot start converting due to problems with converting arrays."); + ERR_FAIL_COND_V_MSG(!test_conversion(reg_container), false, "Aborting conversion due to validation tests failing"); maximum_line_length = cached_maximum_line_length; @@ -492,7 +511,7 @@ bool ProjectConverter3To4::validate_conversion() { { String conventer_text = "; Project was converted by built-in tool to Godot 4.0"; - ERR_FAIL_COND_V_MSG(!FileAccess::exists("project.godot"), false, "Current directory doesn't contains any Godot 3 project"); + ERR_FAIL_COND_V_MSG(!FileAccess::exists("project.godot"), false, "Current directory doesn't contain any Godot 3 project"); Error err = OK; String project_godot_content = FileAccess::get_file_as_string("project.godot", &err); @@ -587,6 +606,7 @@ bool ProjectConverter3To4::validate_conversion() { } else if (file_name.ends_with("project.godot")) { changed_elements.append_array(check_for_rename_common(RenamesMap3To4::project_godot_renames, reg_container.project_godot_regexes, lines)); changed_elements.append_array(check_for_rename_common(RenamesMap3To4::builtin_types_renames, reg_container.builtin_types_regexes, lines)); + changed_elements.append_array(check_for_rename_input_map_scancode(lines, reg_container)); changed_elements.append_array(check_for_rename_common(RenamesMap3To4::input_map_renames, reg_container.input_map_regexes, lines)); } else if (file_name.ends_with(".csproj")) { // TODO @@ -674,9 +694,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)); @@ -684,8 +718,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)); @@ -694,7 +729,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)); @@ -706,6 +742,10 @@ bool ProjectConverter3To4::test_conversion_basic(String name, String expected, c bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { bool valid = true; + valid = valid && test_conversion_with_regex("tool", "@tool", &ProjectConverter3To4::fix_tool_declaration, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\n tool", "\n tool", &ProjectConverter3To4::fix_tool_declaration, "gdscript keyword", reg_container); + valid = valid && test_conversion_with_regex("\n\ntool", "@tool\n\n", &ProjectConverter3To4::fix_tool_declaration, "gdscript keyword", reg_container); + valid = valid && test_conversion_basic("TYPE_REAL", "TYPE_FLOAT", RenamesMap3To4::enum_renames, reg_container.enum_regexes, "enum"); valid = valid && test_conversion_basic("can_instance", "can_instantiate", RenamesMap3To4::gdscript_function_renames, reg_container.gdscript_function_regexes, "gdscript function"); @@ -730,9 +770,9 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { // Custom Renames. - valid = valid && test_conversion_with_regex("(Connect(A,B,C,D,E,F,G) != OK):", "(Connect(A,new Callable(B,C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename csharp", reg_container); - valid = valid && test_conversion_with_regex("(Disconnect(A,B,C) != OK):", "(Disconnect(A,new Callable(B,C)) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename csharp", reg_container); - valid = valid && test_conversion_with_regex("(IsConnected(A,B,C) != OK):", "(IsConnected(A,new Callable(B,C)) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename", reg_container); + valid = valid && test_conversion_with_regex("(Connect(A,B,C,D,E,F,G) != OK):", "(Connect(A, new Callable(B, C), D, E, F, G) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename csharp", reg_container); + valid = valid && test_conversion_with_regex("(Disconnect(A,B,C) != OK):", "(Disconnect(A, new Callable(B, C)) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename csharp", reg_container); + valid = valid && test_conversion_with_regex("(IsConnected(A,B,C) != OK):", "(IsConnected(A, new Callable(B, C)) != OK):", &ProjectConverter3To4::rename_csharp_functions, "custom rename", reg_container); valid = valid && test_conversion_with_regex("[Remote]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); valid = valid && test_conversion_with_regex("[RemoteSync]", "[RPC(MultiplayerAPI.RPCMode.AnyPeer, CallLocal = true)]", &ProjectConverter3To4::rename_csharp_attributes, "custom rename csharp", reg_container); @@ -788,11 +828,11 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { valid = valid && test_conversion_gdscript_builtin("list_dir_begin( a )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("list_dir_begin( )", "list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("sort_custom( a , b )", "sort_custom(Callable(a,b))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("sort_custom( a , b )", "sort_custom(Callable(a, b))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("func c(var a, var b)", "func c(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("draw_line(1, 2, 3, 4, 5)", "draw_line(1,2,3,4)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("draw_line(1, 2, 3, 4, 5)", "draw_line(1, 2, 3, 4)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("\timage.lock()", "\tfalse # image.lock() # TODOConverter40, Image no longer requires locking, `false` helps to not break one line if/else, so it can freely be removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("\timage.unlock()", "\tfalse # image.unlock() # TODOConverter40, Image no longer requires locking, `false` helps to not break one line if/else, so it can freely be removed", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); @@ -816,9 +856,6 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { valid = valid && test_conversion_with_regex("\texport_dialog", "\texport_dialog", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); valid = valid && test_conversion_with_regex("export", "@export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); valid = valid && test_conversion_with_regex(" export", " export", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid && test_conversion_with_regex("tool", "@tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid && test_conversion_with_regex("\n tool", "\n tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); - valid = valid && test_conversion_with_regex("\n\ntool", "\n\n@tool", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); valid = valid && test_conversion_with_regex("\n\nremote func", "\n\n@rpc(\"any_peer\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); valid = valid && test_conversion_with_regex("\n\nremotesync func", "\n\n@rpc(\"any_peer\", \"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); valid = valid && test_conversion_with_regex("\n\nsync func", "\n\n@rpc(\"any_peer\", \"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container); @@ -838,8 +875,8 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { valid = valid && test_conversion_gdscript_builtin("yield(this, \"timeout\")", "await this.timeout", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("yield(this, \\\"timeout\\\")", "await this.timeout", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, true); - valid = valid && test_conversion_gdscript_builtin(" Transform.xform(Vector3(a,b,c)) ", " Transform * Vector3(a,b,c) ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin(" Transform.xform_inv(Vector3(a,b,c)) ", " Vector3(a,b,c) * Transform ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin(" Transform.xform(Vector3(a,b,c) + Vector3.UP) ", " Transform * (Vector3(a,b,c) + Vector3.UP) ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin(" Transform.xform_inv(Vector3(a,b,c) + Vector3.UP) ", " (Vector3(a,b,c) + Vector3.UP) * Transform ", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("export(float) var lifetime = 3.0", "export var lifetime: float = 3.0", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("export(String, 'AnonymousPro', 'CourierPrime') var _font_name = 'AnonymousPro'", "export var _font_name = 'AnonymousPro' # (String, 'AnonymousPro', 'CourierPrime')", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); // TODO, this is only a workaround @@ -864,27 +901,30 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { valid = valid && test_conversion_gdscript_builtin("'.a'", "'.a'", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("\t._input(_event)", "\tsuper._input(_event)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C) != OK):", "(connect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,D) != OK):", "(connect(A,Callable(B,C).bind(D)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,[D]) != OK):", "(connect(A,Callable(B,C).bind(D)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,[D,E]) != OK):", "(connect(A,Callable(B,C).bind(D,E)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,[D,E],F) != OK):", "(connect(A,Callable(B,C).bind(D,E),F) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,D,E) != OK):", "(connect(A,Callable(B,C).bind(D),E) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C) != OK):", "(connect(A, Callable(B, C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,D) != OK):", "(connect(A, Callable(B, C).bind(D)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,[D]) != OK):", "(connect(A, Callable(B, C).bind(D)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,[D,E]) != OK):", "(connect(A, Callable(B, C).bind(D,E)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,[D,E],F) != OK):", "(connect(A, Callable(B, C).bind(D,E), F) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(connect(A,B,C,D,E) != OK):", "(connect(A, Callable(B, C).bind(D), E) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("(start(A,B) != OK):", "(start(Callable(A,B)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(start(A,B) != OK):", "(start(Callable(A, B)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("func start(A,B):", "func start(A,B):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("(start(A,B,C,D,E,F,G) != OK):", "(start(Callable(A,B).bind(C),D,E,F,G) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("disconnect(A,B,C) != OK):", "disconnect(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("is_connected(A,B,C) != OK):", "is_connected(A,Callable(B,C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("is_connected(A,B,C))", "is_connected(A,Callable(B,C)))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(start(A,B,C,D,E,F,G) != OK):", "(start(Callable(A, B).bind(C), D, E, F, G) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("disconnect(A,B,C) != OK):", "disconnect(A, Callable(B, C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("is_connected(A,B,C) != OK):", "is_connected(A, Callable(B, C)) != OK):", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("is_connected(A,B,C))", "is_connected(A, Callable(B, C)))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("(tween_method(A,B,C,D,E).foo())", "(tween_method(Callable(A,B),C,D,E).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("(tween_method(A,B,C,D,E,[F,G]).foo())", "(tween_method(Callable(A,B).bind(F,G),C,D,E).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("(tween_callback(A,B).foo())", "(tween_callback(Callable(A,B)).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - 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("(tween_method(A,B,C,D,E).foo())", "(tween_method(Callable(A, B), C, D, E).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(tween_method(A,B,C,D,E,[F,G]).foo())", "(tween_method(Callable(A, B).bind(F,G), C, D, E).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("(tween_callback(A,B).foo())", "(tween_callback(Callable(A, B)).foo())", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + 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); @@ -894,18 +934,18 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { valid = valid && test_conversion_gdscript_builtin("create_from_image(aa, bb)", "create_from_image(aa) #,bb", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("q_ImageTexture.create_from_image(variable1, variable2)", "q_ImageTexture.create_from_image(variable1) #,variable2", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("set_cell_item(a, b, c, d ,e) # AA", "set_cell_item( Vector3(a,b,c) ,d,e) # AA", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("set_cell_item(a, b, c, d ,e) # AA", "set_cell_item(Vector3(a, b, c), d, e) # AA", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("set_cell_item(a, b)", "set_cell_item(a, b)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("get_cell_item_orientation(a, b,c)", "get_cell_item_orientation(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("get_cell_item(a, b,c)", "get_cell_item(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("map_to_world(a, b,c)", "map_to_local(Vector3i(a,b,c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("get_cell_item_orientation(a, b,c)", "get_cell_item_orientation(Vector3i(a, b, c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("get_cell_item(a, b,c)", "get_cell_item(Vector3i(a, b, c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("map_to_world(a, b,c)", "map_to_local(Vector3i(a, b, c))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("PackedStringArray(req_godot).join('.')", "'.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("=PackedStringArray(req_godot).join('.')", "='.'.join(PackedStringArray(req_godot))", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("apply_force(position, impulse)", "apply_force(impulse, position)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("apply_impulse(position, impulse)", "apply_impulse(impulse, position)", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); - valid = valid && test_conversion_gdscript_builtin("draw_rect(a,b,c,d,e).abc", "draw_rect(a,b,c,d).abc# e) TODOGODOT4 Antialiasing argument is missing", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); + valid = valid && test_conversion_gdscript_builtin("draw_rect(a,b,c,d,e).abc", "draw_rect(a, b, c, d).abc# e) TODOGODOT4 Antialiasing argument is missing", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("get_focus_owner()", "get_viewport().gui_get_focus_owner()", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("button.pressed = 1", "button.button_pressed = 1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); valid = valid && test_conversion_gdscript_builtin("button.pressed=1", "button.button_pressed=1", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false); @@ -913,12 +953,18 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) { valid = valid && test_conversion_with_regex("AAA Color.white AF", "AAA Color.WHITE AF", &ProjectConverter3To4::rename_colors, "custom rename", reg_container); + // Note: Do not change to *scancode*, it is applied before that conversion. + valid = valid && test_conversion_with_regex("\"device\":-1,\"scancode\":16777231,\"physical_scancode\":16777232", "\"device\":-1,\"scancode\":4194319,\"physical_scancode\":4194320", &ProjectConverter3To4::rename_input_map_scancode, "custom rename", reg_container); + valid = valid && test_conversion_with_regex("\"device\":-1,\"scancode\":65,\"physical_scancode\":66", "\"device\":-1,\"scancode\":65,\"physical_scancode\":66", &ProjectConverter3To4::rename_input_map_scancode, "custom rename", reg_container); + // Custom rule conversion { 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); @@ -1255,13 +1301,13 @@ String ProjectConverter3To4::connect_arguments(const Vector<String> &arguments, String value; if (arguments.size() > 0 && from != 0 && from < to) { - value = ","; + value = ", "; } for (int i = from; i < to; i++) { value += arguments[i]; if (i != to - 1) { - value += ','; + value += ", "; } } return value; @@ -1342,8 +1388,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++) { @@ -1375,8 +1426,24 @@ 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::fix_tool_declaration(Vector<SourceLine> &source_lines, const RegExContainer ®_container) { + // In godot4, "tool" became "@tool" and must be located at the top of the file + for (int i = 0; i < source_lines.size(); ++i) { + if (source_lines[i].line == "tool") { + source_lines.remove_at(i); + source_lines.insert(0, { "@tool", false }); + return; // assuming there's at most 1 tool declaration + } + } +} + +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])) { @@ -1443,8 +1510,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); } @@ -1753,7 +1825,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 2) { - line = line.substr(0, start) + "sort_custom(Callable(" + parts[0] + "," + parts[1] + "))" + line.substr(end + start); + line = line.substr(0, start) + "sort_custom(Callable(" + parts[0] + ", " + parts[1] + "))" + line.substr(end + start); } } } @@ -1767,14 +1839,14 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai } } - // -- draw_line(1,2,3,4,5) -> draw_line(1,2,3,4) CanvasItem + // -- draw_line(1,2,3,4,5) -> draw_line(1, 2, 3, 4) CanvasItem if (line.contains("draw_line(")) { int start = line.find("draw_line("); int end = get_end_parenthesis(line.substr(start)) + 1; if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 5) { - line = line.substr(0, start) + "draw_line(" + parts[0] + "," + parts[1] + "," + parts[2] + "," + parts[3] + ")" + line.substr(end + start); + line = line.substr(0, start) + "draw_line(" + parts[0] + ", " + parts[1] + ", " + parts[2] + ", " + parts[3] + ")" + line.substr(end + start); } } } @@ -1831,7 +1903,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 1) { - line = line.substr(0, start) + " * " + parts[0] + line.substr(end + start); + line = line.substr(0, start) + " * (" + parts[0] + ")" + line.substr(end + start); } } } @@ -1846,13 +1918,13 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai int start2 = line.find(object_exec + ".xform"); Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 1) { - line = line.substr(0, start2) + parts[0] + " * " + object_exec + line.substr(end + start); + line = line.substr(0, start2) + "(" + parts[0] + ") * " + object_exec + line.substr(end + start); } } } } - // -- "(connect(A,B,C,D,E) != OK):", "(connect(A,Callable(B,C).bind(D),E) Object + // -- "(connect(A,B,C,D,E) != OK):", "(connect(A, Callable(B, C).bind(D), E) Object if (line.contains("connect(")) { int start = line.find("connect("); // Protection from disconnect @@ -1861,9 +1933,9 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { - line = line.substr(0, start) + "connect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); + line = line.substr(0, start) + "connect(" + parts[0] + ", Callable(" + parts[1] + ", " + parts[2] + "))" + line.substr(end + start); } else if (parts.size() >= 4) { - line = line.substr(0, start) + "connect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + ").bind(" + parts[3].lstrip("[").rstrip("]") + ")" + connect_arguments(parts, 4) + ")" + line.substr(end + start); + line = line.substr(0, start) + "connect(" + parts[0] + ", Callable(" + parts[1] + ", " + parts[2] + ").bind(" + parts[3].lstrip(" [").rstrip("] ") + ")" + connect_arguments(parts, 4) + ")" + line.substr(end + start); } } } @@ -1875,7 +1947,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { - line = line.substr(0, start) + "disconnect(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); + line = line.substr(0, start) + "disconnect(" + parts[0] + ", Callable(" + parts[1] + ", " + parts[2] + "))" + line.substr(end + start); } } } @@ -1886,7 +1958,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { - line = line.substr(0, start) + "is_connected(" + parts[0] + ",Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); + line = line.substr(0, start) + "is_connected(" + parts[0] + ", Callable(" + parts[1] + ", " + parts[2] + "))" + line.substr(end + start); } } } @@ -1898,9 +1970,9 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 5) { - line = line.substr(0, start) + "tween_method(Callable(" + parts[0] + "," + parts[1] + ")," + parts[2] + "," + parts[3] + "," + parts[4] + ")" + line.substr(end + start); + line = line.substr(0, start) + "tween_method(Callable(" + parts[0] + ", " + parts[1] + "), " + parts[2] + ", " + parts[3] + ", " + parts[4] + ")" + line.substr(end + start); } else if (parts.size() >= 6) { - line = line.substr(0, start) + "tween_method(Callable(" + parts[0] + "," + parts[1] + ").bind(" + connect_arguments(parts, 5).substr(1).lstrip("[").rstrip("]") + ")," + parts[2] + "," + parts[3] + "," + parts[4] + ")" + line.substr(end + start); + line = line.substr(0, start) + "tween_method(Callable(" + parts[0] + ", " + parts[1] + ").bind(" + connect_arguments(parts, 5).substr(1).lstrip(" [").rstrip("] ") + "), " + parts[2] + ", " + parts[3] + ", " + parts[4] + ")" + line.substr(end + start); } } } @@ -1911,14 +1983,14 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 2) { - line = line.substr(0, start) + "tween_callback(Callable(" + parts[0] + "," + parts[1] + "))" + line.substr(end + start); + line = line.substr(0, start) + "tween_callback(Callable(" + parts[0] + ", " + parts[1] + "))" + line.substr(end + start); } else if (parts.size() >= 3) { - line = line.substr(0, start) + "tween_callback(Callable(" + parts[0] + "," + parts[1] + ").bind(" + connect_arguments(parts, 2).substr(1).lstrip("[").rstrip("]") + "))" + line.substr(end + start); + line = line.substr(0, start) + "tween_callback(Callable(" + parts[0] + ", " + parts[1] + ").bind(" + connect_arguments(parts, 2).substr(1).lstrip(" [").rstrip("] ") + "))" + line.substr(end + start); } } } - // -- start(a,b) -> start(Callable(a,b)) Thread - // -- start(a,b,c,d) -> start(Callable(a,b).bind(c),d) Thread + // -- start(a,b) -> start(Callable(a, b)) Thread + // -- start(a,b,c,d) -> start(Callable(a, b).bind(c), d) Thread if (line.contains("start(")) { int start = line.find("start("); int end = get_end_parenthesis(line.substr(start)) + 1; @@ -1927,24 +1999,25 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 2) { - line = line.substr(0, start) + "start(Callable(" + parts[0] + "," + parts[1] + "))" + line.substr(end + start); + line = line.substr(0, start) + "start(Callable(" + parts[0] + ", " + parts[1] + "))" + line.substr(end + start); } else if (parts.size() >= 3) { - line = line.substr(0, start) + "start(Callable(" + parts[0] + "," + parts[1] + ").bind(" + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start); + line = line.substr(0, start) + "start(Callable(" + parts[0] + ", " + parts[1] + ").bind(" + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start); } } } } - // -- 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("); @@ -1974,7 +2047,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() > 2) { - line = line.substr(0, start) + "set_cell_item( Vector3(" + parts[0] + "," + parts[1] + "," + parts[2] + ") " + connect_arguments(parts, 3) + ")" + line.substr(end + start); + line = line.substr(0, start) + "set_cell_item(Vector3(" + parts[0] + ", " + parts[1] + ", " + parts[2] + ")" + connect_arguments(parts, 3).lstrip(" ") + ")" + line.substr(end + start); } } } @@ -1985,7 +2058,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { - line = line.substr(0, start) + "get_cell_item(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start); + line = line.substr(0, start) + "get_cell_item(Vector3i(" + parts[0] + ", " + parts[1] + ", " + parts[2] + "))" + line.substr(end + start); } } } @@ -1996,7 +2069,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { - line = line.substr(0, start) + "get_cell_item_orientation(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start); + line = line.substr(0, start) + "get_cell_item_orientation(Vector3i(" + parts[0] + ", " + parts[1] + ", " + parts[2] + "))" + line.substr(end + start); } } } @@ -2029,7 +2102,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { - line = line.substr(0, start) + "map_to_local(Vector3i(" + parts[0] + "," + parts[1] + "," + parts[2] + "))" + line.substr(end + start); + line = line.substr(0, start) + "map_to_local(Vector3i(" + parts[0] + ", " + parts[1] + ", " + parts[2] + "))" + line.substr(end + start); } else if (parts.size() == 1) { line = line.substr(0, start) + "map_to_local(" + parts[0] + ")" + line.substr(end + start); } @@ -2067,7 +2140,7 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 5) { - line = line.substr(0, start) + "draw_rect(" + parts[0] + "," + parts[1] + "," + parts[2] + "," + parts[3] + ")" + line.substr(end + start) + "# " + parts[4] + ") TODOGODOT4 Antialiasing argument is missing"; + line = line.substr(0, start) + "draw_rect(" + parts[0] + ", " + parts[1] + ", " + parts[2] + ", " + parts[3] + ")" + line.substr(end + start) + "# " + parts[4] + ") TODOGODOT4 Antialiasing argument is missing"; } } } @@ -2195,6 +2268,10 @@ void ProjectConverter3To4::process_gdscript_line(String &line, const RegExContai if (line.contains("_unhandled_key_input(event: InputEventKey)")) { line = line.replace("_unhandled_key_input(event: InputEventKey)", "_unhandled_key_input(event: InputEvent)"); } + + if (line.contains("Engine.editor_hint")) { + line = line.replace("Engine.editor_hint", "Engine.is_editor_hint()"); + } } void ProjectConverter3To4::process_csharp_line(String &line, const RegExContainer ®_container) { @@ -2220,7 +2297,7 @@ void ProjectConverter3To4::process_csharp_line(String &line, const RegExContaine if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() >= 3) { - line = line.substr(0, start) + "Connect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start); + line = line.substr(0, start) + "Connect(" + parts[0] + ", new Callable(" + parts[1] + ", " + parts[2] + ")" + connect_arguments(parts, 3) + ")" + line.substr(end + start); } } } @@ -2232,7 +2309,7 @@ void ProjectConverter3To4::process_csharp_line(String &line, const RegExContaine if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { - line = line.substr(0, start) + "Disconnect(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); + line = line.substr(0, start) + "Disconnect(" + parts[0] + ", new Callable(" + parts[1] + ", " + parts[2] + "))" + line.substr(end + start); } } } @@ -2243,14 +2320,19 @@ void ProjectConverter3To4::process_csharp_line(String &line, const RegExContaine if (end > -1) { Vector<String> parts = parse_arguments(line.substr(start, end)); if (parts.size() == 3) { - line = line.substr(0, start) + "IsConnected(" + parts[0] + ",new Callable(" + parts[1] + "," + parts[2] + "))" + line.substr(end + start); + line = line.substr(0, start) + "IsConnected(" + parts[0] + ", new Callable(" + parts[1] + ", " + parts[2] + "))" + line.substr(end + start); } } } } -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); } @@ -2275,10 +2357,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); @@ -2340,14 +2427,16 @@ 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); - } if (line.contains("export")) { line = reg_container.keyword_gdscript_export_single.sub(line, "@export", true); } @@ -2495,10 +2584,73 @@ Vector<String> ProjectConverter3To4::check_for_rename_gdscript_keywords(Vector<S return found_renames; } -void ProjectConverter3To4::custom_rename(Vector<String> &lines, String from, String to) { +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 (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); + + for (int i = 0; i < reg_match.size(); ++i) { + Ref<RegExMatch> match = reg_match[i]; + PackedStringArray strings = match->get_strings(); + int key = strings[3].to_int(); + + if (key & old_spkey) { + // Create new key, clearing old Special Key and setting new one. + key = (key & ~old_spkey) | (int)Key::SPECIAL; + + line = line.replace(strings[0], String(",\"") + strings[1] + "scancode\":" + String::num_int64(key)); + } + } + } + } +} + +Vector<String> ProjectConverter3To4::check_for_rename_input_map_scancode(Vector<String> &lines, const RegExContainer ®_container) { + Vector<String> found_renames; + + // The old Special Key, now colliding with CMD_OR_CTRL. + const int old_spkey = (1 << 24); + + int current_line = 1; + for (String &line : lines) { + if (uint64_t(line.length()) <= maximum_line_length) { + TypedArray<RegExMatch> reg_match = reg_container.input_map_keycode.search_all(line); + + for (int i = 0; i < reg_match.size(); ++i) { + Ref<RegExMatch> match = reg_match[i]; + PackedStringArray strings = match->get_strings(); + int key = strings[3].to_int(); + + if (key & old_spkey) { + // Create new key, clearing old Special Key and setting new one. + key = (key & ~old_spkey) | (int)Key::SPECIAL; + + found_renames.append(line_formatter(current_line, strings[3], String::num_int64(key), line)); + } + } + } + current_line++; + } + return found_renames; +} + +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); } @@ -2524,8 +2676,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])) { @@ -2595,10 +2752,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 420dd79d72..134273b4be 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,30 +71,35 @@ class ProjectConverter3To4 { uint64_t maximum_file_size; uint64_t maximum_line_length; - void rename_colors(Vector<String> &lines, const RegExContainer ®_container); + void fix_tool_declaration(Vector<SourceLine> &source_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 custom_rename(Vector<String> &lines, String from, String to); + 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<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(); @@ -102,11 +112,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/property_selector.cpp b/editor/property_selector.cpp index b756cdb8ed..ec323b5853 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -124,7 +124,7 @@ void PropertySelector::_update_search() { bool found = false; - Ref<Texture2D> type_icons[Variant::VARIANT_MAX] = { + Ref<Texture2D> type_icons[] = { search_options->get_theme_icon(SNAME("Variant"), SNAME("EditorIcons")), search_options->get_theme_icon(SNAME("bool"), SNAME("EditorIcons")), search_options->get_theme_icon(SNAME("int"), SNAME("EditorIcons")), @@ -137,11 +137,14 @@ void PropertySelector::_update_search() { search_options->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")), search_options->get_theme_icon(SNAME("Vector3i"), SNAME("EditorIcons")), search_options->get_theme_icon(SNAME("Transform2D"), SNAME("EditorIcons")), + search_options->get_theme_icon(SNAME("Vector4"), SNAME("EditorIcons")), + search_options->get_theme_icon(SNAME("Vector4"), SNAME("EditorIcons")), // Vector4i, needs icon. search_options->get_theme_icon(SNAME("Plane"), SNAME("EditorIcons")), search_options->get_theme_icon(SNAME("Quaternion"), SNAME("EditorIcons")), search_options->get_theme_icon(SNAME("AABB"), SNAME("EditorIcons")), search_options->get_theme_icon(SNAME("Basis"), SNAME("EditorIcons")), search_options->get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")), + search_options->get_theme_icon(SNAME("Variant"), SNAME("EditorIcons")), // Projection, needs icon. search_options->get_theme_icon(SNAME("Color"), SNAME("EditorIcons")), search_options->get_theme_icon(SNAME("StringName"), SNAME("EditorIcons")), search_options->get_theme_icon(SNAME("NodePath"), SNAME("EditorIcons")), @@ -161,6 +164,7 @@ void PropertySelector::_update_search() { search_options->get_theme_icon(SNAME("PackedVector3Array"), SNAME("EditorIcons")), search_options->get_theme_icon(SNAME("PackedColorArray"), SNAME("EditorIcons")) }; + static_assert((sizeof(type_icons) / sizeof(type_icons[0])) == Variant::VARIANT_MAX, "Number of type icons doesn't match the number of Variant types."); for (const PropertyInfo &E : props) { if (E.usage == PROPERTY_USAGE_CATEGORY) { diff --git a/editor/renames_map_3_to_4.cpp b/editor/renames_map_3_to_4.cpp index 90c8709c3b..b956930c0e 100644 --- a/editor/renames_map_3_to_4.cpp +++ b/editor/renames_map_3_to_4.cpp @@ -387,7 +387,6 @@ const char *RenamesMap3To4::gdscript_function_renames[][2] = { { "get_unit_db", "get_volume_db" }, // AudioStreamPlayer3D { "get_unit_offset", "get_progress_ratio" }, // PathFollow2D, PathFollow3D { "get_use_in_baked_light", "is_baking_navigation" }, // GridMap - { "get_used_cells_by_id", "get_used_cells" }, // TileMap { "get_v_scrollbar", "get_v_scroll_bar" }, // ScrollContainer { "get_visible_name", "_get_visible_name" }, // EditorImportPlugin { "get_window_layout", "_get_window_layout" }, // EditorPlugin @@ -721,7 +720,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 @@ -795,7 +794,6 @@ const char *RenamesMap3To4::csharp_function_renames[][2] = { { "GetUnitDb", "GetVolumeDb" }, // AudioStreamPlayer3D { "GetUnitOffset", "GetProgressRatio" }, // PathFollow2D, PathFollow3D { "GetUseInBakedLight", "IsBakingNavigation" }, // GridMap - { "GetUsedCellsById", "GetUsedCells" }, // TileMap { "GetVScrollbar", "GetVScrollBar" }, // ScrollContainer { "GetVisibleName", "_GetVisibleName" }, // EditorImportPlugin { "GetWindowLayout", "_GetWindowLayout" }, // EditorPlugin @@ -907,12 +905,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 @@ -1084,6 +1082,7 @@ const char *RenamesMap3To4::gdscript_properties_renames[][2] = { { "files_disabled", "file_disabled_color" }, // Theme { "folder_icon_modulate", "folder_icon_color" }, // Theme { "global_rate_scale", "playback_speed_scale" }, // AudioServer + { "global_translation", "global_position" }, // Node3D { "gravity_distance_scale", "gravity_point_unit_distance" }, // Area(2D/3D) { "gravity_vec", "gravity_direction" }, // Area(2D/3D) { "hint_tooltip", "tooltip_text" }, // Control @@ -1122,7 +1121,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 +1214,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 @@ -1478,6 +1477,7 @@ const char *RenamesMap3To4::class_renames[][2] = { { "CubeMesh", "BoxMesh" }, { "CylinderShape", "CylinderShape3D" }, { "DirectionalLight", "DirectionalLight3D" }, + { "Directory", "DirAccess" }, { "DynamicFont", "FontFile" }, { "DynamicFontData", "FontFile" }, { "EditorNavigationMeshGenerator", "NavigationMeshGenerator" }, @@ -1520,6 +1520,7 @@ const char *RenamesMap3To4::class_renames[][2] = { { "NavigationPolygonInstance", "NavigationRegion2D" }, { "NavigationRegion", "NavigationRegion3D" }, { "NavigationServer", "NavigationServer3D" }, + { "NetworkedMultiplayerCustom", "MultiplayerPeerExtension" }, { "NetworkedMultiplayerENet", "ENetMultiplayerPeer" }, { "NetworkedMultiplayerPeer", "MultiplayerPeer" }, { "Occluder", "OccluderInstance3D" }, 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/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index 7dcdc8e7cf..a736e36c6a 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -297,13 +297,14 @@ static bool _test_blender_path(const String &p_path, String *r_err = nullptr) { } return false; } - - if (pipe.find("Blender ") != 0) { + int bl = pipe.find("Blender "); + if (bl == -1) { if (r_err) { *r_err = vformat(TTR("Unexpected --version output from Blender binary at: %s"), path); } return false; } + pipe = pipe.substr(bl); pipe = pipe.replace_first("Blender ", ""); int pp = pipe.find("."); if (pp == -1) { 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 aad8ab9a57..1dbf6b3471 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -57,6 +57,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" @@ -366,6 +367,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.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/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/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp index 79e8c3a6d6..ee9687cf3d 100644 --- a/modules/navigation/godot_navigation_server.cpp +++ b/modules/navigation/godot_navigation_server.cpp @@ -757,7 +757,7 @@ COMMAND_1(free, RID, p_object) { agent_owner.free(p_object); } else { - ERR_FAIL_COND("Attempted to free a NavigationServer RID that did not exist (or was already freed)."); + ERR_PRINT("Attempted to free a NavigationServer RID that did not exist (or was already freed)."); } } diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 50aea3da2e..3463cb5d9d 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -4313,7 +4313,7 @@ double TextServerAdvanced::_shaped_text_fit_to_width(const RID &p_shaped, double elongation_count++; } } - if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { + if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE && (gl.flags & GRAPHEME_IS_PUNCTUATION) != GRAPHEME_IS_PUNCTUATION) { space_count++; } } @@ -4330,9 +4330,9 @@ double TextServerAdvanced::_shaped_text_fit_to_width(const RID &p_shaped, double int count = delta_width_per_kashida / gl.advance; int prev_count = gl.repeat; if ((gl.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) { - gl.repeat = MAX(count, 0); + gl.repeat = CLAMP(count, 0, 255); } else { - gl.repeat = MAX(count + 1, 1); + gl.repeat = CLAMP(count + 1, 1, 255); } justification_width += (gl.repeat - prev_count) * gl.advance; } @@ -4346,7 +4346,7 @@ double TextServerAdvanced::_shaped_text_fit_to_width(const RID &p_shaped, double for (int i = start_pos; i <= end_pos; i++) { Glyph &gl = sd->glyphs.write[i]; if (gl.count > 0) { - if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { + if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE && (gl.flags & GRAPHEME_IS_PUNCTUATION) != GRAPHEME_IS_PUNCTUATION) { double old_adv = gl.advance; double new_advance; if ((gl.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) { @@ -4782,6 +4782,19 @@ bool TextServerAdvanced::_shaped_text_update_breaks(const RID &p_shaped) { gl.font_rid = sd_glyphs[i].font_rid; gl.font_size = sd_glyphs[i].font_size; gl.flags = GRAPHEME_IS_BREAK_SOFT | GRAPHEME_IS_VIRTUAL | GRAPHEME_IS_SPACE; + // Mark virtual space after punctuation as punctuation to avoid justification at this point. + if (c_punct_size == 0) { + if (u_ispunct(c) && c != 0x005f) { + gl.flags |= GRAPHEME_IS_PUNCTUATION; + } + } else { + for (int j = 0; j < c_punct_size; j++) { + if (c_punct[j] == c) { + gl.flags |= GRAPHEME_IS_PUNCTUATION; + break; + } + } + } if (sd_glyphs[i].flags & GRAPHEME_IS_RTL) { gl.flags |= GRAPHEME_IS_RTL; for (int j = sd_glyphs[i].count - 1; j >= 0; j--) { @@ -4993,7 +5006,7 @@ bool TextServerAdvanced::_shaped_text_update_justification_ops(const RID &p_shap } } } - } else if ((sd_glyphs[i].flags & GRAPHEME_IS_SPACE) != GRAPHEME_IS_SPACE) { + } else if ((sd_glyphs[i].flags & GRAPHEME_IS_SPACE) != GRAPHEME_IS_SPACE && (sd_glyphs[i].flags & GRAPHEME_IS_PUNCTUATION) != GRAPHEME_IS_PUNCTUATION) { int count = sd_glyphs[i].count; // Do not add extra spaces at the end of the line. if (sd_glyphs[i].end == sd->end) { diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index d67ae6b45b..15124ad488 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -3262,7 +3262,7 @@ double TextServerFallback::_shaped_text_fit_to_width(const RID &p_shaped, double for (int i = start_pos; i <= end_pos; i++) { const Glyph &gl = sd->glyphs[i]; if (gl.count > 0) { - if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { + if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE && (gl.flags & GRAPHEME_IS_PUNCTUATION) != GRAPHEME_IS_PUNCTUATION) { space_count++; } } @@ -3273,7 +3273,7 @@ double TextServerFallback::_shaped_text_fit_to_width(const RID &p_shaped, double for (int i = start_pos; i <= end_pos; i++) { Glyph &gl = sd->glyphs.write[i]; if (gl.count > 0) { - if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { + if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE && (gl.flags & GRAPHEME_IS_PUNCTUATION) != GRAPHEME_IS_PUNCTUATION) { double old_adv = gl.advance; gl.advance = MAX(gl.advance + delta_width_per_space, Math::round(0.1 * gl.font_size)); justification_width += (gl.advance - old_adv); @@ -3372,7 +3372,7 @@ bool TextServerFallback::_shaped_text_update_breaks(const RID &p_shaped) { if (sd_glyphs[i].count > 0) { char32_t c = sd->text[sd_glyphs[i].start - sd->start]; if (c_punct_size == 0) { - if (is_punct(c) && c != 0x005F) { + if (is_punct(c) && c != 0x005F && c != ' ') { sd_glyphs[i].flags |= GRAPHEME_IS_PUNCTUATION; } } else { 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/platform/web/dom_keys.inc b/platform/web/dom_keys.inc index e63bd7c69f..ae3b2fc1a5 100644 --- a/platform/web/dom_keys.inc +++ b/platform/web/dom_keys.inc @@ -51,6 +51,7 @@ Key dom_code2godot_scancode(EM_UTF8 const p_code[32], EM_UTF8 const p_key[32], b DOM2GODOT("Numpad9", KP_9); DOM2GODOT("NumpadAdd", KP_ADD); DOM2GODOT("NumpadBackspace", BACKSPACE); + DOM2GODOT("Clear", CLEAR); // NumLock on macOS. DOM2GODOT("NumpadClear", CLEAR); DOM2GODOT("NumpadClearEntry", CLEAR); //DOM2GODOT("NumpadComma", UNKNOWN); @@ -125,16 +126,22 @@ Key dom_code2godot_scancode(EM_UTF8 const p_code[32], EM_UTF8 const p_key[32], b DOM2GODOT("Slash", SLASH); // Functional keys in the Alphanumeric section. + DOM2GODOT("Alt", ALT); DOM2GODOT("AltLeft", ALT); DOM2GODOT("AltRight", ALT); DOM2GODOT("Backspace", BACKSPACE); DOM2GODOT("CapsLock", CAPSLOCK); DOM2GODOT("ContextMenu", MENU); + DOM2GODOT("Control", CTRL); DOM2GODOT("ControlLeft", CTRL); DOM2GODOT("ControlRight", CTRL); DOM2GODOT("Enter", ENTER); + DOM2GODOT("Meta", META); DOM2GODOT("MetaLeft", META); DOM2GODOT("MetaRight", META); + DOM2GODOT("OSLeft", META); // Command on macOS. + DOM2GODOT("OSRight", META); // Command on macOS. + DOM2GODOT("Shift", SHIFT); DOM2GODOT("ShiftLeft", SHIFT); DOM2GODOT("ShiftRight", SHIFT); DOM2GODOT("Space", SPACE); diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 92af3fef69..360e446de7 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -3404,16 +3404,8 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } break; case WM_SYSKEYUP: case WM_KEYUP: - if (windows[window_id].ime_suppress_next_keyup) { - windows[window_id].ime_suppress_next_keyup = false; - break; - } - [[fallthrough]]; case WM_SYSKEYDOWN: case WM_KEYDOWN: { - if (windows[window_id].ime_in_progress) { - break; - } if (wParam == VK_SHIFT) { shift_mem = (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN); } @@ -3426,6 +3418,17 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA gr_mem = alt_mem; } } + if (wParam == VK_LWIN || wParam == VK_RWIN) { + meta_mem = (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN); + } + + if (windows[window_id].ime_suppress_next_keyup && (uMsg == WM_KEYUP || uMsg == WM_SYSKEYUP)) { + windows[window_id].ime_suppress_next_keyup = false; + break; + } + if (windows[window_id].ime_in_progress) { + break; + } if (mouse_mode == MOUSE_MODE_CAPTURED) { // When SetCapture is used, ALT+F4 hotkey is ignored by Windows, so handle it ourselves diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 22297f4c29..941e72c8f3 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -879,7 +879,11 @@ Error EditorExportPlatformWindows::run(const Ref<EditorExportPreset> &p_preset, print_line("Creating temporary directory..."); ep.step(TTR("Creating temporary directory..."), 2); String temp_dir; +#ifndef WINDOWS_ENABLED err = ssh_run_on_remote(host, port, extra_args_ssh, "powershell -command \\\"\\$tmp = Join-Path \\$Env:Temp \\$(New-Guid); New-Item -Type Directory -Path \\$tmp | Out-Null; Write-Output \\$tmp\\\"", &temp_dir); +#else + err = ssh_run_on_remote(host, port, extra_args_ssh, "powershell -command \"$tmp = Join-Path $Env:Temp $(New-Guid); New-Item -Type Directory -Path $tmp ^| Out-Null; Write-Output $tmp\"", &temp_dir); +#endif if (err != OK || temp_dir.is_empty()) { CLEANUP_AND_RETURN(err); } @@ -891,6 +895,10 @@ Error EditorExportPlatformWindows::run(const Ref<EditorExportPreset> &p_preset, CLEANUP_AND_RETURN(err); } + if (cmd_args.is_empty()) { + cmd_args = " "; + } + { String run_script = p_preset->get("ssh_remote_deploy/run_script"); run_script = run_script.replace("{temp_dir}", temp_dir); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index d384049fb5..6e219fb929 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -69,6 +69,11 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; #define WM_POINTERUPDATE 0x0245 #endif +// Missing in MinGW headers before 8.0. +#ifndef DWRITE_FONT_WEIGHT_SEMI_LIGHT +#define DWRITE_FONT_WEIGHT_SEMI_LIGHT (DWRITE_FONT_WEIGHT)350 +#endif + #if defined(__GNUC__) // Workaround GCC warning from -Wcast-function-type. #define GetProcAddress (void *)GetProcAddress @@ -673,9 +678,8 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, } CloseHandle(pipe[0]); // Close pipe read handle. - } else { - WaitForSingleObject(pi.pi.hProcess, INFINITE); } + WaitForSingleObject(pi.pi.hProcess, INFINITE); if (r_exitcode) { DWORD ret2; 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/scene/animation/tween.cpp b/scene/animation/tween.cpp index 9d1118e0ef..e05c24ae09 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -489,6 +489,11 @@ Tween::Tween(bool p_valid) { } Ref<PropertyTweener> PropertyTweener::from(Variant p_value) { + ERR_FAIL_COND_V(tween.is_null(), nullptr); + if (!tween->_validate_type_match(p_value, final_val)) { + return nullptr; + } + initial_val = p_value; do_continue = false; return this; diff --git a/scene/animation/tween.h b/scene/animation/tween.h index c5abcb28a6..b7dc941111 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -61,6 +61,8 @@ class MethodTweener; class Tween : public RefCounted { GDCLASS(Tween, RefCounted); + friend class PropertyTweener; + public: enum TweenProcessMode { TWEEN_PROCESS_PHYSICS, diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index ee39327d4d..91c4fa3761 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -2926,6 +2926,12 @@ void CodeEdit::_filter_code_completion_candidates_impl() { code_completion_options.clear(); code_completion_base = string_to_complete; + /* Don't autocomplete setting numerical values. */ + if (code_completion_base.is_numeric()) { + cancel_code_completion(); + return; + } + Vector<ScriptLanguage::CodeCompletionOption> completion_options_casei; Vector<ScriptLanguage::CodeCompletionOption> completion_options_substr; Vector<ScriptLanguage::CodeCompletionOption> completion_options_substr_casei; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 7ab33d5c6c..8f425436b7 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1263,7 +1263,7 @@ void TextEdit::_notification(int p_what) { if (draw_tabs && ((glyphs[j].flags & TextServer::GRAPHEME_IS_TAB) == TextServer::GRAPHEME_IS_TAB)) { int yofs = (text_height - tab_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index); tab_icon->draw(ci, Point2(char_pos, ofs_y + yofs), gl_color); - } else if (draw_spaces && ((glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE)) { + } else if (draw_spaces && ((glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE) && ((glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL)) { int yofs = (text_height - space_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index); int xofs = (glyphs[j].advance * glyphs[j].repeat - space_icon->get_width()) / 2; space_icon->draw(ci, Point2(char_pos + xofs, ofs_y + yofs), gl_color); diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 0f7985bee6..f6e224aca0 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -1458,6 +1458,9 @@ Error FontFile::load_bitmap_font(const String &p_path) { } if (ch[i] == 1 && first_ol_ch == -1) { first_ol_ch = i; + if (outline == 0) { + outline = 1; + } } if (ch[i] == 2 && first_cm_ch == -1) { first_cm_ch = i; @@ -1747,6 +1750,9 @@ Error FontFile::load_bitmap_font(const String &p_path) { } if (ch[i] == 1 && first_ol_ch == -1) { first_ol_ch = i; + if (outline == 0) { + outline = 1; + } } if (ch[i] == 2 && first_cm_ch == -1) { first_cm_ch = i; diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 05be40c446..651bad1aa7 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -1232,6 +1232,12 @@ Error ImageTexture3D::create(Image::Format p_format, int p_width, int p_height, texture = tex; } + format = p_format; + width = p_width; + height = p_height; + depth = p_depth; + mipmaps = p_mipmaps; + return OK; } diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index e0128bfe25..91789201c6 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -1972,22 +1972,25 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_list_end(); RD::get_singleton()->draw_command_end_label(); } + if (rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + RENDER_TIMESTAMP("Resolve MSAA"); - if (!can_continue_color && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { - // Handle views individual, might want to look at rewriting our resolve to do both layers in one pass. - for (uint32_t v = 0; v < rb->get_view_count(); v++) { - RD::get_singleton()->texture_resolve_multisample(rb_data->get_color_msaa(v), rb->get_internal_texture(v)); - } - if (using_separate_specular) { + if (!can_continue_color) { + // Handle views individual, might want to look at rewriting our resolve to do both layers in one pass. for (uint32_t v = 0; v < rb->get_view_count(); v++) { - RD::get_singleton()->texture_resolve_multisample(rb_data->get_specular_msaa(v), rb_data->get_specular(v)); + RD::get_singleton()->texture_resolve_multisample(rb_data->get_color_msaa(v), rb->get_internal_texture(v)); + } + if (using_separate_specular) { + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + RD::get_singleton()->texture_resolve_multisample(rb_data->get_specular_msaa(v), rb_data->get_specular(v)); + } } } - } - if (!can_continue_depth && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { - for (uint32_t v = 0; v < rb->get_view_count(); v++) { - resolve_effects->resolve_depth(rb_data->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]); + if (!can_continue_depth) { + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + resolve_effects->resolve_depth(rb_data->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]); + } } } @@ -2016,11 +2019,15 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } if (scene_state.used_screen_texture) { + RENDER_TIMESTAMP("Copy Screen Texture"); + // Copy screen texture to backbuffer so we can read from it _render_buffers_copy_screen_texture(p_render_data); } if (scene_state.used_depth_texture) { + RENDER_TIMESTAMP("Copy Depth Texture"); + // Copy depth texture to backbuffer so we can read from it _render_buffers_copy_depth_texture(p_render_data); } diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 6c39560729..6bfbc2e0a7 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -271,7 +271,12 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe // - add blit to 2D pass RID render_target = render_buffers->get_render_target(); ERR_FAIL_COND_V(render_target.is_null(), RID()); - RID target_buffer = texture_storage->render_target_get_rd_texture(render_target); + RID target_buffer; + if (texture_storage->render_target_get_msaa(render_target) == RS::VIEWPORT_MSAA_DISABLED) { + target_buffer = texture_storage->render_target_get_rd_texture(render_target); + } else { + target_buffer = texture_storage->render_target_get_rd_texture_msaa(render_target); + } ERR_FAIL_COND_V(target_buffer.is_null(), RID()); int target_buffer_id = textures.size(); @@ -742,14 +747,15 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color } // We do this last because our get_color_fbs creates and caches the framebuffer if we need it. - if (using_subpass_post_process && rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES).is_null()) { + RID four_subpasses = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES); + if (using_subpass_post_process && four_subpasses.is_null()) { // can't do blit subpass because we don't have all subpasses using_subpass_post_process = false; } if (using_subpass_post_process) { // all as subpasses - framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES); + framebuffer = four_subpasses; } else if (using_subpass_transparent) { // our tonemap pass is separate framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_THREE_SUBPASSES); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index a1346661e1..1aab52d1c3 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -2911,6 +2911,13 @@ RID TextureStorage::render_target_get_rd_texture_slice(RID p_render_target, uint } } +RID TextureStorage::render_target_get_rd_texture_msaa(RID p_render_target) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + return rt->color_multisample; +} + RID TextureStorage::render_target_get_rd_backbuffer(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, RID()); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index b6bb9fa52f..f710de1100 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -741,6 +741,7 @@ public: RID render_target_get_rd_framebuffer(RID p_render_target); RID render_target_get_rd_texture(RID p_render_target); RID render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer); + RID render_target_get_rd_texture_msaa(RID p_render_target); RID render_target_get_rd_backbuffer(RID p_render_target); RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target); 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; |