summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct2
-rw-r--r--drivers/gles3/storage/material_storage.cpp20
-rw-r--r--editor/plugins/theme_editor_plugin.cpp4
-rw-r--r--editor/project_converter_3_to_4.cpp449
-rw-r--r--editor/project_converter_3_to_4.h33
-rw-r--r--editor/property_selector.cpp6
-rw-r--r--editor/renames_map_3_to_4.cpp17
-rw-r--r--modules/gdscript/gdscript_compiler.cpp12
-rw-r--r--modules/gdscript/gdscript_compiler.h2
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.cpp5
-rw-r--r--modules/gltf/gltf_document.cpp14
-rw-r--r--modules/mono/csharp_script.cpp5
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs26
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs6
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs2
-rw-r--r--modules/mono/editor/bindings_generator.cpp6
-rw-r--r--modules/navigation/godot_navigation_server.cpp2
-rw-r--r--modules/text_server_adv/text_server_adv.cpp23
-rw-r--r--modules/text_server_fb/text_server_fb.cpp6
-rw-r--r--platform/linuxbsd/detect.py3
-rw-r--r--platform/web/dom_keys.inc7
-rw-r--r--platform/windows/display_server_windows.cpp19
-rw-r--r--platform/windows/export/export_plugin.cpp8
-rw-r--r--platform/windows/os_windows.cpp8
-rw-r--r--scene/2d/back_buffer_copy.cpp1
-rw-r--r--scene/2d/camera_2d.cpp14
-rw-r--r--scene/2d/camera_2d.h2
-rw-r--r--scene/animation/tween.cpp5
-rw-r--r--scene/animation/tween.h2
-rw-r--r--scene/gui/code_edit.cpp6
-rw-r--r--scene/gui/text_edit.cpp2
-rw-r--r--scene/resources/font.cpp6
-rw-r--r--scene/resources/texture.cpp6
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp29
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp12
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp7
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h1
-rw-r--r--servers/rendering/shader_language.cpp8
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 &reg_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 &reg_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 &reg_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 &reg_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 *> &regex_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 &reg_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 &reg_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 &reg_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 &reg_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 &reg_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 &reg_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 &reg_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 &reg_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 &reg_container) {
- for (String &line : lines) {
+void ProjectConverter3To4::rename_colors(Vector<SourceLine> &source_lines, const RegExContainer &reg_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 &reg_container) {
- for (String &line : lines) {
+void ProjectConverter3To4::fix_tool_declaration(Vector<SourceLine> &source_lines, const RegExContainer &reg_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 &reg_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 &reg_container, bool builtin) {
- for (String &line : lines) {
+void ProjectConverter3To4::rename_gdscript_functions(Vector<SourceLine> &source_lines, const RegExContainer &reg_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 &reg_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 &reg_container) {
- for (String &line : lines) {
+void ProjectConverter3To4::rename_csharp_functions(Vector<SourceLine> &source_lines, const RegExContainer &reg_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 &reg_container) {
+void ProjectConverter3To4::rename_csharp_attributes(Vector<SourceLine> &source_lines, const RegExContainer &reg_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 &reg_container) {
+void ProjectConverter3To4::rename_gdscript_keywords(Vector<SourceLine> &source_lines, const RegExContainer &reg_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 &reg_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 &reg_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 &reg_container);
+ void fix_tool_declaration(Vector<SourceLine> &source_lines, const RegExContainer &reg_container);
+
+ void rename_colors(Vector<SourceLine> &source_lines, const RegExContainer &reg_container);
Vector<String> check_for_rename_colors(Vector<String> &lines, const RegExContainer &reg_container);
- void rename_classes(Vector<String> &lines, const RegExContainer &reg_container);
+ void rename_classes(Vector<SourceLine> &source_lines, const RegExContainer &reg_container);
Vector<String> check_for_rename_classes(Vector<String> &lines, const RegExContainer &reg_container);
- void rename_gdscript_functions(Vector<String> &lines, const RegExContainer &reg_container, bool builtin);
+ void rename_gdscript_functions(Vector<SourceLine> &source_lines, const RegExContainer &reg_container, bool builtin);
Vector<String> check_for_rename_gdscript_functions(Vector<String> &lines, const RegExContainer &reg_container, bool builtin);
void process_gdscript_line(String &line, const RegExContainer &reg_container, bool builtin);
- void rename_csharp_functions(Vector<String> &lines, const RegExContainer &reg_container);
+ void rename_csharp_functions(Vector<SourceLine> &source_lines, const RegExContainer &reg_container);
Vector<String> check_for_rename_csharp_functions(Vector<String> &lines, const RegExContainer &reg_container);
void process_csharp_line(String &line, const RegExContainer &reg_container);
- void rename_csharp_attributes(Vector<String> &lines, const RegExContainer &reg_container);
+ void rename_csharp_attributes(Vector<SourceLine> &source_lines, const RegExContainer &reg_container);
Vector<String> check_for_rename_csharp_attributes(Vector<String> &lines, const RegExContainer &reg_container);
- void rename_gdscript_keywords(Vector<String> &lines, const RegExContainer &reg_container);
+ void rename_gdscript_keywords(Vector<SourceLine> &source_lines, const RegExContainer &reg_container);
Vector<String> check_for_rename_gdscript_keywords(Vector<String> &lines, const RegExContainer &reg_container);
- void custom_rename(Vector<String> &lines, String from, String to);
+ void rename_input_map_scancode(Vector<SourceLine> &source_lines, const RegExContainer &reg_container);
+ Vector<String> check_for_rename_input_map_scancode(Vector<String> &lines, const RegExContainer &reg_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 &reg_container, bool builtin);
- bool test_conversion_with_regex(String name, String expected, void (ProjectConverter3To4::*func)(Vector<String> &, const RegExContainer &), String what, const RegExContainer &reg_container);
+ bool test_conversion_gdscript_builtin(String name, String expected, void (ProjectConverter3To4::*func)(Vector<SourceLine> &, const RegExContainer &, bool), String what, const RegExContainer &reg_container, bool builtin);
+ bool test_conversion_with_regex(String name, String expected, void (ProjectConverter3To4::*func)(Vector<SourceLine> &, const RegExContainer &), String what, const RegExContainer &reg_container);
bool test_conversion_basic(String name, String expected, const char *array[][2], LocalVector<RegEx *> &regex_cache, String what);
bool test_array_names();
bool test_conversion(RegExContainer &reg_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;