From 5122a3e3b00e154c0148bb2709671e6c3a0b0432 Mon Sep 17 00:00:00 2001 From: David Nikdel Date: Mon, 10 Jun 2024 08:34:25 -0400 Subject: [PATCH 001/237] editor: warn on UID duplicates This commonly occurs when files are copied outside of the editor and don't get new UIDs. Restricting this warning to first_scan since it's we want to exclude the case of files being moved after initial load which is harder to handle. Addresses https://github.com/godotengine/godot-proposals/discussions/8949 --- editor/editor_file_system.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 3adff84e40b..cdaa001d9e8 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -961,6 +961,14 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Refuid != ResourceUID::INVALID_ID) { if (ResourceUID::get_singleton()->has_id(fi->uid)) { + // Restrict UID dupe warning to first-scan since we know there are no file moves going on yet. + if (first_scan) { + // Warn if we detect files with duplicate UIDs. + const String other_path = ResourceUID::get_singleton()->get_id_path(fi->uid); + if (other_path != path) { + WARN_PRINT(vformat("UID duplicate detected between %s and %s.", path, other_path)); + } + } ResourceUID::get_singleton()->set_id(fi->uid, path); } else { ResourceUID::get_singleton()->add_id(fi->uid, path); From c981e8b76554ba322aa36d756032d8d9131bc0bd Mon Sep 17 00:00:00 2001 From: kobewi Date: Thu, 20 Jun 2024 00:46:14 +0200 Subject: [PATCH 002/237] Don't rescan filesystem when adding new directory --- editor/editor_file_system.cpp | 29 +++++++++++++++++++++++++++++ editor/editor_file_system.h | 8 ++++++++ editor/filesystem_dock.cpp | 11 ++++++++++- editor/filesystem_dock.h | 1 + 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index a1e392cd7dd..6f9d89ff65c 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -2574,6 +2574,35 @@ void EditorFileSystem::move_group_file(const String &p_path, const String &p_new } } +void EditorFileSystem::add_new_directory(const String &p_path) { + String path = p_path.get_base_dir(); + EditorFileSystemDirectory *parent = filesystem; + int base = p_path.count("/"); + int max_bit = base + 1; + + while (path != "res://") { + EditorFileSystemDirectory *dir = get_filesystem_path(path); + if (dir) { + parent = dir; + break; + } + path = path.get_base_dir(); + base--; + } + + for (int i = base; i < max_bit; i++) { + EditorFileSystemDirectory *efd = memnew(EditorFileSystemDirectory); + efd->parent = parent; + efd->name = p_path.get_slice("/", i); + parent->subdirs.push_back(efd); + + if (i == base) { + parent->subdirs.sort_custom(); + } + parent = efd; + } +} + ResourceUID::ID EditorFileSystem::_resource_saver_get_resource_id_for_path(const String &p_path, bool p_generate) { if (!p_path.is_resource_file() || p_path.begins_with(ProjectSettings::get_singleton()->get_project_data_path())) { // Saved externally (configuration file) or internal file, do not assign an ID. diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index cd95d5fb951..ef0ef5b3892 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -207,6 +207,12 @@ class EditorFileSystem : public Node { ScanProgress get_sub(int p_current, int p_total) const; }; + struct DirectoryComparator { + bool operator()(const EditorFileSystemDirectory *p_a, const EditorFileSystemDirectory *p_b) const { + return p_a->name.filenocasecmp_to(p_b->name) < 0; + } + }; + void _save_filesystem_cache(); void _save_filesystem_cache(EditorFileSystemDirectory *p_dir, Ref p_file); @@ -326,6 +332,8 @@ class EditorFileSystem : public Node { bool is_group_file(const String &p_path) const; void move_group_file(const String &p_path, const String &p_new_path); + void add_new_directory(const String &p_path); + static bool _should_skip_directory(const String &p_path); void add_import_format_support_query(Ref p_query); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 1c22ecd673e..ad3fa45a014 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1326,6 +1326,15 @@ void FileSystemDock::_fs_changed() { set_process(false); } +void FileSystemDock::_directory_created(const String &p_path) { + if (!DirAccess::exists(p_path)) { + return; + } + EditorFileSystem::get_singleton()->add_new_directory(p_path); + _update_tree(get_uncollapsed_paths()); + _update_file_list(true); +} + void FileSystemDock::_set_scanning_mode() { button_hist_prev->set_disabled(true); button_hist_next->set_disabled(true); @@ -4142,7 +4151,7 @@ FileSystemDock::FileSystemDock() { make_dir_dialog = memnew(DirectoryCreateDialog); add_child(make_dir_dialog); - make_dir_dialog->connect("dir_created", callable_mp(this, &FileSystemDock::_rescan).unbind(1)); + make_dir_dialog->connect("dir_created", callable_mp(this, &FileSystemDock::_directory_created)); make_scene_dialog = memnew(SceneCreateDialog); add_child(make_scene_dialog); diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 3fbff3ef194..266e3c7975e 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -262,6 +262,7 @@ class FileSystemDock : public VBoxContainer { void _toggle_file_display(); void _set_file_display(bool p_active); void _fs_changed(); + void _directory_created(const String &p_path); void _select_file(const String &p_path, bool p_select_in_favorites = false); void _tree_activate_file(); From 28c60a5ff90533bf13e89373336c36f7016c38cc Mon Sep 17 00:00:00 2001 From: Alvin Wong Date: Sun, 28 Jul 2024 00:29:52 +0800 Subject: [PATCH 003/237] Combine existing modes when calling SetConsoleMode Otherwise the default modes will be cleared, which causes long lines to be truncated in some terminals (e.g. Windows Terminal). --- platform/windows/console_wrapper_windows.cpp | 4 +++- platform/windows/os_windows.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/windows/console_wrapper_windows.cpp b/platform/windows/console_wrapper_windows.cpp index 133711a9eaf..1d7836add1f 100644 --- a/platform/windows/console_wrapper_windows.cpp +++ b/platform/windows/console_wrapper_windows.cpp @@ -65,7 +65,9 @@ int main(int argc, char *argv[]) { // Enable virtual terminal sequences processing. HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); - DWORD out_mode = ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING; + DWORD out_mode = 0; + GetConsoleMode(stdout_handle, &out_mode); + out_mode |= ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING; SetConsoleMode(stdout_handle, out_mode); // Find main executable name and check if it exist. diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 9025f53f42b..a366827e11e 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1925,7 +1925,9 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { // NOTE: The engine does not use ANSI escape codes to color error/warning messages; it uses Windows API calls instead. // Therefore, error/warning messages are still colored on Windows versions older than 10. HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); - DWORD outMode = ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING; + DWORD outMode = 0; + GetConsoleMode(stdoutHandle, &outMode); + outMode |= ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING; if (!SetConsoleMode(stdoutHandle, outMode)) { // Windows 8.1 or below, or Windows 10 prior to Anniversary Update. print_verbose("Can't set the ENABLE_VIRTUAL_TERMINAL_PROCESSING Windows console mode. `print_rich()` will not work as expected."); From f3841d644eec2366df6d30d7ce6b942504fb2a97 Mon Sep 17 00:00:00 2001 From: Raul Santos Date: Tue, 30 Jul 2024 18:19:42 +0200 Subject: [PATCH 004/237] C#: Generate signal delegates with typed arrays Signals with typed arrays were generating C# delegates with untyped arrays. --- modules/mono/editor/bindings_generator.cpp | 26 +++++++++------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 9a76a256395..6bd99a8f22f 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -2934,11 +2934,6 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::SignalInterface &p_isignal, StringBuilder &p_output) { String arguments_sig; - String delegate_type_params; - - if (!p_isignal.arguments.is_empty()) { - delegate_type_params += "<"; - } // Retrieve information from the arguments const ArgumentInterface &first = p_isignal.arguments.front()->get(); @@ -2959,18 +2954,13 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf if (&iarg != &first) { arguments_sig += ", "; - delegate_type_params += ", "; } - arguments_sig += arg_type->cs_type; + String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters); + + arguments_sig += arg_cs_type; arguments_sig += " "; arguments_sig += iarg.name; - - delegate_type_params += arg_type->cs_type; - } - - if (!p_isignal.arguments.is_empty()) { - delegate_type_params += ">"; } // Generate signal @@ -3019,8 +3009,14 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf p_output << ", "; } - p_output << sformat(arg_type->cs_variant_to_managed, - "args[" + itos(idx) + "]", arg_type->cs_type, arg_type->name); + if (arg_type->cname == name_cache.type_Array_generic || arg_type->cname == name_cache.type_Dictionary_generic) { + String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters); + + p_output << "new " << arg_cs_type << "(" << sformat(arg_type->cs_variant_to_managed, "args[" + itos(idx) + "]", arg_type->cs_type, arg_type->name) << ")"; + } else { + p_output << sformat(arg_type->cs_variant_to_managed, + "args[" + itos(idx) + "]", arg_type->cs_type, arg_type->name); + } idx++; } From 4f11a0a9873ec9bd2a95ed0d10094606c172693b Mon Sep 17 00:00:00 2001 From: kleonc <9283098+kleonc@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:26:21 +0200 Subject: [PATCH 005/237] Support importing 1/2/4-bpp BMP images of size non-divisible by 8/4/2 --- modules/bmp/image_loader_bmp.cpp | 67 +++++--------------------------- 1 file changed, 10 insertions(+), 57 deletions(-) diff --git a/modules/bmp/image_loader_bmp.cpp b/modules/bmp/image_loader_bmp.cpp index 72b540496d0..1804d73a696 100644 --- a/modules/bmp/image_loader_bmp.cpp +++ b/modules/bmp/image_loader_bmp.cpp @@ -59,30 +59,6 @@ Error ImageLoaderBMP::convert_to_image(Ref p_image, size_t height = (size_t)p_header.bmp_info_header.bmp_height; size_t bits_per_pixel = (size_t)p_header.bmp_info_header.bmp_bit_count; - // Check whether we can load it - - if (bits_per_pixel == 1) { - // Requires bit unpacking... - ERR_FAIL_COND_V_MSG(width % 8 != 0, ERR_UNAVAILABLE, - vformat("1-bpp BMP images must have a width that is a multiple of 8, but the imported BMP is %d pixels wide.", int(width))); - ERR_FAIL_COND_V_MSG(height % 8 != 0, ERR_UNAVAILABLE, - vformat("1-bpp BMP images must have a height that is a multiple of 8, but the imported BMP is %d pixels tall.", int(height))); - - } else if (bits_per_pixel == 2) { - // Requires bit unpacking... - ERR_FAIL_COND_V_MSG(width % 4 != 0, ERR_UNAVAILABLE, - vformat("2-bpp BMP images must have a width that is a multiple of 4, but the imported BMP is %d pixels wide.", int(width))); - ERR_FAIL_COND_V_MSG(height % 4 != 0, ERR_UNAVAILABLE, - vformat("2-bpp BMP images must have a height that is a multiple of 4, but the imported BMP is %d pixels tall.", int(height))); - - } else if (bits_per_pixel == 4) { - // Requires bit unpacking... - ERR_FAIL_COND_V_MSG(width % 2 != 0, ERR_UNAVAILABLE, - vformat("4-bpp BMP images must have a width that is a multiple of 2, but the imported BMP is %d pixels wide.", int(width))); - ERR_FAIL_COND_V_MSG(height % 2 != 0, ERR_UNAVAILABLE, - vformat("4-bpp BMP images must have a height that is a multiple of 2, but the imported BMP is %d pixels tall.", int(height))); - } - // Image data (might be indexed) Vector data; int data_len = 0; @@ -98,55 +74,32 @@ Error ImageLoaderBMP::convert_to_image(Ref p_image, uint8_t *data_w = data.ptrw(); uint8_t *write_buffer = data_w; - const uint32_t width_bytes = width * bits_per_pixel / 8; - const uint32_t line_width = (width_bytes + 3) & ~3; + const uint32_t width_bytes = (width * bits_per_pixel + 7) / 8; + const uint32_t line_width = (width_bytes + 3) & ~3; // Padded to 4 bytes. - // The actual data traversal is determined by - // the data width in case of 8/4/2/1 bit images - const uint32_t w = bits_per_pixel >= 16 ? width : width_bytes; const uint8_t *line = p_buffer + (line_width * (height - 1)); const uint8_t *end_buffer = p_buffer + p_header.bmp_file_header.bmp_file_size - p_header.bmp_file_header.bmp_file_offset; + ERR_FAIL_COND_V(line + line_width > end_buffer, ERR_FILE_CORRUPT); for (uint64_t i = 0; i < height; i++) { const uint8_t *line_ptr = line; - for (unsigned int j = 0; j < w; j++) { - ERR_FAIL_COND_V(line_ptr >= end_buffer, ERR_FILE_CORRUPT); + for (unsigned int j = 0; j < width; j++) { switch (bits_per_pixel) { case 1: { - uint8_t color_index = *line_ptr; + write_buffer[index] = (line[(j * bits_per_pixel) / 8] >> (8 - bits_per_pixel * (1 + j % 8))) & 0x01; - write_buffer[index + 0] = (color_index >> 7) & 1; - write_buffer[index + 1] = (color_index >> 6) & 1; - write_buffer[index + 2] = (color_index >> 5) & 1; - write_buffer[index + 3] = (color_index >> 4) & 1; - write_buffer[index + 4] = (color_index >> 3) & 1; - write_buffer[index + 5] = (color_index >> 2) & 1; - write_buffer[index + 6] = (color_index >> 1) & 1; - write_buffer[index + 7] = (color_index >> 0) & 1; - - index += 8; - line_ptr += 1; + index++; } break; case 2: { - uint8_t color_index = *line_ptr; + write_buffer[index] = (line[(j * bits_per_pixel) / 8] >> (8 - bits_per_pixel * (1 + j % 4))) & 0x03; - write_buffer[index + 0] = (color_index >> 6) & 3; - write_buffer[index + 1] = (color_index >> 4) & 3; - write_buffer[index + 2] = (color_index >> 2) & 3; - write_buffer[index + 3] = color_index & 3; - - index += 4; - line_ptr += 1; + index++; } break; case 4: { - uint8_t color_index = *line_ptr; - - write_buffer[index + 0] = (color_index >> 4) & 0x0f; - write_buffer[index + 1] = color_index & 0x0f; + write_buffer[index] = (line[(j * bits_per_pixel) / 8] >> (8 - bits_per_pixel * (1 + j % 2))) & 0x0f; - index += 2; - line_ptr += 1; + index++; } break; case 8: { uint8_t color_index = *line_ptr; From 74f64aaf98beba74c8c7eedac152c4a50b336994 Mon Sep 17 00:00:00 2001 From: Marius Hanl Date: Sat, 31 Aug 2024 19:23:34 +0200 Subject: [PATCH 006/237] Use InputMap actions consistently across all LineEdit's that filter an underlying Tree or ItemList. - Instead of checking for Key::UP, Key::DOWN, Key::PAGEUP, Key::PAGEDOWN etc., we rather check for the action like 'ui_up' or 'ui_down'. - Also use AcceptDialog's 'register_text_enter' functionality to consistently close a dialog when ENTER is pressed while the LineEdit has focus (instead of redirecting ENTER keys to e.g. the underlying Tree). - Unify the LineEdit filter behavior for the SceneTreeDialog and corresponding usages - Improve OK Button disablement (something should be selected) --- editor/animation_track_editor.cpp | 20 ------- editor/animation_track_editor.h | 1 - editor/create_dialog.cpp | 33 +++++------- editor/create_dialog.h | 2 +- editor/editor_command_palette.cpp | 19 +++---- editor/editor_command_palette.h | 2 +- editor/editor_help_search.cpp | 15 ++---- editor/editor_quick_open.cpp | 52 ++++++++---------- editor/editor_quick_open.h | 2 +- editor/gui/scene_tree_editor.cpp | 15 ++++++ editor/gui/scene_tree_editor.h | 1 + editor/plugins/script_editor_plugin.cpp | 14 ++--- editor/plugins/script_editor_plugin.h | 2 +- editor/plugins/theme_editor_plugin.cpp | 20 +++---- editor/plugins/theme_editor_plugin.h | 2 +- .../plugins/visual_shader_editor_plugin.cpp | 51 +++++++++--------- editor/plugins/visual_shader_editor_plugin.h | 5 +- editor/property_selector.cpp | 53 ++++++++----------- editor/property_selector.h | 2 +- .../gridmap/editor/grid_map_editor_plugin.cpp | 15 +++--- .../gridmap/editor/grid_map_editor_plugin.h | 2 +- .../multiplayer/editor/replication_editor.cpp | 20 ------- .../multiplayer/editor/replication_editor.h | 1 - 23 files changed, 142 insertions(+), 207 deletions(-) diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 8c07cefc194..2f6798ab869 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -7178,24 +7178,6 @@ void AnimationTrackEditor::_pick_track_select_recursive(TreeItem *p_item, const } } -void AnimationTrackEditor::_pick_track_filter_input(const Ref &p_ie) { - Ref k = p_ie; - - if (k.is_valid()) { - switch (k->get_keycode()) { - case Key::UP: - case Key::DOWN: - case Key::PAGEUP: - case Key::PAGEDOWN: { - pick_track->get_scene_tree()->get_scene_tree()->gui_input(k); - pick_track->get_filter_line_edit()->accept_event(); - } break; - default: - break; - } - } -} - AnimationTrackEditor::AnimationTrackEditor() { main_panel = memnew(PanelContainer); main_panel->set_focus_mode(FOCUS_ALL); // Allow panel to have focus so that shortcuts work as expected. @@ -7413,11 +7395,9 @@ AnimationTrackEditor::AnimationTrackEditor() { pick_track = memnew(SceneTreeDialog); add_child(pick_track); - pick_track->register_text_enter(pick_track->get_filter_line_edit()); pick_track->set_title(TTR("Pick a node to animate:")); pick_track->connect("selected", callable_mp(this, &AnimationTrackEditor::_new_track_node_selected)); pick_track->get_filter_line_edit()->connect(SceneStringName(text_changed), callable_mp(this, &AnimationTrackEditor::_pick_track_filter_text_changed)); - pick_track->get_filter_line_edit()->connect(SceneStringName(gui_input), callable_mp(this, &AnimationTrackEditor::_pick_track_filter_input)); prop_selector = memnew(PropertySelector); add_child(prop_selector); diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index a517ba8b43f..e1d269a86e7 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -649,7 +649,6 @@ class AnimationTrackEditor : public VBoxContainer { void _pick_track_filter_text_changed(const String &p_newtext); void _pick_track_select_recursive(TreeItem *p_item, const String &p_filter, Vector &p_select_candidates); - void _pick_track_filter_input(const Ref &p_ie); double snap_unit; void _update_snap_unit(); diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 204636e128c..42346a0c0bd 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -425,26 +425,19 @@ void CreateDialog::_text_changed(const String &p_newtext) { _update_search(); } -void CreateDialog::_sbox_input(const Ref &p_ie) { - Ref k = p_ie; - if (k.is_valid() && k->is_pressed()) { - switch (k->get_keycode()) { - case Key::UP: - case Key::DOWN: - case Key::PAGEUP: - case Key::PAGEDOWN: { - search_options->gui_input(k); - search_box->accept_event(); - } break; - case Key::SPACE: { - TreeItem *ti = search_options->get_selected(); - if (ti) { - ti->set_collapsed(!ti->is_collapsed()); - } - search_box->accept_event(); - } break; - default: - break; +void CreateDialog::_sbox_input(const Ref &p_event) { + // Redirect navigational key events to the tree. + Ref key = p_event; + if (key.is_valid()) { + if (key->is_action("ui_up", true) || key->is_action("ui_down", true) || key->is_action("ui_page_up") || key->is_action("ui_page_down")) { + search_options->gui_input(key); + search_box->accept_event(); + } else if (key->is_action_pressed("ui_select", true)) { + TreeItem *ti = search_options->get_selected(); + if (ti) { + ti->set_collapsed(!ti->is_collapsed()); + } + search_box->accept_event(); } } } diff --git a/editor/create_dialog.h b/editor/create_dialog.h index d2866e9f041..e2b1b7b34be 100644 --- a/editor/create_dialog.h +++ b/editor/create_dialog.h @@ -77,7 +77,7 @@ class CreateDialog : public ConfirmationDialog { void _fill_type_list(); void _cleanup(); - void _sbox_input(const Ref &p_ie); + void _sbox_input(const Ref &p_event); void _text_changed(const String &p_newtext); void select_type(const String &p_type, bool p_center_on_item = true); void _item_selected(); diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp index a4a08d5b5e5..f40307712d4 100644 --- a/editor/editor_command_palette.cpp +++ b/editor/editor_command_palette.cpp @@ -183,18 +183,13 @@ void EditorCommandPalette::_notification(int p_what) { } } -void EditorCommandPalette::_sbox_input(const Ref &p_ie) { - Ref k = p_ie; - if (k.is_valid()) { - switch (k->get_keycode()) { - case Key::UP: - case Key::DOWN: - case Key::PAGEUP: - case Key::PAGEDOWN: { - search_options->gui_input(k); - } break; - default: - break; +void EditorCommandPalette::_sbox_input(const Ref &p_event) { + // Redirect navigational key events to the tree. + Ref key = p_event; + if (key.is_valid()) { + if (key->is_action("ui_up", true) || key->is_action("ui_down", true) || key->is_action("ui_page_up") || key->is_action("ui_page_down")) { + search_options->gui_input(key); + command_search_box->accept_event(); } } } diff --git a/editor/editor_command_palette.h b/editor/editor_command_palette.h index cc0f726b3a3..f7a5d495c4b 100644 --- a/editor/editor_command_palette.h +++ b/editor/editor_command_palette.h @@ -80,7 +80,7 @@ class EditorCommandPalette : public ConfirmationDialog { void _update_command_search(const String &search_text); float _score_path(const String &p_search, const String &p_path); - void _sbox_input(const Ref &p_ie); + void _sbox_input(const Ref &p_event); void _confirmed(); void _add_command(String p_command_name, String p_key_name, Callable p_binded_action, String p_shortcut_text = "None"); void _save_history() const; diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index eb97337b379..00ef6a68426 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -169,19 +169,12 @@ void EditorHelpSearch::_update_results() { } void EditorHelpSearch::_search_box_gui_input(const Ref &p_event) { - // Redirect up and down navigational key events to the results list. + // Redirect navigational key events to the tree. Ref key = p_event; if (key.is_valid()) { - switch (key->get_keycode()) { - case Key::UP: - case Key::DOWN: - case Key::PAGEUP: - case Key::PAGEDOWN: { - results_tree->gui_input(key); - search_box->accept_event(); - } break; - default: - break; + if (key->is_action("ui_up", true) || key->is_action("ui_down", true) || key->is_action("ui_page_up") || key->is_action("ui_page_down")) { + results_tree->gui_input(key); + search_box->accept_event(); } } } diff --git a/editor/editor_quick_open.cpp b/editor/editor_quick_open.cpp index dfb87f43da5..bd30fc28d11 100644 --- a/editor/editor_quick_open.cpp +++ b/editor/editor_quick_open.cpp @@ -202,36 +202,30 @@ void EditorQuickOpen::_text_changed(const String &p_newtext) { _update_search(); } -void EditorQuickOpen::_sbox_input(const Ref &p_ie) { - Ref k = p_ie; - if (k.is_valid()) { - switch (k->get_keycode()) { - case Key::UP: - case Key::DOWN: - case Key::PAGEUP: - case Key::PAGEDOWN: { - search_options->gui_input(k); - search_box->accept_event(); - - if (allow_multi_select) { - TreeItem *root = search_options->get_root(); - if (!root->get_first_child()) { - break; - } - - TreeItem *current = search_options->get_selected(); - TreeItem *item = search_options->get_next_selected(root); - while (item) { - item->deselect(0); - item = search_options->get_next_selected(item); - } - - current->select(0); - current->set_as_cursor(0); +void EditorQuickOpen::_sbox_input(const Ref &p_event) { + // Redirect navigational key events to the tree. + Ref key = p_event; + if (key.is_valid()) { + if (key->is_action("ui_up", true) || key->is_action("ui_down", true) || key->is_action("ui_page_up") || key->is_action("ui_page_down")) { + search_options->gui_input(key); + search_box->accept_event(); + + if (allow_multi_select) { + TreeItem *root = search_options->get_root(); + if (!root->get_first_child()) { + return; } - } break; - default: - break; + + TreeItem *current = search_options->get_selected(); + TreeItem *item = search_options->get_next_selected(root); + while (item) { + item->deselect(0); + item = search_options->get_next_selected(item); + } + + current->select(0); + current->set_as_cursor(0); + } } } } diff --git a/editor/editor_quick_open.h b/editor/editor_quick_open.h index bbc689040a6..815cc0c8fe9 100644 --- a/editor/editor_quick_open.h +++ b/editor/editor_quick_open.h @@ -69,7 +69,7 @@ class EditorQuickOpen : public ConfirmationDialog { virtual void cancel_pressed() override; void _cleanup(); - void _sbox_input(const Ref &p_ie); + void _sbox_input(const Ref &p_event); void _text_changed(const String &p_newtext); protected: diff --git a/editor/gui/scene_tree_editor.cpp b/editor/gui/scene_tree_editor.cpp index 52ba98b4d5c..1c153b0451f 100644 --- a/editor/gui/scene_tree_editor.cpp +++ b/editor/gui/scene_tree_editor.cpp @@ -1744,6 +1744,17 @@ void SceneTreeDialog::_filter_changed(const String &p_filter) { tree->set_filter(p_filter); } +void SceneTreeDialog::_on_filter_gui_input(const Ref &p_event) { + // Redirect navigational key events to the tree. + Ref key = p_event; + if (key.is_valid()) { + if (key->is_action("ui_up", true) || key->is_action("ui_down", true) || key->is_action("ui_page_up") || key->is_action("ui_page_down")) { + tree->get_scene_tree()->gui_input(key); + filter->accept_event(); + } + } +} + void SceneTreeDialog::_bind_methods() { ClassDB::bind_method("_cancel", &SceneTreeDialog::_cancel); @@ -1764,6 +1775,10 @@ SceneTreeDialog::SceneTreeDialog() { filter->set_clear_button_enabled(true); filter->add_theme_constant_override("minimum_character_width", 0); filter->connect(SceneStringName(text_changed), callable_mp(this, &SceneTreeDialog::_filter_changed)); + filter->connect(SceneStringName(gui_input), callable_mp(this, &SceneTreeDialog::_on_filter_gui_input)); + + register_text_enter(filter); + filter_hbc->add_child(filter); // Add 'Show All' button to HBoxContainer next to the filter, visible only when valid_types is defined. diff --git a/editor/gui/scene_tree_editor.h b/editor/gui/scene_tree_editor.h index b4d9644f167..63c2c027c28 100644 --- a/editor/gui/scene_tree_editor.h +++ b/editor/gui/scene_tree_editor.h @@ -195,6 +195,7 @@ class SceneTreeDialog : public ConfirmationDialog { void _cancel(); void _selected_changed(); void _filter_changed(const String &p_filter); + void _on_filter_gui_input(const Ref &p_event); void _show_all_nodes_changed(bool p_button_pressed); protected: diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index d7de5a72230..1222fd7c1fa 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -358,12 +358,14 @@ void ScriptEditorQuickOpen::_text_changed(const String &p_newtext) { _update_search(); } -void ScriptEditorQuickOpen::_sbox_input(const Ref &p_ie) { - Ref k = p_ie; - - if (k.is_valid() && (k->get_keycode() == Key::UP || k->get_keycode() == Key::DOWN || k->get_keycode() == Key::PAGEUP || k->get_keycode() == Key::PAGEDOWN)) { - search_options->gui_input(k); - search_box->accept_event(); +void ScriptEditorQuickOpen::_sbox_input(const Ref &p_event) { + // Redirect navigational key events to the tree. + Ref key = p_event; + if (key.is_valid()) { + if (key->is_action("ui_up", true) || key->is_action("ui_down", true) || key->is_action("ui_page_up") || key->is_action("ui_page_down")) { + search_options->gui_input(key); + search_box->accept_event(); + } } } diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index e0fac5d0c6e..8e82d606052 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -131,7 +131,7 @@ class ScriptEditorQuickOpen : public ConfirmationDialog { void _update_search(); - void _sbox_input(const Ref &p_ie); + void _sbox_input(const Ref &p_event); Vector functions; void _confirmed(); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index ea1756b65ae..8f646a76212 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -2174,19 +2174,13 @@ void ThemeTypeDialog::_add_type_filter_cbk(const String &p_value) { _update_add_type_options(p_value); } -void ThemeTypeDialog::_type_filter_input(const Ref &p_ie) { - Ref k = p_ie; - if (k.is_valid() && k->is_pressed()) { - switch (k->get_keycode()) { - case Key::UP: - case Key::DOWN: - case Key::PAGEUP: - case Key::PAGEDOWN: { - add_type_options->gui_input(k); - add_type_filter->accept_event(); - } break; - default: - break; +void ThemeTypeDialog::_type_filter_input(const Ref &p_event) { + // Redirect navigational key events to the item list. + Ref key = p_event; + if (key.is_valid()) { + if (key->is_action("ui_up", true) || key->is_action("ui_down", true) || key->is_action("ui_page_up") || key->is_action("ui_page_down")) { + add_type_options->gui_input(key); + add_type_filter->accept_event(); } } } diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h index ae92365c327..1d009637b7a 100644 --- a/editor/plugins/theme_editor_plugin.h +++ b/editor/plugins/theme_editor_plugin.h @@ -303,7 +303,7 @@ class ThemeTypeDialog : public ConfirmationDialog { void _update_add_type_options(const String &p_filter = ""); void _add_type_filter_cbk(const String &p_value); - void _type_filter_input(const Ref &p_ie); + void _type_filter_input(const Ref &p_event); void _add_type_options_cbk(int p_index); void _add_type_dialog_entered(const String &p_value); void _add_type_dialog_activated(int p_index); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 3059d10c4c3..53bf4696d67 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -2148,6 +2148,7 @@ String VisualShaderEditor::_get_description(int p_idx) { void VisualShaderEditor::_update_options_menu() { node_desc->set_text(""); + highend_label->set_visible(false); members_dialog->get_ok_button()->set_disabled(true); members->clear(); @@ -2312,6 +2313,8 @@ void VisualShaderEditor::_update_options_menu() { item->select(0); node_desc->set_text(options[i].description); is_first_item = false; + + members_dialog->get_ok_button()->set_disabled(false); } switch (options[i].return_type) { case VisualShaderNode::PORT_TYPE_SCALAR: @@ -4924,7 +4927,7 @@ void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos, VisualShaderNod Vector2 difference = (dialog_rect.get_end() - window_rect.get_end()).maxf(0); members_dialog->set_position(members_dialog->get_position() - difference); - callable_mp((Control *)node_filter, &Control::grab_focus).call_deferred(); // Still not visible. + node_filter->grab_focus(); node_filter->select_all(); } @@ -4947,6 +4950,8 @@ void VisualShaderEditor::_show_add_varying_dialog() { add_varying_dialog->set_position(graph->get_screen_position() + varying_button->get_position() + Point2(5 * EDSCALE, 65 * EDSCALE)); add_varying_dialog->popup(); + varying_name->grab_focus(); + // Keep dialog within window bounds. Rect2 window_rect = Rect2(DisplayServer::get_singleton()->window_get_position(), DisplayServer::get_singleton()->window_get_size()); Rect2 dialog_rect = Rect2(add_varying_dialog->get_position(), add_varying_dialog->get_size()); @@ -4958,6 +4963,8 @@ void VisualShaderEditor::_show_remove_varying_dialog() { remove_varying_dialog->set_position(graph->get_screen_position() + varying_button->get_position() + Point2(5 * EDSCALE, 65 * EDSCALE)); remove_varying_dialog->popup(); + varyings->grab_focus(); + // Keep dialog within window bounds. Rect2 window_rect = Rect2(DisplayServer::get_singleton()->window_get_position(), DisplayServer::get_singleton()->window_get_size()); Rect2 dialog_rect = Rect2(remove_varying_dialog->get_position(), remove_varying_dialog->get_size()); @@ -4965,11 +4972,14 @@ void VisualShaderEditor::_show_remove_varying_dialog() { remove_varying_dialog->set_position(remove_varying_dialog->get_position() - difference); } -void VisualShaderEditor::_sbox_input(const Ref &p_ie) { - Ref ie = p_ie; - if (ie.is_valid() && (ie->get_keycode() == Key::UP || ie->get_keycode() == Key::DOWN || ie->get_keycode() == Key::ENTER || ie->get_keycode() == Key::KP_ENTER)) { - members->gui_input(ie); - node_filter->accept_event(); +void VisualShaderEditor::_sbox_input(const Ref &p_event) { + // Redirect navigational key events to the tree. + Ref key = p_event; + if (key.is_valid()) { + if (key->is_action("ui_up", true) || key->is_action("ui_down", true) || key->is_action("ui_page_up") || key->is_action("ui_page_down")) { + members->gui_input(key); + node_filter->accept_event(); + } } } @@ -5700,9 +5710,6 @@ void VisualShaderEditor::_member_selected() { } } -void VisualShaderEditor::_member_unselected() { -} - void VisualShaderEditor::_member_create() { TreeItem *item = members->get_selected(); if (item != nullptr && item->has_meta("id")) { @@ -6092,7 +6099,6 @@ void VisualShaderEditor::_show_preview_text() { } else { code_preview_window->popup(); } - _preview_size_changed(); if (pending_update_preview) { _update_preview(); @@ -6105,14 +6111,9 @@ void VisualShaderEditor::_show_preview_text() { void VisualShaderEditor::_preview_close_requested() { code_preview_showed = false; - code_preview_window->hide(); code_preview_button->set_pressed(false); } -void VisualShaderEditor::_preview_size_changed() { - code_preview_vbox->set_custom_minimum_size(code_preview_window->get_size()); -} - static ShaderLanguage::DataType _visual_shader_editor_get_global_shader_uniform_type(const StringName &p_variable) { RS::GlobalShaderParameterType gvt = RS::get_singleton()->global_shader_parameter_get_type(p_variable); return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt); @@ -6460,12 +6461,12 @@ VisualShaderEditor::VisualShaderEditor() { // CODE PREVIEW /////////////////////////////////////// - code_preview_window = memnew(Window); + code_preview_window = memnew(AcceptDialog); code_preview_window->set_title(TTR("Generated Shader Code")); code_preview_window->set_visible(code_preview_showed); - code_preview_window->set_exclusive(true); - code_preview_window->connect("close_requested", callable_mp(this, &VisualShaderEditor::_preview_close_requested)); - code_preview_window->connect("size_changed", callable_mp(this, &VisualShaderEditor::_preview_size_changed)); + code_preview_window->set_ok_button_text(TTR("Close")); + code_preview_window->connect(SceneStringName(confirmed), callable_mp(this, &VisualShaderEditor::_preview_close_requested)); + code_preview_window->connect("canceled", callable_mp(this, &VisualShaderEditor::_preview_close_requested)); add_child(code_preview_window); code_preview_vbox = memnew(VBoxContainer); @@ -6612,7 +6613,6 @@ VisualShaderEditor::VisualShaderEditor() { members->set_custom_minimum_size(Size2(180 * EDSCALE, 200 * EDSCALE)); members->connect("item_activated", callable_mp(this, &VisualShaderEditor::_member_create)); members->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_member_selected)); - members->connect("nothing_selected", callable_mp(this, &VisualShaderEditor::_member_unselected)); HBoxContainer *desc_hbox = memnew(HBoxContainer); members_vb->add_child(desc_hbox); @@ -6638,21 +6638,20 @@ VisualShaderEditor::VisualShaderEditor() { members_dialog = memnew(ConfirmationDialog); members_dialog->set_title(TTR("Create Shader Node")); - members_dialog->set_exclusive(true); members_dialog->add_child(members_vb); members_dialog->set_ok_button_text(TTR("Create")); - members_dialog->get_ok_button()->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_member_create)); + members_dialog->connect(SceneStringName(confirmed), callable_mp(this, &VisualShaderEditor::_member_create)); members_dialog->get_ok_button()->set_disabled(true); members_dialog->connect("canceled", callable_mp(this, &VisualShaderEditor::_member_cancel)); + members_dialog->register_text_enter(node_filter); add_child(members_dialog); // add varyings dialog { add_varying_dialog = memnew(ConfirmationDialog); add_varying_dialog->set_title(TTR("Create Shader Varying")); - add_varying_dialog->set_exclusive(true); add_varying_dialog->set_ok_button_text(TTR("Create")); - add_varying_dialog->get_ok_button()->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_varying_create)); + add_varying_dialog->connect(SceneStringName(confirmed), callable_mp(this, &VisualShaderEditor::_varying_create)); add_varying_dialog->get_ok_button()->set_disabled(true); add_child(add_varying_dialog); @@ -6679,6 +6678,7 @@ VisualShaderEditor::VisualShaderEditor() { varying_name->set_custom_minimum_size(Size2(150 * EDSCALE, 0)); varying_name->set_h_size_flags(SIZE_EXPAND_FILL); varying_name->connect(SceneStringName(text_changed), callable_mp(this, &VisualShaderEditor::_varying_name_changed)); + add_varying_dialog->register_text_enter(varying_name); varying_mode = memnew(OptionButton); hb->add_child(varying_mode); @@ -6696,9 +6696,8 @@ VisualShaderEditor::VisualShaderEditor() { { remove_varying_dialog = memnew(ConfirmationDialog); remove_varying_dialog->set_title(TTR("Delete Shader Varying")); - remove_varying_dialog->set_exclusive(true); remove_varying_dialog->set_ok_button_text(TTR("Delete")); - remove_varying_dialog->get_ok_button()->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_varying_deleted)); + remove_varying_dialog->connect(SceneStringName(confirmed), callable_mp(this, &VisualShaderEditor::_varying_deleted)); add_child(remove_varying_dialog); VBoxContainer *vb = memnew(VBoxContainer); diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 69b2f30c406..3b2ad333041 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -230,7 +230,7 @@ class VisualShaderEditor : public ShaderEditor { bool pending_update_preview = false; bool shader_error = false; - Window *code_preview_window = nullptr; + AcceptDialog *code_preview_window = nullptr; VBoxContainer *code_preview_vbox = nullptr; CodeEdit *preview_text = nullptr; Ref syntax_highlighter = nullptr; @@ -576,9 +576,8 @@ class VisualShaderEditor : public ShaderEditor { void _graph_gui_input(const Ref &p_event); void _member_filter_changed(const String &p_text); - void _sbox_input(const Ref &p_ie); + void _sbox_input(const Ref &p_event); void _member_selected(); - void _member_unselected(); void _member_create(); void _member_cancel(); diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp index d47270841da..f4409a86590 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -30,49 +30,38 @@ #include "property_selector.h" -#include "core/os/keyboard.h" -#include "editor/doc_tools.h" #include "editor/editor_help.h" #include "editor/editor_node.h" #include "editor/themes/editor_scale.h" #include "scene/gui/line_edit.h" -#include "scene/gui/rich_text_label.h" #include "scene/gui/tree.h" void PropertySelector::_text_changed(const String &p_newtext) { _update_search(); } -void PropertySelector::_sbox_input(const Ref &p_ie) { - Ref k = p_ie; - - if (k.is_valid()) { - switch (k->get_keycode()) { - case Key::UP: - case Key::DOWN: - case Key::PAGEUP: - case Key::PAGEDOWN: { - search_options->gui_input(k); - search_box->accept_event(); - - TreeItem *root = search_options->get_root(); - if (!root->get_first_child()) { - break; - } - - TreeItem *current = search_options->get_selected(); +void PropertySelector::_sbox_input(const Ref &p_event) { + // Redirect navigational key events to the tree. + Ref key = p_event; + if (key.is_valid()) { + if (key->is_action("ui_up", true) || key->is_action("ui_down", true) || key->is_action("ui_page_up") || key->is_action("ui_page_down")) { + search_options->gui_input(key); + search_box->accept_event(); + + TreeItem *root = search_options->get_root(); + if (!root->get_first_child()) { + return; + } - TreeItem *item = search_options->get_next_selected(root); - while (item) { - item->deselect(0); - item = search_options->get_next_selected(item); - } + TreeItem *current = search_options->get_selected(); - current->select(0); + TreeItem *item = search_options->get_next_selected(root); + while (item) { + item->deselect(0); + item = search_options->get_next_selected(item); + } - } break; - default: - break; + current->select(0); } } } @@ -313,7 +302,7 @@ void PropertySelector::_update_search() { } } - get_ok_button()->set_disabled(root->get_first_child() == nullptr); + get_ok_button()->set_disabled(search_options->get_selected() == nullptr); } void PropertySelector::_confirmed() { @@ -329,6 +318,8 @@ void PropertySelector::_item_selected() { help_bit->set_custom_text(String(), String(), String()); TreeItem *item = search_options->get_selected(); + get_ok_button()->set_disabled(item == nullptr); + if (!item) { return; } diff --git a/editor/property_selector.h b/editor/property_selector.h index 34cade9267d..48bc8a05484 100644 --- a/editor/property_selector.h +++ b/editor/property_selector.h @@ -45,7 +45,7 @@ class PropertySelector : public ConfirmationDialog { Tree *search_options = nullptr; void _text_changed(const String &p_newtext); - void _sbox_input(const Ref &p_ie); + void _sbox_input(const Ref &p_event); void _update_search(); void _confirmed(); void _item_selected(); diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp index ea63e071042..07848c61db6 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.cpp +++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp @@ -815,13 +815,14 @@ void GridMapEditor::_text_changed(const String &p_text) { update_palette(); } -void GridMapEditor::_sbox_input(const Ref &p_ie) { - const Ref k = p_ie; - - if (k.is_valid() && (k->get_keycode() == Key::UP || k->get_keycode() == Key::DOWN || k->get_keycode() == Key::PAGEUP || k->get_keycode() == Key::PAGEDOWN)) { - // Forward the key input to the ItemList so it can be scrolled - mesh_library_palette->gui_input(k); - search_box->accept_event(); +void GridMapEditor::_sbox_input(const Ref &p_event) { + // Redirect navigational key events to the item list. + Ref key = p_event; + if (key.is_valid()) { + if (key->is_action("ui_up", true) || key->is_action("ui_down", true) || key->is_action("ui_page_up") || key->is_action("ui_page_down")) { + mesh_library_palette->gui_input(key); + search_box->accept_event(); + } } } diff --git a/modules/gridmap/editor/grid_map_editor_plugin.h b/modules/gridmap/editor/grid_map_editor_plugin.h index cfa0f0c35ce..4294c93c936 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.h +++ b/modules/gridmap/editor/grid_map_editor_plugin.h @@ -199,7 +199,7 @@ class GridMapEditor : public VBoxContainer { void _update_theme(); void _text_changed(const String &p_text); - void _sbox_input(const Ref &p_ie); + void _sbox_input(const Ref &p_event); void _mesh_library_palette_input(const Ref &p_ie); void _icon_size_changed(float p_value); diff --git a/modules/multiplayer/editor/replication_editor.cpp b/modules/multiplayer/editor/replication_editor.cpp index 851ad858769..386feae4f9b 100644 --- a/modules/multiplayer/editor/replication_editor.cpp +++ b/modules/multiplayer/editor/replication_editor.cpp @@ -93,24 +93,6 @@ void ReplicationEditor::_pick_node_select_recursive(TreeItem *p_item, const Stri } } -void ReplicationEditor::_pick_node_filter_input(const Ref &p_ie) { - Ref k = p_ie; - - if (k.is_valid()) { - switch (k->get_keycode()) { - case Key::UP: - case Key::DOWN: - case Key::PAGEUP: - case Key::PAGEDOWN: { - pick_node->get_scene_tree()->get_scene_tree()->gui_input(k); - pick_node->get_filter_line_edit()->accept_event(); - } break; - default: - break; - } - } -} - void ReplicationEditor::_pick_node_selected(NodePath p_path) { Node *root = current->get_node(current->get_root_path()); ERR_FAIL_NULL(root); @@ -184,11 +166,9 @@ ReplicationEditor::ReplicationEditor() { pick_node = memnew(SceneTreeDialog); add_child(pick_node); - pick_node->register_text_enter(pick_node->get_filter_line_edit()); pick_node->set_title(TTR("Pick a node to synchronize:")); pick_node->connect("selected", callable_mp(this, &ReplicationEditor::_pick_node_selected)); pick_node->get_filter_line_edit()->connect(SceneStringName(text_changed), callable_mp(this, &ReplicationEditor::_pick_node_filter_text_changed)); - pick_node->get_filter_line_edit()->connect("gui_input", callable_mp(this, &ReplicationEditor::_pick_node_filter_input)); prop_selector = memnew(PropertySelector); add_child(prop_selector); diff --git a/modules/multiplayer/editor/replication_editor.h b/modules/multiplayer/editor/replication_editor.h index 8f117742923..017fa739679 100644 --- a/modules/multiplayer/editor/replication_editor.h +++ b/modules/multiplayer/editor/replication_editor.h @@ -81,7 +81,6 @@ class ReplicationEditor : public VBoxContainer { void _pick_node_filter_text_changed(const String &p_newtext); void _pick_node_select_recursive(TreeItem *p_item, const String &p_filter, Vector &p_select_candidates); - void _pick_node_filter_input(const Ref &p_ie); void _pick_node_selected(NodePath p_path); void _pick_new_property(); From 608d5598e85556133cccf522b100d0f0cf1b4017 Mon Sep 17 00:00:00 2001 From: Lars Pettersson Date: Sat, 31 Aug 2024 21:38:15 +0200 Subject: [PATCH 007/237] Fix Path2D editor not updating gizmos on selection --- editor/plugins/path_2d_editor_plugin.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index 5b23cf44d03..a8083c22d7f 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -468,6 +468,8 @@ void Path2DEditor::edit(Node *p_path2d) { } node = nullptr; } + + canvas_item_editor->update_viewport(); } void Path2DEditor::_bind_methods() { @@ -718,7 +720,6 @@ bool Path2DEditorPlugin::handles(Object *p_object) const { void Path2DEditorPlugin::make_visible(bool p_visible) { if (p_visible) { path2d_editor->show(); - } else { path2d_editor->hide(); path2d_editor->edit(nullptr); From 28b95ff55010d8f9e3f9feca4f75e5aeaf1ac9aa Mon Sep 17 00:00:00 2001 From: Alvin Wong Date: Sun, 1 Sep 2024 04:03:00 +0800 Subject: [PATCH 008/237] Remove ARFLAGS hack for Windows, replace with TEMPFILE TEMPFILE is the built-in way of SCons to use a response file for command lines that are too long. --- methods.py | 24 ++++++------------------ platform/windows/detect.py | 5 +++++ 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/methods.py b/methods.py index bfd08cfc7b5..c24e110edae 100644 --- a/methods.py +++ b/methods.py @@ -467,16 +467,6 @@ def use_windows_spawn_fix(self, platform=None): if os.name != "nt": return # not needed, only for windows - # On Windows, due to the limited command line length, when creating a static library - # from a very high number of objects SCons will invoke "ar" once per object file; - # that makes object files with same names to be overwritten so the last wins and - # the library loses symbols defined by overwritten objects. - # By enabling quick append instead of the default mode (replacing), libraries will - # got built correctly regardless the invocation strategy. - # Furthermore, since SCons will rebuild the library from scratch when an object file - # changes, no multiple versions of the same object file will be present. - self.Replace(ARFLAGS="q") - def mySubProcess(cmdline, env): startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW @@ -500,19 +490,17 @@ def mySubProcess(cmdline, env): return rv def mySpawn(sh, escape, cmd, args, env): + # Used by TEMPFILE. + if cmd == "del": + os.remove(args[1]) + return 0 + newargs = " ".join(args[1:]) cmdline = cmd + " " + newargs rv = 0 env = {str(key): str(value) for key, value in iter(env.items())} - if len(cmdline) > 32000 and cmd.endswith("ar"): - cmdline = cmd + " " + args[1] + " " + args[2] + " " - for i in range(3, len(args)): - rv = mySubProcess(cmdline + args[i], env) - if rv: - break - else: - rv = mySubProcess(cmdline, env) + rv = mySubProcess(cmdline, env) return rv diff --git a/platform/windows/detect.py b/platform/windows/detect.py index d2a9c2315ff..ff25e416ae9 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -654,6 +654,11 @@ def configure_mingw(env: "SConsEnvironment"): # https://www.scons.org/wiki/LongCmdLinesOnWin32 env.use_windows_spawn_fix() + # In case the command line to AR is too long, use a response file. + env["ARCOM_ORIG"] = env["ARCOM"] + env["ARCOM"] = "${TEMPFILE('$ARCOM_ORIG', '$ARCOMSTR')}" + env["TEMPFILESUFFIX"] = ".rsp" + ## Build type if not env["use_llvm"] and not try_cmd("gcc --version", env["mingw_prefix"], env["arch"]): From f82262eecb558accb926628aa95b6e66209dcad3 Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Mon, 2 Sep 2024 01:28:07 -0700 Subject: [PATCH 009/237] GLTF: Add append_gltf_node to GLTFState --- modules/gltf/doc_classes/GLTFNode.xml | 7 ++++++ modules/gltf/doc_classes/GLTFState.xml | 11 +++++++++ modules/gltf/gltf_document.cpp | 34 ++++++++++---------------- modules/gltf/gltf_document.h | 6 ----- modules/gltf/gltf_state.cpp | 14 +++++++++++ modules/gltf/gltf_state.h | 1 + modules/gltf/structures/gltf_node.cpp | 5 ++++ modules/gltf/structures/gltf_node.h | 1 + 8 files changed, 52 insertions(+), 27 deletions(-) diff --git a/modules/gltf/doc_classes/GLTFNode.xml b/modules/gltf/doc_classes/GLTFNode.xml index 2786c25e9ad..a242a0d1d8b 100644 --- a/modules/gltf/doc_classes/GLTFNode.xml +++ b/modules/gltf/doc_classes/GLTFNode.xml @@ -12,6 +12,13 @@ https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_004_ScenesNodes.md" + + + + + Appends the given child node index to the [member children] array. + + diff --git a/modules/gltf/doc_classes/GLTFState.xml b/modules/gltf/doc_classes/GLTFState.xml index c049acf557e..de7ec2a4ca5 100644 --- a/modules/gltf/doc_classes/GLTFState.xml +++ b/modules/gltf/doc_classes/GLTFState.xml @@ -28,6 +28,17 @@ Appends the given byte array data to the buffers and creates a [GLTFBufferView] for it. The index of the destination [GLTFBufferView] is returned. If [param deduplication] is true, the buffers will first be searched for duplicate data, otherwise new bytes will always be appended. + + + + + + + Append the given [GLTFNode] to the state, and return its new index. This can be used to export one Godot node as multiple glTF nodes, or inject new glTF nodes at import time. On import, this must be called before [method GLTFDocumentExtension._generate_scene_node] finishes for the parent node. On export, this must be called before [method GLTFDocumentExtension._export_node] runs for the parent node. + The [param godot_scene_node] parameter is the Godot scene node that corresponds to this glTF node. This is highly recommended to be set to a valid node, but may be null if there is no corresponding Godot scene node. One Godot scene node may be used for multiple glTF nodes, so if exporting multiple glTF nodes for one Godot scene node, use the same Godot scene node for each. + The [param parent_node_index] parameter is the index of the parent [GLTFNode] in the state. If [code]-1[/code], the node will be a root node, otherwise the new node will be added to the parent's list of children. The index will also be written to the [member GLTFNode.parent] property of the new node. + + diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 69973a34dd6..acb72c552fa 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -414,7 +414,6 @@ static Vector _xform_to_array(const Transform3D p_transform) { Error GLTFDocument::_serialize_nodes(Ref p_state) { Array nodes; - const int scene_node_count = p_state->scene_nodes.size(); for (int i = 0; i < p_state->nodes.size(); i++) { Dictionary node; Ref gltf_node = p_state->nodes[i]; @@ -465,7 +464,7 @@ Error GLTFDocument::_serialize_nodes(Ref p_state) { } Node *scene_node = nullptr; - if (i < scene_node_count) { + if (i < (int)p_state->scene_nodes.size()) { scene_node = p_state->scene_nodes[i]; } for (Ref ext : document_extensions) { @@ -5264,6 +5263,7 @@ void GLTFDocument::_convert_scene_node(Ref p_state, Node *p_current, gltf_node.instantiate(); gltf_node->set_original_name(p_current->get_name()); gltf_node->set_name(_gen_unique_name(p_state, p_current->get_name())); + gltf_node->merge_meta_from(p_current); if (cast_to(p_current)) { Node3D *spatial = cast_to(p_current); _convert_spatial(p_state, spatial, gltf_node); @@ -5309,14 +5309,18 @@ void GLTFDocument::_convert_scene_node(Ref p_state, Node *p_current, ERR_CONTINUE(ext.is_null()); ext->convert_scene_node(p_state, gltf_node, p_current); } - GLTFNodeIndex current_node_i = p_state->nodes.size(); - GLTFNodeIndex gltf_root = p_gltf_root; - if (gltf_root == -1) { - gltf_root = current_node_i; - p_state->root_nodes.push_back(gltf_root); + GLTFNodeIndex current_node_i; + if (gltf_node->get_parent() == -1) { + current_node_i = p_state->append_gltf_node(gltf_node, p_current, p_gltf_parent); + } else if (gltf_node->get_parent() < -1) { + return; + } else { + current_node_i = p_state->nodes.size() - 1; + while (gltf_node != p_state->nodes[current_node_i]) { + current_node_i--; + } } - gltf_node->merge_meta_from(p_current); - _create_gltf_node(p_state, p_current, current_node_i, p_gltf_parent, gltf_root, gltf_node); + const GLTFNodeIndex gltf_root = (p_gltf_root == -1) ? current_node_i : p_gltf_root; for (int node_i = 0; node_i < p_current->get_child_count(); node_i++) { _convert_scene_node(p_state, p_current->get_child(node_i), current_node_i, gltf_root); } @@ -5377,18 +5381,6 @@ void GLTFDocument::_convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeInd } #endif // MODULE_CSG_ENABLED -void GLTFDocument::_create_gltf_node(Ref p_state, Node *p_scene_parent, GLTFNodeIndex p_current_node_i, - GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_gltf_node, Ref p_gltf_node) { - p_state->scene_nodes.insert(p_current_node_i, p_scene_parent); - p_state->nodes.push_back(p_gltf_node); - ERR_FAIL_COND(p_current_node_i == p_parent_node_index); - p_state->nodes.write[p_current_node_i]->parent = p_parent_node_index; - if (p_parent_node_index == -1) { - return; - } - p_state->nodes.write[p_parent_node_index]->children.push_back(p_current_node_i); -} - void GLTFDocument::_convert_animation_player_to_gltf(AnimationPlayer *p_animation_player, Ref p_state, GLTFNodeIndex p_gltf_current, GLTFNodeIndex p_gltf_root_index, Ref p_gltf_node, Node *p_scene_parent) { ERR_FAIL_NULL(p_animation_player); p_state->animation_players.push_back(p_animation_player); diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index b3e6dcf54a6..d347d491029 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -342,12 +342,6 @@ class GLTFDocument : public Resource { void _convert_csg_shape_to_gltf(CSGShape3D *p_current, GLTFNodeIndex p_gltf_parent, Ref p_gltf_node, Ref p_state); #endif // MODULE_CSG_ENABLED - void _create_gltf_node(Ref p_state, - Node *p_scene_parent, - GLTFNodeIndex p_current_node_i, - GLTFNodeIndex p_parent_node_index, - GLTFNodeIndex p_root_gltf_node, - Ref p_gltf_node); void _convert_animation_player_to_gltf( AnimationPlayer *p_animation_player, Ref p_state, GLTFNodeIndex p_gltf_current, diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp index 73a61ff77f2..7763874d028 100644 --- a/modules/gltf/gltf_state.cpp +++ b/modules/gltf/gltf_state.cpp @@ -35,6 +35,7 @@ void GLTFState::_bind_methods() { ClassDB::bind_method(D_METHOD("add_used_extension", "extension_name", "required"), &GLTFState::add_used_extension); ClassDB::bind_method(D_METHOD("append_data_to_buffers", "data", "deduplication"), &GLTFState::append_data_to_buffers); + ClassDB::bind_method(D_METHOD("append_gltf_node", "gltf_node", "godot_scene_node", "parent_node_index"), &GLTFState::append_gltf_node); ClassDB::bind_method(D_METHOD("get_json"), &GLTFState::get_json); ClassDB::bind_method(D_METHOD("set_json", "json"), &GLTFState::set_json); @@ -441,3 +442,16 @@ GLTFBufferViewIndex GLTFState::append_data_to_buffers(const Vector &p_d buffer_views.push_back(buffer_view); return new_index; } + +GLTFNodeIndex GLTFState::append_gltf_node(Ref p_gltf_node, Node *p_godot_scene_node, GLTFNodeIndex p_parent_node_index) { + p_gltf_node->set_parent(p_parent_node_index); + const GLTFNodeIndex new_index = nodes.size(); + nodes.append(p_gltf_node); + scene_nodes.insert(new_index, p_godot_scene_node); + if (p_parent_node_index == -1) { + root_nodes.append(new_index); + } else if (p_parent_node_index < new_index) { + nodes.write[p_parent_node_index]->append_child_index(new_index); + } + return new_index; +} diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index 07efafe13bf..79540491926 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -119,6 +119,7 @@ class GLTFState : public Resource { void add_used_extension(const String &p_extension, bool p_required = false); GLTFBufferViewIndex append_data_to_buffers(const Vector &p_data, const bool p_deduplication); + GLTFNodeIndex append_gltf_node(Ref p_gltf_node, Node *p_godot_scene_node, GLTFNodeIndex p_parent_node_index); enum GLTFHandleBinary { HANDLE_BINARY_DISCARD_TEXTURES = 0, diff --git a/modules/gltf/structures/gltf_node.cpp b/modules/gltf/structures/gltf_node.cpp index 2934e4b5ee6..ccee5e8ca43 100644 --- a/modules/gltf/structures/gltf_node.cpp +++ b/modules/gltf/structures/gltf_node.cpp @@ -55,6 +55,7 @@ void GLTFNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_scale", "scale"), &GLTFNode::set_scale); ClassDB::bind_method(D_METHOD("get_children"), &GLTFNode::get_children); ClassDB::bind_method(D_METHOD("set_children", "children"), &GLTFNode::set_children); + ClassDB::bind_method(D_METHOD("append_child_index", "child_index"), &GLTFNode::append_child_index); ClassDB::bind_method(D_METHOD("get_light"), &GLTFNode::get_light); ClassDB::bind_method(D_METHOD("set_light", "light"), &GLTFNode::set_light); ClassDB::bind_method(D_METHOD("get_additional_data", "extension_name"), &GLTFNode::get_additional_data); @@ -170,6 +171,10 @@ void GLTFNode::set_children(Vector p_children) { children = p_children; } +void GLTFNode::append_child_index(int p_child_index) { + children.append(p_child_index); +} + GLTFLightIndex GLTFNode::get_light() { return light; } diff --git a/modules/gltf/structures/gltf_node.h b/modules/gltf/structures/gltf_node.h index 63399fb32bc..f3f6bfa2f16 100644 --- a/modules/gltf/structures/gltf_node.h +++ b/modules/gltf/structures/gltf_node.h @@ -97,6 +97,7 @@ class GLTFNode : public Resource { Vector get_children(); void set_children(Vector p_children); + void append_child_index(int p_child_index); GLTFLightIndex get_light(); void set_light(GLTFLightIndex p_light); From 8835f326b1b8ae0727727fec93ddb1e871571f32 Mon Sep 17 00:00:00 2001 From: Ryan <73148864+Ryan-000@users.noreply.github.com> Date: Sat, 24 Aug 2024 01:58:54 -0400 Subject: [PATCH 010/237] Expose get_rpc_config and get_node_rpc_config add documentation Update doc/classes/Node.xml change name of get_node_rpc_config to get_rpc_config Co-Authored-By: moondog <159832633+dog-on-moon@users.noreply.github.com> Co-Authored-By: Micky <66727710+Mickeon@users.noreply.github.com> --- core/object/script_language.cpp | 2 ++ core/object/script_language.h | 2 +- core/object/script_language_extension.h | 2 +- doc/classes/Node.xml | 6 ++++++ doc/classes/Script.xml | 6 ++++++ modules/gdscript/gdscript.cpp | 2 +- modules/gdscript/gdscript.h | 2 +- modules/mono/csharp_script.cpp | 2 +- modules/mono/csharp_script.h | 2 +- modules/multiplayer/scene_rpc_interface.cpp | 2 +- scene/main/node.cpp | 3 ++- scene/main/node.h | 4 ++-- 12 files changed, 25 insertions(+), 10 deletions(-) diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index cdc56e5ec51..652e3164c64 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -173,6 +173,8 @@ void Script::_bind_methods() { ClassDB::bind_method(D_METHOD("is_tool"), &Script::is_tool); ClassDB::bind_method(D_METHOD("is_abstract"), &Script::is_abstract); + ClassDB::bind_method(D_METHOD("get_rpc_config"), &Script::get_rpc_config); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "source_code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_source_code", "get_source_code"); } diff --git a/core/object/script_language.h b/core/object/script_language.h index 59a43a7b297..2238a29649f 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -180,7 +180,7 @@ class Script : public Resource { virtual bool is_placeholder_fallback_enabled() const { return false; } - virtual const Variant get_rpc_config() const = 0; + virtual Variant get_rpc_config() const = 0; Script() {} }; diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index c9344f5799b..bc773c5ad34 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -205,7 +205,7 @@ class ScriptExtension : public Script { GDVIRTUAL0RC(Variant, _get_rpc_config) - virtual const Variant get_rpc_config() const override { + virtual Variant get_rpc_config() const override { Variant ret; GDVIRTUAL_REQUIRED_CALL(_get_rpc_config, ret); return ret; diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index c54219c0566..2d309f62165 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -498,6 +498,12 @@ Returns the time elapsed (in seconds) since the last process callback. This value is identical to [method _process]'s [code]delta[/code] parameter, and may vary from frame to frame. See also [constant NOTIFICATION_PROCESS]. + + + + Returns a [Dictionary] mapping method names to their RPC configuration defined for this node using [method rpc_config]. + + diff --git a/doc/classes/Script.xml b/doc/classes/Script.xml index 45f0bbb8aac..80aad9d30d1 100644 --- a/doc/classes/Script.xml +++ b/doc/classes/Script.xml @@ -58,6 +58,12 @@ Returns the default value of the specified property. + + + + Returns a [Dictionary] mapping method names to their RPC configuration defined by this script. + + diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 7bf5e946fbb..663838932be 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -904,7 +904,7 @@ void GDScript::get_members(HashSet *p_members) { } } -const Variant GDScript::get_rpc_config() const { +Variant GDScript::get_rpc_config() const { return rpc_config; } diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 6527a0ea4dc..4ff57d1c2e3 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -334,7 +334,7 @@ class GDScript : public Script { virtual void get_constants(HashMap *p_constants) override; virtual void get_members(HashSet *p_members) override; - virtual const Variant get_rpc_config() const override; + virtual Variant get_rpc_config() const override; void unload_static() const; diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 6d561c15663..cb9d9dc8fbd 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -2716,7 +2716,7 @@ int CSharpScript::get_member_line(const StringName &p_member) const { return -1; } -const Variant CSharpScript::get_rpc_config() const { +Variant CSharpScript::get_rpc_config() const { return rpc_config; } diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index c48e1a95c98..ec7328be4a4 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -284,7 +284,7 @@ class CSharpScript : public Script { int get_member_line(const StringName &p_member) const override; - const Variant get_rpc_config() const override; + Variant get_rpc_config() const override; #ifdef TOOLS_ENABLED bool is_placeholder_fallback_enabled() const override { diff --git a/modules/multiplayer/scene_rpc_interface.cpp b/modules/multiplayer/scene_rpc_interface.cpp index 1463598ddc6..5e1067a8a4f 100644 --- a/modules/multiplayer/scene_rpc_interface.cpp +++ b/modules/multiplayer/scene_rpc_interface.cpp @@ -108,7 +108,7 @@ const SceneRPCInterface::RPCConfigCache &SceneRPCInterface::_get_node_config(con return rpc_cache[oid]; } RPCConfigCache cache; - _parse_rpc_config(p_node->get_node_rpc_config(), true, cache); + _parse_rpc_config(p_node->get_rpc_config(), true, cache); if (p_node->get_script_instance()) { _parse_rpc_config(p_node->get_script_instance()->get_rpc_config(), false, cache); } diff --git a/scene/main/node.cpp b/scene/main/node.cpp index de6d49761b5..488acd2ed18 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -757,7 +757,7 @@ void Node::rpc_config(const StringName &p_method, const Variant &p_config) { } } -const Variant Node::get_node_rpc_config() const { +Variant Node::get_rpc_config() const { return data.rpc_config; } @@ -3640,6 +3640,7 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer); ClassDB::bind_method(D_METHOD("rpc_config", "method", "config"), &Node::rpc_config); + ClassDB::bind_method(D_METHOD("get_rpc_config"), &Node::get_rpc_config); ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description); ClassDB::bind_method(D_METHOD("get_editor_description"), &Node::get_editor_description); diff --git a/scene/main/node.h b/scene/main/node.h index 2f6372dad58..7d42af71416 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -199,7 +199,7 @@ class Node : public Object { void *process_group = nullptr; // to avoid cyclic dependency int multiplayer_authority = 1; // Server by default. - Variant rpc_config; + Variant rpc_config = Dictionary(); // Variables used to properly sort the node when processing, ignored otherwise. int process_priority = 0; @@ -717,7 +717,7 @@ class Node : public Object { bool is_multiplayer_authority() const; void rpc_config(const StringName &p_method, const Variant &p_config); // config a local method for RPC - const Variant get_node_rpc_config() const; + Variant get_rpc_config() const; template Error rpc(const StringName &p_method, VarArgs... p_args); From 8155c1f836806f24ec055c7d3c109cee2c993110 Mon Sep 17 00:00:00 2001 From: HolonProduction Date: Sat, 7 Sep 2024 16:23:02 +0200 Subject: [PATCH 011/237] LSP: Don't use smart resolve for completion --- .../language_server/gdscript_text_document.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp index fa5f279db9f..ad35513bc8f 100644 --- a/modules/gdscript/language_server/gdscript_text_document.cpp +++ b/modules/gdscript/language_server/gdscript_text_document.cpp @@ -229,19 +229,6 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) { arr[i] = item.to_json(); i++; } - } else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) { - arr = native_member_completions.duplicate(); - - for (KeyValue &E : GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts) { - ExtendGDScriptParser *scr = E.value; - const Array &items = scr->get_member_completions(); - - const int start_size = arr.size(); - arr.resize(start_size + items.size()); - for (int i = start_size; i < arr.size(); i++) { - arr[i] = items[i - start_size]; - } - } } return arr; } From 86762f0a03206998bddc539a80c438c2da5068ce Mon Sep 17 00:00:00 2001 From: Elliot Fontaine <92150839+elliotfontaine@users.noreply.github.com> Date: Sat, 7 Sep 2024 15:14:38 +0200 Subject: [PATCH 012/237] Code Editor: Add button to toggle between search and search+replace modes --- editor/code_editor.cpp | 22 ++++++++++++++++++++++ editor/code_editor.h | 3 +++ 2 files changed, 25 insertions(+) diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index dd8aa523c46..59783c58b58 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -108,6 +108,7 @@ void FindReplaceBar::_notification(int p_what) { hide_button->set_texture_hover(get_editor_theme_icon(SNAME("Close"))); hide_button->set_texture_pressed(get_editor_theme_icon(SNAME("Close"))); hide_button->set_custom_minimum_size(hide_button->get_texture_normal()->get_size()); + _update_toggle_replace_button(replace_text->is_visible_in_tree()); } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -539,6 +540,14 @@ void FindReplaceBar::_hide_bar(bool p_force_focus) { hide(); } +void FindReplaceBar::_update_toggle_replace_button(bool p_replace_visible) { + String tooltip = p_replace_visible ? TTR("Hide Replace") : TTR("Show Replace"); + String shortcut = ED_GET_SHORTCUT(p_replace_visible ? "script_text_editor/find" : "script_text_editor/replace")->get_as_text(); + toggle_replace_button->set_tooltip_text(vformat("%s (%s)", tooltip, shortcut)); + StringName rtl_compliant_arrow = is_layout_rtl() ? SNAME("GuiTreeArrowLeft") : SNAME("GuiTreeArrowRight"); + toggle_replace_button->set_icon(get_editor_theme_icon(p_replace_visible ? SNAME("GuiTreeArrowDown") : rtl_compliant_arrow)); +} + void FindReplaceBar::_show_search(bool p_with_replace, bool p_show_only) { show(); if (p_show_only) { @@ -582,6 +591,7 @@ void FindReplaceBar::popup_search(bool p_show_only) { hbc_button_replace->hide(); hbc_option_replace->hide(); selection_only->set_pressed(false); + _update_toggle_replace_button(false); _show_search(false, p_show_only); } @@ -591,6 +601,7 @@ void FindReplaceBar::popup_replace() { replace_text->show(); hbc_button_replace->show(); hbc_option_replace->show(); + _update_toggle_replace_button(true); } selection_only->set_pressed(text_editor->has_selection(0) && text_editor->get_selection_from_line(0) < text_editor->get_selection_to_line(0)); @@ -644,6 +655,11 @@ void FindReplaceBar::_replace_text_submitted(const String &p_text) { } } +void FindReplaceBar::_toggle_replace_pressed() { + bool replace_visible = replace_text->is_visible_in_tree(); + replace_visible ? popup_search(true) : popup_replace(); +} + String FindReplaceBar::get_search_text() const { return search_text->get_text(); } @@ -702,6 +718,12 @@ void FindReplaceBar::_bind_methods() { } FindReplaceBar::FindReplaceBar() { + toggle_replace_button = memnew(Button); + add_child(toggle_replace_button); + toggle_replace_button->set_flat(true); + toggle_replace_button->set_focus_mode(FOCUS_NONE); + toggle_replace_button->connect(SceneStringName(pressed), callable_mp(this, &FindReplaceBar::_toggle_replace_pressed)); + vbc_lineedit = memnew(VBoxContainer); add_child(vbc_lineedit); vbc_lineedit->set_alignment(BoxContainer::ALIGNMENT_CENTER); diff --git a/editor/code_editor.h b/editor/code_editor.h index e56405a4b2f..c1c65a2a4a5 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -70,6 +70,7 @@ class FindReplaceBar : public HBoxContainer { SEARCH_PREV, }; + Button *toggle_replace_button = nullptr; LineEdit *search_text = nullptr; Label *matches_label = nullptr; Button *find_prev = nullptr; @@ -106,12 +107,14 @@ class FindReplaceBar : public HBoxContainer { void _show_search(bool p_with_replace, bool p_show_only); void _hide_bar(bool p_force_focus = false); + void _update_toggle_replace_button(bool p_replace_visible); void _editor_text_changed(); void _search_options_changed(bool p_pressed); void _search_text_changed(const String &p_text); void _search_text_submitted(const String &p_text); void _replace_text_submitted(const String &p_text); + void _toggle_replace_pressed(); protected: void _notification(int p_what); From 4d713d91b589155976150c64128a66fa7996510e Mon Sep 17 00:00:00 2001 From: HolonProduction Date: Sun, 8 Sep 2024 21:07:19 +0200 Subject: [PATCH 013/237] LSP: Omit some values based on specification version 3.17 --- modules/gdscript/language_server/godot_lsp.h | 32 ++++++++++++-------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/modules/gdscript/language_server/godot_lsp.h b/modules/gdscript/language_server/godot_lsp.h index bdf339f5fe3..6e19cd7a233 100644 --- a/modules/gdscript/language_server/godot_lsp.h +++ b/modules/gdscript/language_server/godot_lsp.h @@ -958,28 +958,30 @@ struct CompletionItem { /** * A string that should be used when comparing this item - * with other items. When `falsy` the label is used. + * with other items. When omitted the label is used + * as the filter text for this item. */ String sortText; /** * A string that should be used when filtering a set of - * completion items. When `falsy` the label is used. + * completion items. When omitted the label is used as the + * filter text for this item. */ String filterText; /** * A string that should be inserted into a document when selecting - * this completion. When `falsy` the label is used. + * this completion. When omitted the label is used as the insert text + * for this item. * * The `insertText` is subject to interpretation by the client side. * Some tools might not take the string literally. For example - * VS Code when code complete is requested in this example `con` - * and a completion item with an `insertText` of `console` is provided it - * will only insert `sole`. Therefore it is recommended to use `textEdit` instead - * since it avoids additional client side interpretation. - * - * @deprecated Use textEdit instead. + * VS Code when code complete is requested in this example + * `con` and a completion item with an `insertText` of + * `console` is provided it will only insert `sole`. Therefore it is + * recommended to use `textEdit` instead since it avoids additional client + * side interpretation. */ String insertText; @@ -1034,14 +1036,20 @@ struct CompletionItem { dict["label"] = label; dict["kind"] = kind; dict["data"] = data; - dict["insertText"] = insertText; + if (!insertText.is_empty()) { + dict["insertText"] = insertText; + } if (resolved) { dict["detail"] = detail; dict["documentation"] = documentation.to_json(); dict["deprecated"] = deprecated; dict["preselect"] = preselect; - dict["sortText"] = sortText; - dict["filterText"] = filterText; + if (!sortText.is_empty()) { + dict["sortText"] = sortText; + } + if (!filterText.is_empty()) { + dict["filterText"] = filterText; + } if (commitCharacters.size()) { dict["commitCharacters"] = commitCharacters; } From ec8374643ef81ff8fce532f96397d7b68521ef3a Mon Sep 17 00:00:00 2001 From: aXu-AP <1621768+aXu-AP@users.noreply.github.com> Date: Sun, 8 Sep 2024 23:24:13 +0300 Subject: [PATCH 014/237] Allow opening of polygon editor without texture There's no reason to deny access to polygon editor when there's no texture set. --- editor/plugins/polygon_2d_editor_plugin.cpp | 23 +++++++-------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index b8a309bc605..842142db79a 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -326,12 +326,6 @@ void Polygon2DEditor::_menu_option(int p_option) { EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); switch (p_option) { case MODE_EDIT_UV: { - if (node->get_texture().is_null()) { - error->set_text(TTR("No texture in this polygon.\nSet a texture to be able to edit UV.")); - error->popup_centered(); - return; - } - uv_edit_draw->set_texture_filter(node->get_texture_filter_in_tree()); Vector points = node->get_polygon(); @@ -1059,9 +1053,6 @@ void Polygon2DEditor::_uv_draw() { } Ref base_tex = node->get_texture(); - if (base_tex.is_null()) { - return; - } String warning; @@ -1071,12 +1062,14 @@ void Polygon2DEditor::_uv_draw() { // Draw texture as a background if editing uvs or no uv mapping exist. if (uv_edit_mode[0]->is_pressed() || uv_mode == UV_MODE_CREATE || node->get_polygon().is_empty() || node->get_uv().size() != node->get_polygon().size()) { - Transform2D texture_transform = Transform2D(node->get_texture_rotation(), node->get_texture_offset()); - texture_transform.scale(node->get_texture_scale()); - texture_transform.affine_invert(); - RS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), mtx * texture_transform); - uv_edit_draw->draw_texture(base_tex, Point2()); - RS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), Transform2D()); + if (base_tex.is_valid()) { + Transform2D texture_transform = Transform2D(node->get_texture_rotation(), node->get_texture_offset()); + texture_transform.scale(node->get_texture_scale()); + texture_transform.affine_invert(); + RS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), mtx * texture_transform); + uv_edit_draw->draw_texture(base_tex, Point2()); + RS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), Transform2D()); + } preview_polygon->hide(); } else { preview_polygon->set_transform(mtx); From 92b3e5fe8a0ad7d38d2f65e988fea4efc3f5253b Mon Sep 17 00:00:00 2001 From: Robert Yevdokimov <105675984+ryevdokimov@users.noreply.github.com> Date: Mon, 9 Sep 2024 11:37:37 -0700 Subject: [PATCH 015/237] Hide white circle outline during instant transformations --- editor/plugins/node_3d_editor_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 44673e7224c..9eea6df4305 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -3999,7 +3999,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() { xform.orthonormalize(); xform.basis.scale(scale); RenderingServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[3], xform); - RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[3], spatial_editor->is_gizmo_visible() && transform_gizmo_visible && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE)); + RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[3], spatial_editor->is_gizmo_visible() && !_edit.instant && transform_gizmo_visible && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE)); } void Node3DEditorViewport::set_state(const Dictionary &p_state) { From e4db0bca738e22c26f1a699f2edf4e780e32897c Mon Sep 17 00:00:00 2001 From: aXu-AP <1621768+aXu-AP@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:19:17 +0300 Subject: [PATCH 016/237] Make detach script non-destructive operation Fix detach script not returning script's property values on undo. --- editor/scene_tree_dock.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 2a39b118153..79a35183101 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -742,6 +742,14 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (existing != empty) { undo_redo->add_do_method(n, "set_script", empty); undo_redo->add_undo_method(n, "set_script", existing); + + List properties; + n->get_property_list(&properties); + for (const PropertyInfo &property : properties) { + if (property.usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR)) { + undo_redo->add_undo_property(n, property.name, n->get(property.name)); + } + } } } From df0a88b128cb24c1e0e445d5e859c4cffc4f50d2 Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Tue, 10 Sep 2024 13:48:53 -0500 Subject: [PATCH 017/237] SCons: Fix `clang-cl` link/ar flags --- platform/windows/detect.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 684a7c34a00..f5de6c637d8 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -620,18 +620,16 @@ def spawn_capture(sh, escape, cmd, args, env): print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.") sys.exit(255) - env.Append(CCFLAGS=["-flto=thin"]) - env.Append(LINKFLAGS=["-flto=thin"]) + env.AppendUnique(CCFLAGS=["-flto=thin"]) elif env["use_llvm"]: - env.Append(CCFLAGS=["-flto"]) - env.Append(LINKFLAGS=["-flto"]) + env.AppendUnique(CCFLAGS=["-flto"]) else: env.AppendUnique(CCFLAGS=["/GL"]) - env.AppendUnique(ARFLAGS=["/LTCG"]) - if env["progress"]: - env.AppendUnique(LINKFLAGS=["/LTCG:STATUS"]) - else: - env.AppendUnique(LINKFLAGS=["/LTCG"]) + if env["progress"]: + env.AppendUnique(LINKFLAGS=["/LTCG:STATUS"]) + else: + env.AppendUnique(LINKFLAGS=["/LTCG"]) + env.AppendUnique(ARFLAGS=["/LTCG"]) if vcvars_msvc_config: env.Prepend(CPPPATH=[p for p in str(os.getenv("INCLUDE")).split(";")]) From 3e93970ef5eb5013c4aff2eedf7b14e46f724a87 Mon Sep 17 00:00:00 2001 From: Malcolm Nixon Date: Tue, 10 Sep 2024 23:50:39 -0400 Subject: [PATCH 018/237] Expose the optimize method of the Animation class to gdscript. --- doc/classes/Animation.xml | 9 +++++++++ scene/resources/animation.cpp | 1 + 2 files changed, 10 insertions(+) diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml index 942299cc7e4..887e9cda819 100644 --- a/doc/classes/Animation.xml +++ b/doc/classes/Animation.xml @@ -293,6 +293,15 @@ Returns the arguments values to be called on a method track for a given key in a given track. + + + + + + + Optimize the animation and all its tracks in-place. This will preserve only as many keys as are necessary to keep the animation within the specified bounds. + + diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index a2ed6af23c3..31d195d948e 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -3902,6 +3902,7 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("clear"), &Animation::clear); ClassDB::bind_method(D_METHOD("copy_track", "track_idx", "to_animation"), &Animation::copy_track); + ClassDB::bind_method(D_METHOD("optimize", "allowed_velocity_err", "allowed_angular_err", "precision"), &Animation::optimize, DEFVAL(0.01), DEFVAL(0.01), DEFVAL(3)); ClassDB::bind_method(D_METHOD("compress", "page_size", "fps", "split_tolerance"), &Animation::compress, DEFVAL(8192), DEFVAL(120), DEFVAL(4.0)); ClassDB::bind_method(D_METHOD("is_capture_included"), &Animation::is_capture_included); From 02ab0627d698a76343ab80c7afdf3cb261ec80d4 Mon Sep 17 00:00:00 2001 From: Micky Date: Wed, 11 Sep 2024 18:05:19 +0200 Subject: [PATCH 019/237] Improve wording on XRPose's `name` description --- doc/classes/XRPose.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/classes/XRPose.xml b/doc/classes/XRPose.xml index 60a2226a604..76c1ced3527 100644 --- a/doc/classes/XRPose.xml +++ b/doc/classes/XRPose.xml @@ -29,11 +29,11 @@ The linear velocity of this pose. - The name of this pose. Pose names are often driven by an action map setup by the user. Godot does suggest a number of pose names that it expects [XRInterface]s to implement: - - [code]root[/code] defines a root location, often used for tracked objects that do not have further nodes. - - [code]aim[/code] defines the tip of a controller with the orientation pointing outwards, for example: add your raycasts to this. - - [code]grip[/code] defines the location where the user grips the controller - - [code]skeleton[/code] defines the root location a hand mesh should be placed when using hand tracking and the animated skeleton supplied by the XR runtime. + The name of this pose. Usually, this name is derived from an action map set up by the user. Godot also suggests some pose names that [XRInterface] objects are expected to implement: + - [code]root[/code] is the root location, often used for tracked objects that do not have further nodes. + - [code]aim[/code] is the tip of a controller with its orientation pointing outwards, often used for raycasts. + - [code]grip[/code] is the location where the user grips the controller. + - [code]skeleton[/code] is the root location for a hand mesh, when using hand tracking and an animated skeleton is supplied by the XR runtime. The tracking confidence for this pose, provides insight on how accurate the spatial positioning of this record is. From 7ff106f828da690c51f0a8cc89c04b15587a3a43 Mon Sep 17 00:00:00 2001 From: clayjohn Date: Thu, 23 May 2024 11:29:45 -0700 Subject: [PATCH 020/237] Use distance to AABB surface to calculate Mesh LOD instead of using supports --- drivers/gles3/rasterizer_scene_gles3.cpp | 41 +++++++------------ .../render_forward_clustered.cpp | 41 +++++++------------ .../forward_mobile/render_forward_mobile.cpp | 40 +++++++----------- 3 files changed, 42 insertions(+), 80 deletions(-) diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 8b6d3e3268e..39aad6bfbf0 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1363,38 +1363,25 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const GeometryInstanceSurface *surf = inst->surface_caches; + float lod_distance = 0.0; + + if (p_render_data->cam_orthogonal) { + lod_distance = 1.0; + } else { + Vector3 aabb_min = inst->transformed_aabb.position; + Vector3 aabb_max = inst->transformed_aabb.position + inst->transformed_aabb.size; + Vector3 camera_position = p_render_data->main_cam_transform.origin; + Vector3 surface_distance = Vector3(0.0, 0.0, 0.0).max(aabb_min - camera_position).max(camera_position - aabb_max); + + lod_distance = surface_distance.length(); + } + while (surf) { // LOD if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) { - float distance = 0.0; - - // Check if camera is NOT inside the mesh AABB. - if (!inst->transformed_aabb.has_point(p_render_data->main_cam_transform.origin)) { - // Get the LOD support points on the mesh AABB. - Vector3 lod_support_min = inst->transformed_aabb.get_support(p_render_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z)); - Vector3 lod_support_max = inst->transformed_aabb.get_support(-p_render_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z)); - - // Get the distances to those points on the AABB from the camera origin. - float distance_min = (float)p_render_data->main_cam_transform.origin.distance_to(lod_support_min); - float distance_max = (float)p_render_data->main_cam_transform.origin.distance_to(lod_support_max); - - if (distance_min * distance_max < 0.0) { - //crossing plane - distance = 0.0; - } else if (distance_min >= 0.0) { - distance = distance_min; - } else if (distance_max <= 0.0) { - distance = -distance_max; - } - } - - if (p_render_data->cam_orthogonal) { - distance = 1.0; - } - uint32_t indices = 0; - surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, indices); + surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, lod_distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, indices); surf->index_count = indices; if (p_render_data->render_info) { 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 36bd22b7234..aca85ce4972 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -962,40 +962,27 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con GeometryInstanceSurfaceDataCache *surf = inst->surface_caches; + float lod_distance = 0.0; + + if (p_render_data->scene_data->cam_orthogonal) { + lod_distance = 1.0; + } else { + Vector3 aabb_min = inst->transformed_aabb.position; + Vector3 aabb_max = inst->transformed_aabb.position + inst->transformed_aabb.size; + Vector3 camera_position = p_render_data->scene_data->main_cam_transform.origin; + Vector3 surface_distance = Vector3(0.0, 0.0, 0.0).max(aabb_min - camera_position).max(camera_position - aabb_max); + + lod_distance = surface_distance.length(); + } + while (surf) { surf->sort.uses_forward_gi = 0; surf->sort.uses_lightmap = 0; // LOD - if (p_render_data->scene_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) { - float distance = 0.0; - - // Check if camera is NOT inside the mesh AABB. - if (!inst->transformed_aabb.has_point(p_render_data->scene_data->main_cam_transform.origin)) { - // Get the LOD support points on the mesh AABB. - Vector3 lod_support_min = inst->transformed_aabb.get_support(p_render_data->scene_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z)); - Vector3 lod_support_max = inst->transformed_aabb.get_support(-p_render_data->scene_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z)); - - // Get the distances to those points on the AABB from the camera origin. - float distance_min = (float)p_render_data->scene_data->main_cam_transform.origin.distance_to(lod_support_min); - float distance_max = (float)p_render_data->scene_data->main_cam_transform.origin.distance_to(lod_support_max); - - if (distance_min * distance_max < 0.0) { - //crossing plane - distance = 0.0; - } else if (distance_min >= 0.0) { - distance = distance_min; - } else if (distance_max <= 0.0) { - distance = -distance_max; - } - } - if (p_render_data->scene_data->cam_orthogonal) { - distance = 1.0; - } - uint32_t indices = 0; - surf->sort.lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, indices); + surf->sort.lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, lod_distance * p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, indices); if (p_render_data->render_info) { indices = _indices_to_primitives(surf->primitive, indices); if (p_render_list == RENDER_LIST_OPAQUE) { //opaque 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 48c226133d3..8a02ec0eb56 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -1884,39 +1884,27 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const GeometryInstanceSurfaceDataCache *surf = inst->surface_caches; + float lod_distance = 0.0; + + if (p_render_data->scene_data->cam_orthogonal) { + lod_distance = 1.0; + } else { + Vector3 aabb_min = inst->transformed_aabb.position; + Vector3 aabb_max = inst->transformed_aabb.position + inst->transformed_aabb.size; + Vector3 camera_position = p_render_data->scene_data->main_cam_transform.origin; + Vector3 surface_distance = Vector3(0.0, 0.0, 0.0).max(aabb_min - camera_position).max(camera_position - aabb_max); + + lod_distance = surface_distance.length(); + } + while (surf) { surf->sort.uses_lightmap = 0; // LOD if (p_render_data->scene_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) { - float distance = 0.0; - - // Check if camera is NOT inside the mesh AABB. - if (!inst->transformed_aabb.has_point(p_render_data->scene_data->main_cam_transform.origin)) { - // Get the LOD support points on the mesh AABB. - Vector3 lod_support_min = inst->transformed_aabb.get_support(p_render_data->scene_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z)); - Vector3 lod_support_max = inst->transformed_aabb.get_support(-p_render_data->scene_data->main_cam_transform.basis.get_column(Vector3::AXIS_Z)); - - // Get the distances to those points on the AABB from the camera origin. - float distance_min = (float)p_render_data->scene_data->main_cam_transform.origin.distance_to(lod_support_min); - float distance_max = (float)p_render_data->scene_data->main_cam_transform.origin.distance_to(lod_support_max); - - if (distance_min * distance_max < 0.0) { - //crossing plane - distance = 0.0; - } else if (distance_min >= 0.0) { - distance = distance_min; - } else if (distance_max <= 0.0) { - distance = -distance_max; - } - } - if (p_render_data->scene_data->cam_orthogonal) { - distance = 1.0; - } - uint32_t indices = 0; - surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, indices); + surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, lod_distance * p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, indices); if (p_render_data->render_info) { indices = _indices_to_primitives(surf->primitive, indices); if (p_render_list == RENDER_LIST_OPAQUE) { //opaque From c2af6bcb5983356244d699735cda00b0bc5f4f8d Mon Sep 17 00:00:00 2001 From: David Snopek Date: Tue, 18 Jun 2024 10:07:35 -0500 Subject: [PATCH 021/237] GDExtension: Mark virtual function as `is_required` in `extension_api.json` Co-authored-by: Jovan Gerodetti --- core/extension/extension_api_dump.cpp | 1 + core/extension/make_wrappers.py | 4 +- core/object/make_virtuals.py | 30 +++- core/object/object.h | 8 +- core/object/script_language_extension.h | 132 +++++++-------- editor/editor_file_system.h | 12 +- editor/editor_script.cpp | 2 +- editor/editor_script.h | 2 +- editor/editor_vcs_interface.cpp | 46 ++--- editor/editor_vcs_interface.h | 46 ++--- .../editor_export_platform_extension.cpp | 18 +- .../export/editor_export_platform_extension.h | 18 +- editor/export/editor_export_plugin.cpp | 8 +- editor/export/editor_export_plugin.h | 8 +- scene/resources/material.cpp | 4 +- scene/resources/material.h | 4 +- scene/resources/mesh.cpp | 28 +-- scene/resources/mesh.h | 28 +-- scene/resources/style_box.cpp | 2 +- scene/resources/style_box.h | 2 +- scene/resources/texture.cpp | 30 ++-- scene/resources/texture.h | 30 ++-- scene/resources/video_stream.cpp | 2 +- scene/resources/video_stream.h | 2 +- servers/audio/audio_effect.cpp | 4 +- servers/audio/audio_effect.h | 4 +- servers/audio/audio_stream.cpp | 6 +- servers/audio/audio_stream.h | 6 +- .../extensions/physics_server_2d_extension.h | 44 ++--- .../extensions/physics_server_3d_extension.h | 44 ++--- servers/movie_writer/movie_writer.cpp | 14 +- servers/movie_writer/movie_writer.h | 14 +- servers/physics_server_3d.cpp | 6 +- servers/physics_server_3d.h | 6 +- servers/text/text_server_extension.cpp | 160 +++++++++--------- servers/text/text_server_extension.h | 160 +++++++++--------- 36 files changed, 473 insertions(+), 462 deletions(-) diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp index 296ebc901f8..affe0371ff6 100644 --- a/core/extension/extension_api_dump.cpp +++ b/core/extension/extension_api_dump.cpp @@ -1017,6 +1017,7 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) { d2["name"] = String(method_name); d2["is_const"] = (F.flags & METHOD_FLAG_CONST) ? true : false; d2["is_static"] = (F.flags & METHOD_FLAG_STATIC) ? true : false; + d2["is_required"] = (F.flags & METHOD_FLAG_VIRTUAL_REQUIRED) ? true : false; d2["is_vararg"] = false; d2["is_virtual"] = true; // virtual functions have no hash since no MethodBind is involved diff --git a/core/extension/make_wrappers.py b/core/extension/make_wrappers.py index 54f4fd5579d..665b6f0f91d 100644 --- a/core/extension/make_wrappers.py +++ b/core/extension/make_wrappers.py @@ -55,10 +55,10 @@ def generate_mod_version(argcount, const=False, returns=False): proto_ex = """ #define EXBIND$VER($RETTYPE m_name$ARG) \\ -GDVIRTUAL$VER($RETTYPE_##m_name$ARG)\\ +GDVIRTUAL$VER_REQUIRED($RETTYPE_##m_name$ARG)\\ virtual $RETVAL m_name($FUNCARGS) $CONST override { \\ $RETPRE\\ - GDVIRTUAL_REQUIRED_CALL(_##m_name$CALLARGS$RETREF);\\ + GDVIRTUAL_CALL(_##m_name$CALLARGS$RETREF);\\ $RETPOST\\ } """ diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py index 7a85753072e..3df26e3b73f 100644 --- a/core/object/make_virtuals.py +++ b/core/object/make_virtuals.py @@ -2,7 +2,6 @@ StringName _gdvirtual_##m_name##_sn = #m_name;\\ mutable bool _gdvirtual_##m_name##_initialized = false;\\ mutable void *_gdvirtual_##m_name = nullptr;\\ - template \\ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST {\\ ScriptInstance *_script_instance = ((Object *)(this))->get_script_instance();\\ if (_script_instance) {\\ @@ -36,10 +35,8 @@ }\\ return true;\\ }\\ - if (required) {\\ - ERR_PRINT_ONCE("Required virtual method " + get_class() + "::" + #m_name + " must be overridden before calling.");\\ - $RVOID\\ - }\\ + $REQCHECK\\ + $RVOID\\ return false;\\ }\\ _FORCE_INLINE_ bool _gdvirtual_##m_name##_overridden() const {\\ @@ -73,10 +70,11 @@ """ -def generate_version(argcount, const=False, returns=False): +def generate_version(argcount, const=False, returns=False, required=False): s = proto sproto = str(argcount) method_info = "" + method_flags = "METHOD_FLAG_VIRTUAL" if returns: sproto += "R" s = s.replace("$RET", "m_ret,") @@ -86,17 +84,27 @@ def generate_version(argcount, const=False, returns=False): method_info += "\t\tmethod_info.return_val_metadata = GetTypeInfo::METADATA;" else: s = s.replace("$RET ", "") - s = s.replace("\t\t\t$RVOID\\\n", "") + s = s.replace("\t\t$RVOID\\\n", "") s = s.replace("\t\t\t$CALLPTRRETDEF\\\n", "") if const: sproto += "C" + method_flags += " | METHOD_FLAG_CONST" s = s.replace("$CONST", "const") - s = s.replace("$METHOD_FLAGS", "METHOD_FLAG_VIRTUAL | METHOD_FLAG_CONST") else: s = s.replace("$CONST ", "") - s = s.replace("$METHOD_FLAGS", "METHOD_FLAG_VIRTUAL") + if required: + sproto += "_REQUIRED" + method_flags += " | METHOD_FLAG_VIRTUAL_REQUIRED" + s = s.replace( + "$REQCHECK", + 'ERR_PRINT_ONCE("Required virtual method " + get_class() + "::" + #m_name + " must be overridden before calling.");', + ) + else: + s = s.replace("\t\t$REQCHECK\\\n", "") + + s = s.replace("$METHOD_FLAGS", method_flags) s = s.replace("$VER", sproto) argtext = "" callargtext = "" @@ -198,6 +206,10 @@ def run(target, source, env): txt += generate_version(i, False, True) txt += generate_version(i, True, False) txt += generate_version(i, True, True) + txt += generate_version(i, False, False, True) + txt += generate_version(i, False, True, True) + txt += generate_version(i, True, False, True) + txt += generate_version(i, True, True, True) txt += "#endif // GDVIRTUAL_GEN_H\n" diff --git a/core/object/object.h b/core/object/object.h index 6d22f320afc..6a084d0b7ae 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -215,6 +215,7 @@ enum MethodFlags { METHOD_FLAG_VARARG = 16, METHOD_FLAG_STATIC = 32, METHOD_FLAG_OBJECT_CORE = 64, + METHOD_FLAG_VIRTUAL_REQUIRED = 128, METHOD_FLAGS_DEFAULT = METHOD_FLAG_NORMAL, }; @@ -368,11 +369,8 @@ struct ObjectGDExtension { #endif }; -#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call(__VA_ARGS__) -#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call(__VA_ARGS__) - -#define GDVIRTUAL_REQUIRED_CALL(m_name, ...) _gdvirtual_##m_name##_call(__VA_ARGS__) -#define GDVIRTUAL_REQUIRED_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call(__VA_ARGS__) +#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call(__VA_ARGS__) +#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call(__VA_ARGS__) #ifdef DEBUG_METHODS_ENABLED #define GDVIRTUAL_BIND(m_name, ...) ::ClassDB::add_virtual_method(get_class_static(), _gdvirtual_##m_name##_get_method_info(), true, sarray(__VA_ARGS__)); diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index c9344f5799b..7b4d564e0b1 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -57,16 +57,16 @@ class ScriptExtension : public Script { EXBIND1RC(bool, inherits_script, const Ref