From e1cb65bedf1f8e1cf4a9f7ba41660983f998fc2a Mon Sep 17 00:00:00 2001 From: Shatyuka Date: Fri, 3 May 2024 06:36:51 +0800 Subject: [PATCH 001/446] Apply `WS_MINIMIZE` style on window creation --- platform/windows/display_server_windows.cpp | 28 +++++++++++++++------ platform/windows/display_server_windows.h | 4 ++- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index f101d85d5832..33c4ef9dffc1 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -1339,6 +1339,7 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod rendering_device->screen_create(window_id); } #endif + wd.initialized = true; return window_id; } @@ -1895,7 +1896,7 @@ Size2i DisplayServerWindows::window_get_size_with_decorations(WindowID p_window) return Size2(); } -void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex) { +void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_initialized, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_minimized, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex) { // Windows docs for window styles: // https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles // https://docs.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles @@ -1904,12 +1905,16 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre r_style_ex = WS_EX_WINDOWEDGE; if (p_main_window) { r_style_ex |= WS_EX_APPWINDOW; - r_style |= WS_VISIBLE; + if (p_initialized) { + r_style |= WS_VISIBLE; + } } if (p_fullscreen || p_borderless) { r_style |= WS_POPUP; // p_borderless was WS_EX_TOOLWINDOW in the past. - if (p_maximized) { + if (p_minimized) { + r_style |= WS_MINIMIZE; + } else if (p_maximized) { r_style |= WS_MAXIMIZE; } if (!p_fullscreen) { @@ -1924,13 +1929,19 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre } } else { if (p_resizable) { - if (p_maximized) { + if (p_minimized) { + r_style = WS_OVERLAPPEDWINDOW | WS_MINIMIZE; + } else if (p_maximized) { r_style = WS_OVERLAPPEDWINDOW | WS_MAXIMIZE; } else { r_style = WS_OVERLAPPEDWINDOW; } } else { - r_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; + if (p_minimized) { + r_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MINIMIZE; + } else { + r_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; + } } } @@ -1938,7 +1949,7 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre r_style_ex |= WS_EX_TOPMOST | WS_EX_NOACTIVATE; } - if (!p_borderless && !p_no_activate_focus) { + if (!p_borderless && !p_no_activate_focus && p_initialized) { r_style |= WS_VISIBLE; } @@ -1955,7 +1966,7 @@ void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repain DWORD style = 0; DWORD style_ex = 0; - _get_window_style(p_window == MAIN_WINDOW_ID, wd.fullscreen, wd.multiwindow_fs, wd.borderless, wd.resizable, wd.maximized, wd.maximized_fs, wd.no_focus || wd.is_popup, style, style_ex); + _get_window_style(p_window == MAIN_WINDOW_ID, wd.initialized, wd.fullscreen, wd.multiwindow_fs, wd.borderless, wd.resizable, wd.minimized, wd.maximized, wd.maximized_fs, wd.no_focus || wd.is_popup, style, style_ex); SetWindowLongPtr(wd.hWnd, GWL_STYLE, style); SetWindowLongPtr(wd.hWnd, GWL_EXSTYLE, style_ex); @@ -5088,7 +5099,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, DWORD dwExStyle; DWORD dwStyle; - _get_window_style(window_id_counter == MAIN_WINDOW_ID, (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN), p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN, p_flags & WINDOW_FLAG_BORDERLESS_BIT, !(p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT), p_mode == WINDOW_MODE_MAXIMIZED, false, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) | (p_flags & WINDOW_FLAG_POPUP), dwStyle, dwExStyle); + _get_window_style(window_id_counter == MAIN_WINDOW_ID, false, (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN), p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN, p_flags & WINDOW_FLAG_BORDERLESS_BIT, !(p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT), p_mode == WINDOW_MODE_MINIMIZED, p_mode == WINDOW_MODE_MAXIMIZED, false, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) | (p_flags & WINDOW_FLAG_POPUP), dwStyle, dwExStyle); RECT WindowRect; @@ -5793,6 +5804,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win } } + windows[MAIN_WINDOW_ID].initialized = true; show_window(MAIN_WINDOW_ID); #if defined(RD_ENABLED) diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 80f6061348a4..b549e377407f 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -445,6 +445,8 @@ class DisplayServerWindows : public DisplayServer { bool is_popup = false; Rect2i parent_safe_rect; + + bool initialized = false; }; JoypadWindows *joypad = nullptr; @@ -472,7 +474,7 @@ class DisplayServerWindows : public DisplayServer { HashMap indicators; void _send_window_event(const WindowData &wd, WindowEvent p_event); - void _get_window_style(bool p_main_window, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex); + void _get_window_style(bool p_main_window, bool p_initialized, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_minimized, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex); MouseMode mouse_mode; int restore_mouse_trails = 0; From 14f6c816bac06580dc150b8dda111005131656fb Mon Sep 17 00:00:00 2001 From: Robert Yevdokimov Date: Sun, 18 Feb 2024 13:38:45 -0500 Subject: [PATCH 002/446] Offset drag instantiated scenes that result in a collision by its bounds to prevent overlap Co-Authored-By: Robbie Cooper --- editor/plugins/node_3d_editor_plugin.cpp | 56 +++++++++++++++++++----- editor/plugins/node_3d_editor_plugin.h | 2 +- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index d211bd858847..737f8e3f9812 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -4104,8 +4104,31 @@ Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const ray_params.to = world_pos + world_ray * camera->get_far(); PhysicsDirectSpaceState3D::RayResult result; - if (ss->intersect_ray(ray_params, result)) { - return result.position; + if (ss->intersect_ray(ray_params, result) && preview_node->get_child_count() > 0) { + // Calculate an offset for the `preview_node` such that the its bounding box is on top of and touching the contact surface's plane. + + // Use the Gram-Schmidt process to get an orthonormal Basis aligned with the surface normal. + const Vector3 bb_basis_x = result.normal; + Vector3 bb_basis_y = Vector3(0, 1, 0); + bb_basis_y = bb_basis_y - bb_basis_y.project(bb_basis_x); + if (bb_basis_y.is_zero_approx()) { + bb_basis_y = Vector3(0, 0, 1); + bb_basis_y = bb_basis_y - bb_basis_y.project(bb_basis_x); + } + bb_basis_y = bb_basis_y.normalized(); + const Vector3 bb_basis_z = bb_basis_x.cross(bb_basis_y); + const Basis bb_basis = Basis(bb_basis_x, bb_basis_y, bb_basis_z); + + // This normal-aligned Basis allows us to create an AABB that can fit on the surface plane as snugly as possible. + const Transform3D bb_transform = Transform3D(bb_basis, preview_node->get_transform().origin); + const AABB preview_node_bb = _calculate_spatial_bounds(preview_node, true, &bb_transform); + // The x-axis's alignment with the surface normal also makes it trivial to get the distance from `preview_node`'s origin at (0, 0, 0) to the correct AABB face. + const float offset_distance = -preview_node_bb.position.x; + + // `result_offset` is in global space. + const Vector3 result_offset = result.position + result.normal * offset_distance; + + return result_offset; } const bool is_orthogonal = camera->get_projection() == Camera3D::PROJECTION_ORTHOGONAL; @@ -4133,18 +4156,21 @@ Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const return world_pos + world_ray * FALLBACK_DISTANCE; } -AABB Node3DEditorViewport::_calculate_spatial_bounds(const Node3D *p_parent, const Node3D *p_top_level_parent) { +AABB Node3DEditorViewport::_calculate_spatial_bounds(const Node3D *p_parent, bool p_omit_top_level, const Transform3D *p_bounds_orientation) { AABB bounds; - if (!p_top_level_parent) { - p_top_level_parent = p_parent; + Transform3D bounds_orientation; + if (p_bounds_orientation) { + bounds_orientation = *p_bounds_orientation; + } else { + bounds_orientation = p_parent->get_global_transform(); } if (!p_parent) { return AABB(Vector3(-0.2, -0.2, -0.2), Vector3(0.4, 0.4, 0.4)); } - Transform3D xform_to_top_level_parent_space = p_top_level_parent->get_global_transform().affine_inverse() * p_parent->get_global_transform(); + const Transform3D xform_to_top_level_parent_space = bounds_orientation.affine_inverse() * p_parent->get_global_transform(); const VisualInstance3D *visual_instance = Object::cast_to(p_parent); if (visual_instance) { @@ -4155,9 +4181,9 @@ AABB Node3DEditorViewport::_calculate_spatial_bounds(const Node3D *p_parent, con bounds = xform_to_top_level_parent_space.xform(bounds); for (int i = 0; i < p_parent->get_child_count(); i++) { - Node3D *child = Object::cast_to(p_parent->get_child(i)); - if (child) { - AABB child_bounds = _calculate_spatial_bounds(child, p_top_level_parent); + const Node3D *child = Object::cast_to(p_parent->get_child(i)); + if (child && !(p_omit_top_level && child->is_set_as_top_level())) { + const AABB child_bounds = _calculate_spatial_bounds(child, p_omit_top_level, &bounds_orientation); bounds.merge_with(child_bounds); } } @@ -4208,6 +4234,10 @@ void Node3DEditorViewport::_create_preview_node(const Vector &files) con if (instance) { instance = _sanitize_preview_node(instance); preview_node->add_child(instance); + Node3D *node_3d = Object::cast_to(instance); + if (node_3d) { + node_3d->set_as_top_level(false); + } } add_preview = true; } @@ -4428,8 +4458,12 @@ bool Node3DEditorViewport::_create_instance(Node *p_parent, const String &p_path } Transform3D new_tf = node3d->get_transform(); - new_tf.origin = parent_tf.affine_inverse().xform(preview_node_pos + node3d->get_position()); - new_tf.basis = parent_tf.affine_inverse().basis * new_tf.basis; + if (node3d->is_set_as_top_level()) { + new_tf.origin += preview_node_pos; + } else { + new_tf.origin = parent_tf.affine_inverse().xform(preview_node_pos + node3d->get_position()); + new_tf.basis = parent_tf.affine_inverse().basis * new_tf.basis; + } undo_redo->add_do_method(instantiated_scene, "set_transform", new_tf); } diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index ebdf95177301..8b7e29709ec9 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -435,7 +435,7 @@ class Node3DEditorViewport : public Control { Point2 _get_warped_mouse_motion(const Ref &p_ev_mouse_motion) const; Vector3 _get_instance_position(const Point2 &p_pos) const; - static AABB _calculate_spatial_bounds(const Node3D *p_parent, const Node3D *p_top_level_parent = nullptr); + static AABB _calculate_spatial_bounds(const Node3D *p_parent, bool p_omit_top_level = false, const Transform3D *p_bounds_orientation = nullptr); Node *_sanitize_preview_node(Node *p_node) const; From beef0f687c053624f057f79a14878926b77e7e8f Mon Sep 17 00:00:00 2001 From: Chris Cranford Date: Sat, 8 Jun 2024 16:45:49 -0400 Subject: [PATCH 003/446] Expose `update_docs_from_script` method --- doc/classes/ScriptEditor.xml | 8 ++++++++ editor/plugins/script_editor_plugin.cpp | 1 + 2 files changed, 9 insertions(+) diff --git a/doc/classes/ScriptEditor.xml b/doc/classes/ScriptEditor.xml index 43ee4dda6052..c205b2b8f302 100644 --- a/doc/classes/ScriptEditor.xml +++ b/doc/classes/ScriptEditor.xml @@ -94,6 +94,14 @@ [b]Note:[/b] The [EditorSyntaxHighlighter] will still be applied to scripts that are already opened. + + + + + Updates the documentation for the given [param script] if the script's documentation is currently open. + [b]Note:[/b] This should be called whenever the script is changed to keep the open documentation state up to date. + + diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 334b253316a6..7bf72d70a72f 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -3980,6 +3980,7 @@ void ScriptEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("open_script_create_dialog", "base_name", "base_path"), &ScriptEditor::open_script_create_dialog); ClassDB::bind_method(D_METHOD("goto_help", "topic"), &ScriptEditor::goto_help); + ClassDB::bind_method(D_METHOD("update_docs_from_script", "script"), &ScriptEditor::update_docs_from_script); ADD_SIGNAL(MethodInfo("editor_script_changed", PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script"))); ADD_SIGNAL(MethodInfo("script_close", PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script"))); From 5122a3e3b00e154c0148bb2709671e6c3a0b0432 Mon Sep 17 00:00:00 2001 From: David Nikdel Date: Mon, 10 Jun 2024 08:34:25 -0400 Subject: [PATCH 004/446] 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 3adff84e40bd..cdaa001d9e8d 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 005/446] 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 a1e392cd7dd0..6f9d89ff65c5 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 cd95d5fb9511..ef0ef5b3892e 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 1c22ecd673e9..ad3fa45a014d 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 3fbff3ef1940..266e3c7975ed 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 2d493e85a93ada822e4b61f5f001775c67e076fd Mon Sep 17 00:00:00 2001 From: alpacat Date: Sun, 30 Jun 2024 19:48:35 +0800 Subject: [PATCH 006/446] Fix `get_property_list` get wrong order of properties --- modules/mono/csharp_script.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 36c8a40ed9a6..a917180da329 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -1515,9 +1515,10 @@ void CSharpInstance::get_property_list(List *p_properties) const { } } + props.reverse(); for (PropertyInfo &prop : props) { validate_property(prop); - p_properties->push_back(prop); + p_properties->push_front(prop); } } From ee9cea521d97088eb368cb1820db71100da9837b Mon Sep 17 00:00:00 2001 From: Haoyu Qiu Date: Tue, 2 Jul 2024 17:12:21 +0800 Subject: [PATCH 007/446] Fix parsing of `4.` in Expression --- core/math/expression.cpp | 10 ++---- tests/core/math/test_expression.h | 53 +++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 636c2c16bf36..0692ece1e6fa 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -30,12 +30,7 @@ #include "expression.h" -#include "core/io/marshalls.h" -#include "core/math/math_funcs.h" #include "core/object/class_db.h" -#include "core/object/ref_counted.h" -#include "core/os/os.h" -#include "core/variant/variant_parser.h" Error Expression::_get_token(Token &r_token) { while (true) { @@ -392,7 +387,6 @@ Error Expression::_get_token(Token &r_token) { if (is_digit(c)) { } else if (c == 'e') { reading = READING_EXP; - } else { reading = READING_DONE; } @@ -419,7 +413,9 @@ Error Expression::_get_token(Token &r_token) { is_first_char = false; } - str_ofs--; + if (c != 0) { + str_ofs--; + } r_token.type = TK_CONSTANT; diff --git a/tests/core/math/test_expression.h b/tests/core/math/test_expression.h index 512d7932f9a4..c3e42804919c 100644 --- a/tests/core/math/test_expression.h +++ b/tests/core/math/test_expression.h @@ -122,6 +122,59 @@ TEST_CASE("[Expression] Floating-point arithmetic") { "Float multiplication-addition-subtraction-division should return the expected result."); } +TEST_CASE("[Expression] Floating-point notation") { + Expression expression; + + CHECK_MESSAGE( + expression.parse("2.") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + double(expression.execute()) == doctest::Approx(2.0), + "The expression should return the expected result."); + + CHECK_MESSAGE( + expression.parse("(2.)") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + double(expression.execute()) == doctest::Approx(2.0), + "The expression should return the expected result."); + + CHECK_MESSAGE( + expression.parse(".3") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + double(expression.execute()) == doctest::Approx(0.3), + "The expression should return the expected result."); + + CHECK_MESSAGE( + expression.parse("2.+5.") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + double(expression.execute()) == doctest::Approx(7.0), + "The expression should return the expected result."); + + CHECK_MESSAGE( + expression.parse(".3-.8") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + double(expression.execute()) == doctest::Approx(-0.5), + "The expression should return the expected result."); + + CHECK_MESSAGE( + expression.parse("2.+.2") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + double(expression.execute()) == doctest::Approx(2.2), + "The expression should return the expected result."); + + CHECK_MESSAGE( + expression.parse(".0*0.") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + double(expression.execute()) == doctest::Approx(0.0), + "The expression should return the expected result."); +} + TEST_CASE("[Expression] Scientific notation") { Expression expression; From 9a84387017fe7921954107d16a69a54ff54556f6 Mon Sep 17 00:00:00 2001 From: HolonProduction Date: Wed, 22 May 2024 18:54:43 +0200 Subject: [PATCH 008/446] Autocompletion: Keep get_node values which are compatible with type hint --- modules/gdscript/gdscript_editor.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index b58b44973e8c..12a8f5ba3306 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -2971,11 +2971,6 @@ static bool _get_subscript_type(GDScriptParser::CompletionContext &p_context, co } break; case GDScriptParser::Node::IDENTIFIER: { - if (p_subscript->base->datatype.type_source == GDScriptParser::DataType::ANNOTATED_EXPLICIT) { - // Annotated type takes precedence. - return false; - } - const GDScriptParser::IdentifierNode *identifier_node = static_cast(p_subscript->base); switch (identifier_node->source) { @@ -3013,6 +3008,14 @@ static bool _get_subscript_type(GDScriptParser::CompletionContext &p_context, co if (get_node != nullptr) { const Object *node = p_context.base->call("get_node_or_null", NodePath(get_node->full_path)); if (node != nullptr) { + GDScriptParser::DataType assigned_type = _type_from_variant(node, p_context).type; + GDScriptParser::DataType base_type = p_subscript->base->datatype; + + if (p_subscript->base->type == GDScriptParser::Node::IDENTIFIER && base_type.type_source == GDScriptParser::DataType::ANNOTATED_EXPLICIT && (assigned_type.kind != base_type.kind || assigned_type.script_path != base_type.script_path || assigned_type.native_type != base_type.native_type)) { + // Annotated type takes precedence. + return false; + } + if (r_base != nullptr) { *r_base = node; } From 0235086c14bcf840ce11de4233306933e44704c1 Mon Sep 17 00:00:00 2001 From: Silc 'Tokage' Renew <61938263+TokageItLab@users.noreply.github.com> Date: Fri, 26 Jul 2024 17:04:56 +0900 Subject: [PATCH 009/446] Add validation to glTF importer for Blendshape and Animation --- modules/fbx/fbx_document.cpp | 8 +------- modules/gltf/gltf_document.cpp | 8 +------- scene/resources/3d/importer_mesh.cpp | 12 +++++++++++- scene/resources/3d/importer_mesh.h | 2 ++ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/modules/fbx/fbx_document.cpp b/modules/fbx/fbx_document.cpp index b9d9ec7b6cf2..b5ea6302df7a 100644 --- a/modules/fbx/fbx_document.cpp +++ b/modules/fbx/fbx_document.cpp @@ -288,14 +288,8 @@ String FBXDocument::_gen_unique_name(HashSet &unique_names, const String } String FBXDocument::_sanitize_animation_name(const String &p_name) { - // Animations disallow the normal node invalid characters as well as "," and "[" - // (See animation/animation_player.cpp::add_animation) - - // TODO: Consider adding invalid_characters or a validate_animation_name to animation_player to mirror Node. String anim_name = p_name.validate_node_name(); - anim_name = anim_name.replace(",", ""); - anim_name = anim_name.replace("[", ""); - return anim_name; + return AnimationLibrary::validate_library_name(anim_name); } String FBXDocument::_gen_unique_animation_name(Ref p_state, const String &p_name) { diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index dff1e62e824b..4e091736efe6 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -472,14 +472,8 @@ String GLTFDocument::_gen_unique_name(Ref p_state, const String &p_na } String GLTFDocument::_sanitize_animation_name(const String &p_name) { - // Animations disallow the normal node invalid characters as well as "," and "[" - // (See animation/animation_player.cpp::add_animation) - - // TODO: Consider adding invalid_characters or a validate_animation_name to animation_player to mirror Node. String anim_name = p_name.validate_node_name(); - anim_name = anim_name.replace(",", ""); - anim_name = anim_name.replace("[", ""); - return anim_name; + return AnimationLibrary::validate_library_name(anim_name); } String GLTFDocument::_gen_unique_animation_name(Ref p_state, const String &p_name) { diff --git a/scene/resources/3d/importer_mesh.cpp b/scene/resources/3d/importer_mesh.cpp index f912d2650daf..ff3fe78a3779 100644 --- a/scene/resources/3d/importer_mesh.cpp +++ b/scene/resources/3d/importer_mesh.cpp @@ -34,6 +34,7 @@ #include "core/math/convex_hull.h" #include "core/math/random_pcg.h" #include "core/math/static_raycaster.h" +#include "scene/resources/animation_library.h" #include "scene/resources/surface_tool.h" #include @@ -134,9 +135,18 @@ void ImporterMesh::Surface::_split_normals(Array &r_arrays, const LocalVector 0); - blend_shapes.push_back(p_name); + blend_shapes.push_back(validate_blend_shape_name(p_name)); } int ImporterMesh::get_blend_shape_count() const { diff --git a/scene/resources/3d/importer_mesh.h b/scene/resources/3d/importer_mesh.h index ff8683449b59..60dac1269d1f 100644 --- a/scene/resources/3d/importer_mesh.h +++ b/scene/resources/3d/importer_mesh.h @@ -93,6 +93,8 @@ class ImporterMesh : public Resource { int get_blend_shape_count() const; String get_blend_shape_name(int p_blend_shape) const; + static String validate_blend_shape_name(const String &p_name); + void add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const TypedArray &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), const Ref &p_material = Ref(), const String &p_name = String(), const uint64_t p_flags = 0); int get_surface_count() const; From 28c60a5ff90533bf13e89373336c36f7016c38cc Mon Sep 17 00:00:00 2001 From: Alvin Wong Date: Sun, 28 Jul 2024 00:29:52 +0800 Subject: [PATCH 010/446] 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 133711a9eafe..1d7836add1ff 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 9025f53f42b2..a366827e11e1 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 2470eedd614c7a902c8ff0d6d013da014f4267bb Mon Sep 17 00:00:00 2001 From: kobewi Date: Sun, 28 Jul 2024 20:31:36 +0200 Subject: [PATCH 011/446] Call restart_editor() in RUN_PROJECT_MANAGER --- editor/editor_node.cpp | 33 ++++++++++----------------------- editor/editor_node.h | 2 +- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 8b6d316dd16f..7a9a265ffc40 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1961,7 +1961,7 @@ void EditorNode::try_autosave() { editor_data.save_editor_external_data(); } -void EditorNode::restart_editor() { +void EditorNode::restart_editor(bool p_goto_project_manager) { exiting = true; if (project_run_bar->is_playing()) { @@ -1969,22 +1969,25 @@ void EditorNode::restart_editor() { } String to_reopen; - if (get_tree()->get_edited_scene_root()) { + if (!p_goto_project_manager && get_tree()->get_edited_scene_root()) { to_reopen = get_tree()->get_edited_scene_root()->get_scene_file_path(); } _exit_editor(EXIT_SUCCESS); List args; - for (const String &a : Main::get_forwardable_cli_arguments(Main::CLI_SCOPE_TOOL)) { args.push_back(a); } - args.push_back("--path"); - args.push_back(ProjectSettings::get_singleton()->get_resource_path()); + if (p_goto_project_manager) { + args.push_back("--project-manager"); + } else { + args.push_back("--path"); + args.push_back(ProjectSettings::get_singleton()->get_resource_path()); - args.push_back("-e"); + args.push_back("-e"); + } if (!to_reopen.is_empty()) { args.push_back(to_reopen); @@ -3391,23 +3394,7 @@ void EditorNode::_discard_changes(const String &p_str) { } break; case RUN_PROJECT_MANAGER: { - project_run_bar->stop_playing(); - _exit_editor(EXIT_SUCCESS); - String exec = OS::get_singleton()->get_executable_path(); - - List args; - for (const String &a : Main::get_forwardable_cli_arguments(Main::CLI_SCOPE_TOOL)) { - args.push_back(a); - } - - String exec_base_dir = exec.get_base_dir(); - if (!exec_base_dir.is_empty()) { - args.push_back("--path"); - args.push_back(exec_base_dir); - } - args.push_back("--project-manager"); - - OS::get_singleton()->set_restart_on_exit(true, args); + restart_editor(true); } break; case RELOAD_CURRENT_PROJECT: { restart_editor(); diff --git a/editor/editor_node.h b/editor/editor_node.h index 4d55eaf1b2ab..10e4447bdce0 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -917,7 +917,7 @@ class EditorNode : public Node { void save_scene_list(const HashSet &p_scene_paths); void save_before_run(); void try_autosave(); - void restart_editor(); + void restart_editor(bool p_goto_project_manager = false); void unload_editor_addons(); void dim_editor(bool p_dimming); From f3841d644eec2366df6d30d7ce6b942504fb2a97 Mon Sep 17 00:00:00 2001 From: Raul Santos Date: Tue, 30 Jul 2024 18:19:42 +0200 Subject: [PATCH 012/446] 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 9a76a256395b..6bd99a8f22fd 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 e2c03469fb944d5d2489acc14714104ad3166bce Mon Sep 17 00:00:00 2001 From: kobewi Date: Thu, 1 Aug 2024 20:30:16 +0200 Subject: [PATCH 013/446] Close expanded tile editor when inspector updates --- editor/plugins/tiles/tile_data_editors.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index f985bbc62907..c97cd8013628 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -859,6 +859,11 @@ void GenericTilePolygonEditor::_notification(int p_what) { button_expand->set_pressed_no_signal(false); } } break; + + case NOTIFICATION_READY: { + get_parent()->connect(SceneStringName(tree_exited), callable_mp(TileSetEditor::get_singleton(), &TileSetEditor::remove_expanded_editor)); + } break; + case NOTIFICATION_THEME_CHANGED: { button_expand->set_icon(get_editor_theme_icon(SNAME("DistractionFree"))); button_create->set_icon(get_editor_theme_icon(SNAME("CurveCreate"))); From 48a54cb62f51cfb57a0b281d39477ba6d710cd85 Mon Sep 17 00:00:00 2001 From: Leon Stansfield Date: Sun, 4 Aug 2024 15:33:31 +0100 Subject: [PATCH 014/446] Adjusted listings of parameters displayed in inspector to be consistent accross all particle types --- scene/2d/cpu_particles_2d.cpp | 2 +- scene/2d/gpu_particles_2d.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 9c9ba93b410d..754afb05274a 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -1288,7 +1288,7 @@ void CPUParticles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); ADD_GROUP("Time", ""); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,suffix:s"), "set_lifetime", "get_lifetime"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,exp,suffix:s"), "set_lifetime", "get_lifetime"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01,suffix:s"), "set_pre_process_time", "get_pre_process_time"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale"); diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index 1d3f1ceadaff..3f9e9c8af428 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -816,19 +816,17 @@ void GPUParticles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "amount_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001"), "set_amount_ratio", "get_amount_ratio"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles2D"), "set_sub_emitter", "get_sub_emitter"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ParticleProcessMaterial,ShaderMaterial"), "set_process_material", "get_process_material"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture"); ADD_GROUP("Time", ""); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,suffix:s"), "set_lifetime", "get_lifetime"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater,exp,suffix:s"), "set_lifetime", "get_lifetime"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "interp_to_end", PROPERTY_HINT_RANGE, "0.00,1.0,0.001"), "set_interp_to_end", "get_interp_to_end"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01,suffix:s"), "set_pre_process_time", "get_pre_process_time"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01,exp,suffix:s"), "set_pre_process_time", "get_pre_process_time"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio"); ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1,suffix:FPS"), "set_fixed_fps", "get_fixed_fps"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interpolate"), "set_interpolate", "get_interpolate"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "interp_to_end", PROPERTY_HINT_RANGE, "0.00,1.0,0.001"), "set_interp_to_end", "get_interp_to_end"); ADD_GROUP("Collision", "collision_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_base_size", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_collision_base_size", "get_collision_base_size"); ADD_GROUP("Drawing", ""); @@ -840,7 +838,9 @@ void GPUParticles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_lifetime", PROPERTY_HINT_RANGE, "0.01,10,0.01,or_greater,suffix:s"), "set_trail_lifetime", "get_trail_lifetime"); ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_sections", PROPERTY_HINT_RANGE, "2,128,1"), "set_trail_sections", "get_trail_sections"); ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_section_subdivisions", PROPERTY_HINT_RANGE, "1,1024,1"), "set_trail_section_subdivisions", "get_trail_section_subdivisions"); - + ADD_GROUP("Process Material", ""); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ParticleProcessMaterial,ShaderMaterial"), "set_process_material", "get_process_material"); BIND_ENUM_CONSTANT(DRAW_ORDER_INDEX); BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME); BIND_ENUM_CONSTANT(DRAW_ORDER_REVERSE_LIFETIME); @@ -874,7 +874,7 @@ GPUParticles2D::GPUParticles2D() { set_randomness_ratio(0); set_visibility_rect(Rect2(Vector2(-100, -100), Vector2(200, 200))); set_use_local_coordinates(false); - set_draw_order(DRAW_ORDER_LIFETIME); + set_draw_order(DRAW_ORDER_INDEX); set_speed_scale(1); set_fixed_fps(30); set_collision_base_size(collision_base_size); From 4aead96306c07b77c2ef28ee67a3e3c1b811d242 Mon Sep 17 00:00:00 2001 From: Leon Stansfield Date: Sun, 4 Aug 2024 15:45:48 +0100 Subject: [PATCH 015/446] Revent DRAW_ORDER_INDEX to DRAW_ORDER_LIFETIME default particle params for compatibility. --- scene/2d/gpu_particles_2d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index 3f9e9c8af428..3a63af0ab502 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -874,7 +874,7 @@ GPUParticles2D::GPUParticles2D() { set_randomness_ratio(0); set_visibility_rect(Rect2(Vector2(-100, -100), Vector2(200, 200))); set_use_local_coordinates(false); - set_draw_order(DRAW_ORDER_INDEX); + set_draw_order(DRAW_ORDER_LIFETIME); set_speed_scale(1); set_fixed_fps(30); set_collision_base_size(collision_base_size); From 5cf9afb0c0409c1115c5b090371c6c81379315d9 Mon Sep 17 00:00:00 2001 From: kobewi Date: Sun, 4 Aug 2024 22:31:10 +0200 Subject: [PATCH 016/446] Don't fold resources when child of main inspector exits --- editor/editor_properties.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index fdb4ec170b8d..f00f5602cce3 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -3417,7 +3417,8 @@ void EditorPropertyResource::_notification(int p_what) { switch (p_what) { case NOTIFICATION_EXIT_TREE: { const EditorInspector *ei = get_parent_inspector(); - if (ei && !ei->is_main_editor_inspector()) { + const EditorInspector *main_ei = InspectorDock::get_inspector_singleton(); + if (ei && main_ei && ei != main_ei && !main_ei->is_ancestor_of(ei)) { fold_resource(); } } break; From 6e5175592de2b8756062752b0a73d724ae496ca1 Mon Sep 17 00:00:00 2001 From: aaronp64 Date: Thu, 8 Aug 2024 13:16:42 -0400 Subject: [PATCH 017/446] Improve ClassDB::_is_parent_class performance Change ClassDB::_is_parent_class to use ClassInfo::inherits_ptr, instead of looking up each inherited class name. --- core/object/class_db.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index ceeb04b8eae3..7abf23aaeba3 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -227,16 +227,12 @@ class PlaceholderExtensionInstance { #endif bool ClassDB::_is_parent_class(const StringName &p_class, const StringName &p_inherits) { - if (!classes.has(p_class)) { - return false; - } - - StringName inherits = p_class; - while (inherits.operator String().length()) { - if (inherits == p_inherits) { + ClassInfo *c = classes.getptr(p_class); + while (c) { + if (c->name == p_inherits) { return true; } - inherits = _get_parent_class(inherits); + c = c->inherits_ptr; } return false; 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 018/446] 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 72b540496d09..1804d73a696b 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 b67eb68e5bee8c5bcf3d3589be06ab569f7e3e8b Mon Sep 17 00:00:00 2001 From: kobewi Date: Thu, 15 Aug 2024 08:17:40 +0200 Subject: [PATCH 019/446] Misc code cleanup in EditorFileDialog --- editor/gui/editor_file_dialog.cpp | 44 +++++++++++++++++-------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/editor/gui/editor_file_dialog.cpp b/editor/gui/editor_file_dialog.cpp index afc6d58d6314..21eb60255fde 100644 --- a/editor/gui/editor_file_dialog.cpp +++ b/editor/gui/editor_file_dialog.cpp @@ -1522,7 +1522,7 @@ void EditorFileDialog::_favorite_move_down() { } void EditorFileDialog::_update_favorites() { - bool res = (access == ACCESS_RESOURCES); + bool access_resources = (access == ACCESS_RESOURCES); String current = get_current_dir(); favorites->clear(); @@ -1538,8 +1538,11 @@ void EditorFileDialog::_update_favorites() { for (int i = 0; i < favorited.size(); i++) { String name = favorited[i]; - bool cres = name.begins_with("res://"); - if (cres != res || !name.ends_with("/")) { + if (access_resources != name.begins_with("res://")) { + continue; + } + + if (!name.ends_with("/")) { continue; } @@ -1551,7 +1554,7 @@ void EditorFileDialog::_update_favorites() { } // Compute favorite display text. - if (res && name == "res://") { + if (access_resources && name == "res://") { if (name == current) { current_favorite = favorited_paths.size(); } @@ -1562,7 +1565,7 @@ void EditorFileDialog::_update_favorites() { if (name == current || name == current + "/") { current_favorite = favorited_paths.size(); } - name = name.substr(0, name.length() - 1); + name = name.trim_suffix("/"); name = name.get_file(); favorited_paths.append(favorited[i]); favorited_names.append(name); @@ -1589,7 +1592,7 @@ void EditorFileDialog::_update_favorites() { } void EditorFileDialog::_favorite_pressed() { - bool res = (access == ACCESS_RESOURCES); + bool access_resources = (access == ACCESS_RESOURCES); String cd = get_current_dir(); if (!cd.ends_with("/")) { @@ -1599,13 +1602,12 @@ void EditorFileDialog::_favorite_pressed() { Vector favorited = EditorSettings::get_singleton()->get_favorites(); bool found = false; - for (int i = 0; i < favorited.size(); i++) { - bool cres = favorited[i].begins_with("res://"); - if (cres != res) { + for (const String &name : favorited) { + if (access_resources != name.begins_with("res://")) { continue; } - if (favorited[i] == cd) { + if (name == cd) { found = true; break; } @@ -1625,31 +1627,30 @@ void EditorFileDialog::_favorite_pressed() { void EditorFileDialog::_update_recent() { recent->clear(); - bool res = (access == ACCESS_RESOURCES); + bool access_resources = (access == ACCESS_RESOURCES); Vector recentd = EditorSettings::get_singleton()->get_recent_dirs(); Vector recentd_paths; Vector recentd_names; + bool modified = false; for (int i = 0; i < recentd.size(); i++) { - bool cres = recentd[i].begins_with("res://"); - if (cres != res) { + String name = recentd[i]; + if (access_resources != name.begins_with("res://")) { continue; } - if (!dir_access->dir_exists(recentd[i])) { + if (!dir_access->dir_exists(name)) { // Remove invalid directory from the list of Recent directories. recentd.remove_at(i--); + modified = true; continue; } // Compute recent directory display text. - String name = recentd[i]; - if (res && name == "res://") { + if (access_resources && name == "res://") { name = "/"; } else { - if (name.ends_with("/")) { - name = name.substr(0, name.length() - 1); - } + name = name.trim_suffix("/"); name = name.get_file(); } recentd_paths.append(recentd[i]); @@ -1663,7 +1664,10 @@ void EditorFileDialog::_update_recent() { recent->set_item_metadata(-1, recentd_paths[i]); recent->set_item_icon_modulate(-1, get_dir_icon_color(recentd_paths[i])); } - EditorSettings::get_singleton()->set_recent_dirs(recentd); + + if (modified) { + EditorSettings::get_singleton()->set_recent_dirs(recentd); + } } void EditorFileDialog::_recent_selected(int p_idx) { From abe8d2c7195c70ae2a4d37e0049f15d78ed649a8 Mon Sep 17 00:00:00 2001 From: tetrapod00 <145553014+tetrapod00@users.noreply.github.com> Date: Sun, 18 Aug 2024 14:07:12 -0700 Subject: [PATCH 020/446] Document conversion function needed for normal texture in CompositorEffect --- doc/classes/CompositorEffect.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/classes/CompositorEffect.xml b/doc/classes/CompositorEffect.xml index 76a388791880..9ac54edb11b7 100644 --- a/doc/classes/CompositorEffect.xml +++ b/doc/classes/CompositorEffect.xml @@ -57,6 +57,17 @@ var render_scene_buffers : RenderSceneBuffersRD = render_data.get_render_scene_buffers() var roughness_buffer = render_scene_buffers.get_texture("forward_clustered", "normal_roughness") [/codeblock] + The raw normal and roughness buffer is stored in an optimized format, different than the one available in Spatial shaders. When sampling the buffer, a conversion function must be applied. Use this function, copied from [url=https://github.com/godotengine/godot/blob/da5f39889f155658cef7f7ec3cc1abb94e17d815/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl#L334-L341]here[/url]: + [codeblock] + vec4 normal_roughness_compatibility(vec4 p_normal_roughness) { + float roughness = p_normal_roughness.w; + if (roughness > 0.5) { + roughness = 1.0 - roughness; + } + roughness /= (127.0 / 255.0); + return vec4(normalize(p_normal_roughness.xyz * 2.0 - 1.0) * 0.5 + 0.5, roughness); + } + [/codeblock] If [code]true[/code] this triggers specular data being rendered to a separate buffer and combined after effects have been applied, only applicable for the Forward+ renderer. From 42e5c5b41c6a60fe1c21e0edd2e1c9b70dd87e57 Mon Sep 17 00:00:00 2001 From: kobewi Date: Wed, 21 Aug 2024 10:44:45 +0200 Subject: [PATCH 021/446] Allow horizontal scrolling in Tree using Shift --- scene/gui/tree.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 46fcdcf7f6c2..55ce7904f355 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -3957,25 +3957,25 @@ void Tree::gui_input(const Ref &p_event) { } break; case MouseButton::WHEEL_UP: { - if (_scroll(false, -mb->get_factor() / 8)) { + if (_scroll(mb->is_shift_pressed(), -mb->get_factor() / 8)) { accept_event(); } } break; case MouseButton::WHEEL_DOWN: { - if (_scroll(false, mb->get_factor() / 8)) { + if (_scroll(mb->is_shift_pressed(), mb->get_factor() / 8)) { accept_event(); } } break; case MouseButton::WHEEL_LEFT: { - if (_scroll(true, -mb->get_factor() / 8)) { + if (_scroll(!mb->is_shift_pressed(), -mb->get_factor() / 8)) { accept_event(); } } break; case MouseButton::WHEEL_RIGHT: { - if (_scroll(true, mb->get_factor() / 8)) { + if (_scroll(!mb->is_shift_pressed(), mb->get_factor() / 8)) { accept_event(); } From 94b31c1db7176d7e37ec836747e50a7d89a06c65 Mon Sep 17 00:00:00 2001 From: wareya Date: Wed, 18 Oct 2023 00:53:11 -0400 Subject: [PATCH 022/446] Optimize cubic hermite algorithm in AudioStreamPlaybackResampled --- servers/audio/audio_stream.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index e2c86869116f..ece088a694b9 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -173,12 +173,12 @@ int AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, } float mu2 = mu * mu; - AudioFrame a0 = 3 * y1 - 3 * y2 + y3 - y0; - AudioFrame a1 = 2 * y0 - 5 * y1 + 4 * y2 - y3; - AudioFrame a2 = y2 - y0; - AudioFrame a3 = 2 * y1; + float h11 = mu2 * (mu - 1); + float z = mu2 - h11; + float h01 = z - h11; + float h10 = mu - z; - p_buffer[i] = (a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3) / 2; + p_buffer[i] = y1 + (y2 - y1) * h01 + ((y2 - y0) * h10 + (y3 - y1) * h11) * 0.5; mix_offset += mix_increment; From 030fd71da23dc8e2c73febb966e4d6caf4f9ddbb Mon Sep 17 00:00:00 2001 From: Jeronimo Schreyer Date: Sun, 10 Dec 2023 18:26:14 -0300 Subject: [PATCH 023/446] add support for visualizing bones in Advanced Import Settings When an imported model Skeleton3D type node is selected, the bones are drawn using lines or octahedrons to provide a clearer reference to their position. Refactored Skeleton3DGizmoPlugin::redraw now uses a static function to generate bone meshes --- editor/import/3d/scene_import_settings.cpp | 23 +++++++- editor/import/3d/scene_import_settings.h | 2 + editor/plugins/skeleton_3d_editor_plugin.cpp | 61 ++++++++++++-------- editor/plugins/skeleton_3d_editor_plugin.h | 11 +++- 4 files changed, 68 insertions(+), 29 deletions(-) diff --git a/editor/import/3d/scene_import_settings.cpp b/editor/import/3d/scene_import_settings.cpp index 7cd5279b6351..955eb8a8dcee 100644 --- a/editor/import/3d/scene_import_settings.cpp +++ b/editor/import/3d/scene_import_settings.cpp @@ -37,6 +37,7 @@ #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_file_dialog.h" +#include "editor/plugins/skeleton_3d_editor_plugin.h" #include "editor/themes/editor_scale.h" #include "scene/3d/importer_mesh_instance_3d.h" #include "scene/animation/animation_player.h" @@ -419,7 +420,9 @@ void SceneImportSettingsDialog::_fill_scene(Node *p_node, TreeItem *p_parent_ite animation_player->connect(SceneStringName(animation_finished), callable_mp(this, &SceneImportSettingsDialog::_animation_finished)); } else if (Object::cast_to(p_node)) { category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE; - skeletons.push_back(Object::cast_to(p_node)); + Skeleton3D *skeleton = Object::cast_to(p_node); + skeleton->connect(SNAME("tree_entered"), callable_mp(this, &SceneImportSettingsDialog::_skeleton_tree_entered).bind(skeleton)); + skeletons.push_back(skeleton); } else { category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE; } @@ -480,6 +483,11 @@ void SceneImportSettingsDialog::_fill_scene(Node *p_node, TreeItem *p_parent_ite contents_aabb.merge_with(aabb); } } + + Skeleton3D *skeleton = Object::cast_to(p_node); + if (skeleton) { + bones_mesh_preview->set_mesh(Skeleton3DGizmoPlugin::get_bones_mesh(skeleton, -1, true)); + } } void SceneImportSettingsDialog::_update_scene() { @@ -800,6 +808,7 @@ void SceneImportSettingsDialog::_select(Tree *p_from, const String &p_type, cons mesh_preview->hide(); _reset_animation(); + bones_mesh_preview->hide(); if (Object::cast_to(scene)) { Object::cast_to(scene)->show(); } @@ -834,6 +843,7 @@ void SceneImportSettingsDialog::_select(Tree *p_from, const String &p_type, cons scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE; } else if (Object::cast_to(nd.node)) { scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE; + bones_mesh_preview->show(); } else { scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE; scene_import_settings_data->hide_options = editing_animation; @@ -1055,6 +1065,10 @@ void SceneImportSettingsDialog::_animation_slider_value_changed(double p_value) animation_player->seek(p_value * animation_map[selected_id].animation->get_length(), true); } +void SceneImportSettingsDialog::_skeleton_tree_entered(Skeleton3D *skeleton) { + bones_mesh_preview->set_skeleton_path(skeleton->get_path()); +} + void SceneImportSettingsDialog::_animation_finished(const StringName &p_name) { Animation::LoopMode loop_mode = animation_loop_mode; @@ -1800,6 +1814,13 @@ SceneImportSettingsDialog::SceneImportSettingsDialog() { collider_mat->set_albedo(Color(0.5, 0.5, 1.0)); } + { + bones_mesh_preview = memnew(MeshInstance3D); + bones_mesh_preview->set_cast_shadows_setting(GeometryInstance3D::SHADOW_CASTING_SETTING_OFF); + bones_mesh_preview->set_skeleton_path(NodePath()); + base_viewport->add_child(bones_mesh_preview); + } + inspector = memnew(EditorInspector); inspector->set_custom_minimum_size(Size2(300 * EDSCALE, 0)); inspector->connect(SNAME("property_edited"), callable_mp(this, &SceneImportSettingsDialog::_inspector_property_edited)); diff --git a/editor/import/3d/scene_import_settings.h b/editor/import/3d/scene_import_settings.h index c2a5151432d8..a1c537ddc8df 100644 --- a/editor/import/3d/scene_import_settings.h +++ b/editor/import/3d/scene_import_settings.h @@ -113,6 +113,7 @@ class SceneImportSettingsDialog : public ConfirmationDialog { bool animation_pingpong = false; bool previous_import_as_skeleton = false; bool previous_rest_as_reset = false; + MeshInstance3D *bones_mesh_preview = nullptr; Ref collider_mat; @@ -190,6 +191,7 @@ class SceneImportSettingsDialog : public ConfirmationDialog { void _material_tree_selected(); void _mesh_tree_selected(); void _scene_tree_selected(); + void _skeleton_tree_entered(Skeleton3D *skeleton); void _cleanup(); void _on_light_1_switch_pressed(); void _on_light_2_switch_pressed(); diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index b340dd976e00..9ac5051eb2a3 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -1180,16 +1180,18 @@ int Skeleton3DEditor::get_selected_bone() const { return selected_bone; } +Skeleton3DGizmoPlugin::SelectionMaterials Skeleton3DGizmoPlugin::selection_materials; + Skeleton3DGizmoPlugin::Skeleton3DGizmoPlugin() { - unselected_mat = Ref(memnew(StandardMaterial3D)); - unselected_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); - unselected_mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); - unselected_mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - unselected_mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); - unselected_mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); - - selected_mat = Ref(memnew(ShaderMaterial)); - selected_sh = Ref(memnew(Shader)); + selection_materials.unselected_mat.instantiate(); + selection_materials.unselected_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + selection_materials.unselected_mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + selection_materials.unselected_mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + selection_materials.unselected_mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true); + selection_materials.unselected_mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); + + selection_materials.selected_mat.instantiate(); + Ref selected_sh = Ref(memnew(Shader)); selected_sh->set_code(R"( // Skeleton 3D gizmo bones shader. @@ -1208,7 +1210,7 @@ void fragment() { ALPHA = COLOR.a; } )"); - selected_mat->set_shader(selected_sh); + selection_materials.selected_mat->set_shader(selected_sh); // Register properties in editor settings. EDITOR_DEF_RST("editors/3d_gizmos/gizmo_colors/skeleton", Color(1, 0.8, 0.4)); @@ -1218,6 +1220,11 @@ void fragment() { EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "editors/3d_gizmos/gizmo_settings/bone_shape", PROPERTY_HINT_ENUM, "Wire,Octahedron")); } +Skeleton3DGizmoPlugin::~Skeleton3DGizmoPlugin() { + selection_materials.unselected_mat.unref(); + selection_materials.selected_mat.unref(); +} + bool Skeleton3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } @@ -1354,6 +1361,11 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { selected = se->get_selected_bone(); } + Ref m = get_bones_mesh(skeleton, selected, p_gizmo->is_selected()); + p_gizmo->add_mesh(m, Ref(), Transform3D(), skeleton->register_skin(skeleton->create_skin_from_rest_transforms())); +} + +Ref Skeleton3DGizmoPlugin::get_bones_mesh(Skeleton3D *p_skeleton, int p_selected, bool p_is_selected) { Color bone_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/skeleton"); Color selected_bone_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/selected_bone"); real_t bone_axis_length = EDITOR_GET("editors/3d_gizmos/gizmo_settings/bone_axis_length"); @@ -1367,11 +1379,11 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Ref surface_tool(memnew(SurfaceTool)); surface_tool->begin(Mesh::PRIMITIVE_LINES); - if (p_gizmo->is_selected()) { - surface_tool->set_material(selected_mat); + if (p_is_selected) { + surface_tool->set_material(selection_materials.selected_mat); } else { - unselected_mat->set_albedo(bone_color); - surface_tool->set_material(unselected_mat); + selection_materials.unselected_mat->set_albedo(bone_color); + surface_tool->set_material(selection_materials.unselected_mat); } LocalVector bones; @@ -1385,16 +1397,16 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { weights[0] = 1; int current_bone_index = 0; - Vector bones_to_process = skeleton->get_parentless_bones(); + Vector bones_to_process = p_skeleton->get_parentless_bones(); while (bones_to_process.size() > current_bone_index) { int current_bone_idx = bones_to_process[current_bone_index]; current_bone_index++; - Color current_bone_color = (current_bone_idx == selected) ? selected_bone_color : bone_color; + Color current_bone_color = (current_bone_idx == p_selected) ? selected_bone_color : bone_color; Vector child_bones_vector; - child_bones_vector = skeleton->get_bone_children(current_bone_idx); + child_bones_vector = p_skeleton->get_bone_children(current_bone_idx); int child_bones_size = child_bones_vector.size(); for (int i = 0; i < child_bones_size; i++) { @@ -1405,8 +1417,8 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { int child_bone_idx = child_bones_vector[i]; - Vector3 v0 = skeleton->get_bone_global_rest(current_bone_idx).origin; - Vector3 v1 = skeleton->get_bone_global_rest(child_bone_idx).origin; + Vector3 v0 = p_skeleton->get_bone_global_rest(current_bone_idx).origin; + Vector3 v1 = p_skeleton->get_bone_global_rest(child_bone_idx).origin; Vector3 d = (v1 - v0).normalized(); real_t dist = v0.distance_to(v1); @@ -1414,7 +1426,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { int closest = -1; real_t closest_d = 0.0; for (int j = 0; j < 3; j++) { - real_t dp = Math::abs(skeleton->get_bone_global_rest(current_bone_idx).basis[j].normalized().dot(d)); + real_t dp = Math::abs(p_skeleton->get_bone_global_rest(current_bone_idx).basis[j].normalized().dot(d)); if (j == 0 || dp > closest_d) { closest = j; } @@ -1441,7 +1453,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { for (int j = 0; j < 3; j++) { Vector3 axis; if (first == Vector3()) { - axis = d.cross(d.cross(skeleton->get_bone_global_rest(current_bone_idx).basis[j])).normalized(); + axis = d.cross(d.cross(p_skeleton->get_bone_global_rest(current_bone_idx).basis[j])).normalized(); first = axis; } else { axis = d.cross(first).normalized(); @@ -1496,7 +1508,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { surface_tool->add_vertex(v0); surface_tool->set_bones(bones); surface_tool->set_weights(weights); - surface_tool->add_vertex(v0 + (skeleton->get_bone_global_rest(current_bone_idx).basis.inverse())[j].normalized() * dist * bone_axis_length); + surface_tool->add_vertex(v0 + (p_skeleton->get_bone_global_rest(current_bone_idx).basis.inverse())[j].normalized() * dist * bone_axis_length); if (j == closest) { continue; @@ -1513,7 +1525,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { surface_tool->add_vertex(v1); surface_tool->set_bones(bones); surface_tool->set_weights(weights); - surface_tool->add_vertex(v1 + (skeleton->get_bone_global_rest(child_bone_idx).basis.inverse())[j].normalized() * dist * bone_axis_length); + surface_tool->add_vertex(v1 + (p_skeleton->get_bone_global_rest(child_bone_idx).basis.inverse())[j].normalized() * dist * bone_axis_length); if (j == closest) { continue; @@ -1526,6 +1538,5 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { } } - Ref m = surface_tool->commit(); - p_gizmo->add_mesh(m, Ref(), Transform3D(), skeleton->register_skin(skeleton->create_skin_from_rest_transforms())); + return surface_tool->commit(); } diff --git a/editor/plugins/skeleton_3d_editor_plugin.h b/editor/plugins/skeleton_3d_editor_plugin.h index 79dc16ae2f6e..42beb842a71b 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.h +++ b/editor/plugins/skeleton_3d_editor_plugin.h @@ -252,11 +252,15 @@ class Skeleton3DEditorPlugin : public EditorPlugin { class Skeleton3DGizmoPlugin : public EditorNode3DGizmoPlugin { GDCLASS(Skeleton3DGizmoPlugin, EditorNode3DGizmoPlugin); - Ref unselected_mat; - Ref selected_mat; - Ref selected_sh; + struct SelectionMaterials { + Ref unselected_mat; + Ref selected_mat; + }; + static SelectionMaterials selection_materials; public: + static Ref get_bones_mesh(Skeleton3D *p_skeleton, int p_selected, bool p_is_selected); + bool has_gizmo(Node3D *p_spatial) override; String get_gizmo_name() const override; int get_priority() const override; @@ -269,6 +273,7 @@ class Skeleton3DGizmoPlugin : public EditorNode3DGizmoPlugin { void redraw(EditorNode3DGizmo *p_gizmo) override; Skeleton3DGizmoPlugin(); + ~Skeleton3DGizmoPlugin(); }; #endif // SKELETON_3D_EDITOR_PLUGIN_H From 1b7d7034a426ebc123d1572f3a0b15fc724eba8d Mon Sep 17 00:00:00 2001 From: Giganzo <158825920+Giganzo@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:25:26 +0200 Subject: [PATCH 024/446] Fix Connect Signal Dialog control alignment --- editor/connections_dialog.cpp | 5 ----- editor/themes/editor_theme_manager.cpp | 4 ---- 2 files changed, 9 deletions(-) diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index eb0ab1174b32..99342daa064f 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -486,11 +486,6 @@ void ConnectDialog::_notification(int p_what) { type_list->set_item_icon(i, get_editor_theme_icon(type_name)); } - Ref style = get_theme_stylebox(CoreStringName(normal), "LineEdit")->duplicate(); - if (style.is_valid()) { - style->set_content_margin(SIDE_TOP, style->get_content_margin(SIDE_TOP) + 1.0); - from_signal->add_theme_style_override(CoreStringName(normal), style); - } method_search->set_right_icon(get_editor_theme_icon("Search")); open_method_tree->set_icon(get_editor_theme_icon("Edit")); } break; diff --git a/editor/themes/editor_theme_manager.cpp b/editor/themes/editor_theme_manager.cpp index 9237a62a7428..841af01fdf44 100644 --- a/editor/themes/editor_theme_manager.cpp +++ b/editor/themes/editor_theme_manager.cpp @@ -865,7 +865,6 @@ void EditorThemeManager::_populate_standard_styles(const Ref &p_the // CheckBox. { Ref checkbox_style = p_config.panel_container_style->duplicate(); - checkbox_style->set_content_margin_individual((p_config.increased_margin + 2) * EDSCALE, p_config.base_margin * EDSCALE, (p_config.increased_margin + 2) * EDSCALE, p_config.base_margin * EDSCALE); p_theme->set_stylebox(CoreStringName(normal), "CheckBox", checkbox_style); p_theme->set_stylebox(SceneStringName(pressed), "CheckBox", checkbox_style); @@ -1165,9 +1164,6 @@ void EditorThemeManager::_populate_standard_styles(const Ref &p_the // LineEdit & TextEdit. { Ref text_editor_style = p_config.button_style->duplicate(); - // The original button_style style has an extra 1 pixel offset that makes LineEdits not align with Buttons, - // so this compensates for that. - text_editor_style->set_content_margin(SIDE_TOP, text_editor_style->get_content_margin(SIDE_TOP) - 1 * EDSCALE); // Don't round the bottom corners to make the line look sharper. text_editor_style->set_corner_radius(CORNER_BOTTOM_LEFT, 0); From fe6762a6c7a00654a90b532e8c96a153c1b07593 Mon Sep 17 00:00:00 2001 From: Saracen Date: Tue, 27 Aug 2024 22:55:43 +0100 Subject: [PATCH 025/446] Add Instance Placeholder validation check. Disallow toggling placeholder on editable children or inherited nodes. --- editor/scene_tree_dock.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 02c8a03ac6ed..f0ad4c4b5e1d 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1236,6 +1236,10 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { break; } + if (!_validate_no_foreign()) { + break; + } + List selection = editor_selection->get_selected_node_list(); List::Element *e = selection.front(); if (e) { From 5c21c0d8d353802ba82ba6a5d89f536fee83029a Mon Sep 17 00:00:00 2001 From: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com> Date: Wed, 28 Aug 2024 18:32:45 +0200 Subject: [PATCH 026/446] [Tree] Improve navigation with row select mode Allows navigating with the `ui_left/right` actions when selecting rows, fixing a navigation inconsistency --- scene/gui/tree.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 5830bea25848..9b5ad8189144 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -3468,29 +3468,37 @@ void Tree::gui_input(const Ref &p_event) { accept_event(); } - if (!selected_item || select_mode == SELECT_ROW || selected_col > (columns.size() - 1)) { + if (!selected_item || selected_col > (columns.size() - 1)) { return; } + if (k.is_valid() && k->is_shift_pressed()) { selected_item->set_collapsed_recursive(false); - } else { + } else if (select_mode != SELECT_ROW) { _go_right(); + } else if (selected_item->get_first_child() != nullptr && selected_item->is_collapsed()) { + selected_item->set_collapsed(false); + } else { + _go_down(); } } else if (p_event->is_action("ui_left") && p_event->is_pressed()) { if (!cursor_can_exit_tree) { accept_event(); } - if (!selected_item || select_mode == SELECT_ROW || selected_col < 0) { + if (!selected_item || selected_col < 0) { return; } if (k.is_valid() && k->is_shift_pressed()) { selected_item->set_collapsed_recursive(true); - } else { + } else if (select_mode != SELECT_ROW) { _go_left(); + } else if (selected_item->get_first_child() != nullptr && !selected_item->is_collapsed()) { + selected_item->set_collapsed(true); + } else { + _go_up(); } - } else if (p_event->is_action("ui_up") && p_event->is_pressed() && !is_command) { if (!cursor_can_exit_tree) { accept_event(); From f04a9bb63027fb5284070b3d8f51d094f37b59f8 Mon Sep 17 00:00:00 2001 From: rune-scape Date: Sun, 28 Jul 2024 08:28:24 -0700 Subject: [PATCH 027/446] Avoid const_cast in mesh_storage.h --- drivers/gles3/storage/mesh_storage.cpp | 4 ++-- drivers/gles3/storage/mesh_storage.h | 2 +- servers/rendering/dummy/storage/mesh_storage.h | 2 +- servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp | 4 ++-- servers/rendering/renderer_rd/storage_rd/mesh_storage.h | 2 +- servers/rendering/storage/mesh_storage.cpp | 2 +- servers/rendering/storage/mesh_storage.h | 4 ++-- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp index b55a2e0a8a39..6aa67ef01e5e 100644 --- a/drivers/gles3/storage/mesh_storage.cpp +++ b/drivers/gles3/storage/mesh_storage.cpp @@ -1768,14 +1768,14 @@ AABB MeshStorage::_multimesh_get_custom_aabb(RID p_multimesh) const { return multimesh->custom_aabb; } -AABB MeshStorage::_multimesh_get_aabb(RID p_multimesh) const { +AABB MeshStorage::_multimesh_get_aabb(RID p_multimesh) { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); ERR_FAIL_NULL_V(multimesh, AABB()); if (multimesh->custom_aabb != AABB()) { return multimesh->custom_aabb; } if (multimesh->aabb_dirty) { - const_cast(this)->_update_dirty_multimeshes(); + _update_dirty_multimeshes(); } return multimesh->aabb; } diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h index a2edbb9c4817..31858cd372c6 100644 --- a/drivers/gles3/storage/mesh_storage.h +++ b/drivers/gles3/storage/mesh_storage.h @@ -510,7 +510,7 @@ class MeshStorage : public RendererMeshStorage { virtual RID _multimesh_get_mesh(RID p_multimesh) const override; virtual void _multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) override; virtual AABB _multimesh_get_custom_aabb(RID p_multimesh) const override; - virtual AABB _multimesh_get_aabb(RID p_multimesh) const override; + virtual AABB _multimesh_get_aabb(RID p_multimesh) override; virtual Transform3D _multimesh_instance_get_transform(RID p_multimesh, int p_index) const override; virtual Transform2D _multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override; diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h index ec195621470d..b0953b5dce37 100644 --- a/servers/rendering/dummy/storage/mesh_storage.h +++ b/servers/rendering/dummy/storage/mesh_storage.h @@ -163,7 +163,7 @@ class MeshStorage : public RendererMeshStorage { virtual AABB _multimesh_get_custom_aabb(RID p_multimesh) const override { return AABB(); } virtual RID _multimesh_get_mesh(RID p_multimesh) const override { return RID(); } - virtual AABB _multimesh_get_aabb(RID p_multimesh) const override { return AABB(); } + virtual AABB _multimesh_get_aabb(RID p_multimesh) override { return AABB(); } virtual Transform3D _multimesh_instance_get_transform(RID p_multimesh, int p_index) const override { return Transform3D(); } virtual Transform2D _multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override { return Transform2D(); } diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 539bdcbbd09f..9b8b541b5db1 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -2040,7 +2040,7 @@ AABB MeshStorage::_multimesh_get_custom_aabb(RID p_multimesh) const { return multimesh->custom_aabb; } -AABB MeshStorage::_multimesh_get_aabb(RID p_multimesh) const { +AABB MeshStorage::_multimesh_get_aabb(RID p_multimesh) { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); ERR_FAIL_NULL_V(multimesh, AABB()); if (multimesh->custom_aabb != AABB()) { @@ -2048,7 +2048,7 @@ AABB MeshStorage::_multimesh_get_aabb(RID p_multimesh) const { } if (multimesh->aabb_dirty) { - const_cast(this)->_update_dirty_multimeshes(); + _update_dirty_multimeshes(); } return multimesh->aabb; } diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 4344db783dd1..f811314fb66d 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -652,7 +652,7 @@ class MeshStorage : public RendererMeshStorage { virtual void _multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) override; virtual AABB _multimesh_get_custom_aabb(RID p_multimesh) const override; - virtual AABB _multimesh_get_aabb(RID p_multimesh) const override; + virtual AABB _multimesh_get_aabb(RID p_multimesh) override; virtual MultiMeshInterpolator *_multimesh_get_interpolator(RID p_multimesh) const override; diff --git a/servers/rendering/storage/mesh_storage.cpp b/servers/rendering/storage/mesh_storage.cpp index 221ebaa27779..6680920c9825 100644 --- a/servers/rendering/storage/mesh_storage.cpp +++ b/servers/rendering/storage/mesh_storage.cpp @@ -285,7 +285,7 @@ int RendererMeshStorage::multimesh_get_visible_instances(RID p_multimesh) const return _multimesh_get_visible_instances(p_multimesh); } -AABB RendererMeshStorage::multimesh_get_aabb(RID p_multimesh) const { +AABB RendererMeshStorage::multimesh_get_aabb(RID p_multimesh) { return _multimesh_get_aabb(p_multimesh); } diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h index ecd2a967d0ba..5e3a4738e6fe 100644 --- a/servers/rendering/storage/mesh_storage.h +++ b/servers/rendering/storage/mesh_storage.h @@ -151,7 +151,7 @@ class RendererMeshStorage { virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible); virtual int multimesh_get_visible_instances(RID p_multimesh) const; - virtual AABB multimesh_get_aabb(RID p_multimesh) const; + virtual AABB multimesh_get_aabb(RID p_multimesh); virtual RID _multimesh_allocate() = 0; virtual void _multimesh_initialize(RID p_rid) = 0; @@ -183,7 +183,7 @@ class RendererMeshStorage { virtual void _multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; virtual int _multimesh_get_visible_instances(RID p_multimesh) const = 0; - virtual AABB _multimesh_get_aabb(RID p_multimesh) const = 0; + virtual AABB _multimesh_get_aabb(RID p_multimesh) = 0; // Multimesh is responsible for allocating / destroying a MultiMeshInterpolator object. // This allows shared functionality for interpolation across backends. From 8ca7f0e33408612ddcb840005fb889de3edd4528 Mon Sep 17 00:00:00 2001 From: Hendrik Brucker Date: Fri, 30 Aug 2024 14:04:54 +0200 Subject: [PATCH 028/446] Prevent crash after removing GraphEdit's connection layer and add additional warnings --- scene/gui/graph_edit.cpp | 44 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 60b3e371a0a6..836f2277f52a 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -260,6 +260,8 @@ PackedStringArray GraphEdit::get_configuration_warnings() const { } Error GraphEdit::connect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port) { + ERR_FAIL_NULL_V_MSG(connections_layer, FAILED, "connections_layer is missing."); + if (is_node_connected(p_from, p_from_port, p_to, p_to_port)) { return OK; } @@ -313,6 +315,8 @@ bool GraphEdit::is_node_connected(const StringName &p_from, int p_from_port, con } void GraphEdit::disconnect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port) { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); + for (const List>::Element *E = connections.front(); E; E = E->next()) { if (E->get()->from_node == p_from && E->get()->from_port == p_from_port && E->get()->to_node == p_to && E->get()->to_port == p_to_port) { connection_map[p_from].erase(E->get()); @@ -356,6 +360,8 @@ void GraphEdit::_scroll_moved(double) { } void GraphEdit::_update_scroll_offset() { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); + set_block_minimum_size_adjust(true); for (int i = 0; i < get_child_count(); i++) { @@ -524,6 +530,8 @@ void GraphEdit::_graph_element_resize_request(const Vector2 &p_new_minsize, Node } void GraphEdit::_graph_frame_autoshrink_changed(const Vector2 &p_new_minsize, GraphFrame *p_frame) { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); + _update_graph_frame(p_frame); minimap->queue_redraw(); @@ -535,6 +543,7 @@ void GraphEdit::_graph_frame_autoshrink_changed(const Vector2 &p_new_minsize, Gr void GraphEdit::_graph_element_moved(Node *p_node) { GraphElement *graph_element = Object::cast_to(p_node); ERR_FAIL_NULL(graph_element); + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); minimap->queue_redraw(); queue_redraw(); @@ -543,6 +552,7 @@ void GraphEdit::_graph_element_moved(Node *p_node) { } void GraphEdit::_graph_node_slot_updated(int p_index, Node *p_node) { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); GraphNode *graph_node = Object::cast_to(p_node); ERR_FAIL_NULL(graph_node); @@ -558,6 +568,8 @@ void GraphEdit::_graph_node_slot_updated(int p_index, Node *p_node) { } void GraphEdit::_graph_node_rect_changed(GraphNode *p_node) { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); + // Only invalidate the cache when zooming or the node is moved/resized in graph space. if (panner->is_panning()) { return; @@ -566,7 +578,6 @@ void GraphEdit::_graph_node_rect_changed(GraphNode *p_node) { for (Ref &c : connection_map[p_node->get_name()]) { c->_cache.dirty = true; } - connections_layer->queue_redraw(); callable_mp(this, &GraphEdit::_update_top_connection_layer).call_deferred(); @@ -623,7 +634,9 @@ void GraphEdit::add_child_notify(Node *p_child) { } graph_element->connect("raise_request", callable_mp(this, &GraphEdit::_ensure_node_order_from).bind(graph_element)); graph_element->connect("resize_request", callable_mp(this, &GraphEdit::_graph_element_resize_request).bind(graph_element)); - graph_element->connect(SceneStringName(item_rect_changed), callable_mp((CanvasItem *)connections_layer, &CanvasItem::queue_redraw)); + if (connections_layer != nullptr && connections_layer->is_inside_tree()) { + graph_element->connect(SceneStringName(item_rect_changed), callable_mp((CanvasItem *)connections_layer, &CanvasItem::queue_redraw)); + } graph_element->connect(SceneStringName(item_rect_changed), callable_mp((CanvasItem *)minimap, &GraphEditMinimap::queue_redraw)); graph_element->set_scale(Vector2(zoom, zoom)); @@ -640,6 +653,7 @@ void GraphEdit::remove_child_notify(Node *p_child) { minimap = nullptr; } else if (p_child == connections_layer) { connections_layer = nullptr; + WARN_PRINT("GraphEdit's connection_layer removed. This should not be done. If you like to remove all GraphElements from a GraphEdit node, do not simply remove all non-internal children but check their type since the connection layer has to be kept non-internal due to technical reasons."); } if (top_layer != nullptr && is_inside_tree()) { @@ -662,7 +676,9 @@ void GraphEdit::remove_child_notify(Node *p_child) { for (const Ref &conn : connection_map[graph_node->get_name()]) { conn->_cache.dirty = true; } - connections_layer->queue_redraw(); + if (connections_layer != nullptr && connections_layer->is_inside_tree()) { + connections_layer->queue_redraw(); + } } GraphFrame *frame = Object::cast_to(graph_element); @@ -1680,6 +1696,8 @@ void GraphEdit::set_selected(Node *p_child) { } void GraphEdit::gui_input(const Ref &p_ev) { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); + ERR_FAIL_COND(p_ev.is_null()); if (panner->gui_input(p_ev, warped_panning ? get_global_rect() : Rect2())) { return; @@ -2012,6 +2030,8 @@ void GraphEdit::gui_input(const Ref &p_ev) { } void GraphEdit::_pan_callback(Vector2 p_scroll_vec, Ref p_event) { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); + h_scrollbar->set_value(h_scrollbar->get_value() - p_scroll_vec.x); v_scrollbar->set_value(v_scrollbar->get_value() - p_scroll_vec.y); @@ -2027,6 +2047,8 @@ void GraphEdit::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref &c : connection_map[p_from]) { if (c->from_node == p_from && c->from_port == p_from_port && c->to_node == p_to && c->to_port == p_to_port) { if (!Math::is_equal_approx(c->activity, p_activity)) { @@ -2043,6 +2065,8 @@ void GraphEdit::set_connection_activity(const StringName &p_from, int p_from_por } void GraphEdit::reset_all_connection_activity() { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); + bool changed = false; for (Ref &conn : connections) { if (conn->activity > 0) { @@ -2057,6 +2081,8 @@ void GraphEdit::reset_all_connection_activity() { } void GraphEdit::clear_connections() { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); + for (Ref &c : connections) { c->_cache.line->queue_free(); } @@ -2070,7 +2096,9 @@ void GraphEdit::clear_connections() { } void GraphEdit::force_connection_drag_end() { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); ERR_FAIL_COND_MSG(!connecting, "Drag end requested without active drag!"); + connecting = false; connecting_valid = false; minimap->queue_redraw(); @@ -2100,6 +2128,8 @@ void GraphEdit::set_zoom(float p_zoom) { } void GraphEdit::set_zoom_custom(float p_zoom, const Vector2 &p_center) { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); + p_zoom = CLAMP(p_zoom, zoom_min, zoom_max); if (zoom == p_zoom) { return; @@ -2508,6 +2538,8 @@ bool GraphEdit::is_showing_arrange_button() const { } void GraphEdit::override_connections_shader(const Ref &p_shader) { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); + connections_shader = p_shader; _invalidate_connection_line_cache(); @@ -2526,6 +2558,8 @@ void GraphEdit::_minimap_toggled() { } void GraphEdit::set_connection_lines_curvature(float p_curvature) { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); + lines_curvature = p_curvature; _invalidate_connection_line_cache(); connections_layer->queue_redraw(); @@ -2537,7 +2571,9 @@ float GraphEdit::get_connection_lines_curvature() const { } void GraphEdit::set_connection_lines_thickness(float p_thickness) { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); ERR_FAIL_COND_MSG(p_thickness < 0, "Connection lines thickness must be greater than or equal to 0."); + if (lines_thickness == p_thickness) { return; } @@ -2552,6 +2588,8 @@ float GraphEdit::get_connection_lines_thickness() const { } void GraphEdit::set_connection_lines_antialiased(bool p_antialiased) { + ERR_FAIL_NULL_MSG(connections_layer, "connections_layer is missing."); + if (lines_antialiased == p_antialiased) { return; } From 8ff190b065bbe255349eef4ed708c3b580b24efd Mon Sep 17 00:00:00 2001 From: passivestar <60579014+passivestar@users.noreply.github.com> Date: Fri, 30 Aug 2024 22:00:36 +0400 Subject: [PATCH 029/446] Fix dock width not respecting editor scale --- editor/editor_dock_manager.cpp | 4 ++-- editor/editor_node.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/editor/editor_dock_manager.cpp b/editor/editor_dock_manager.cpp index 75135532aac4..0bdda41f26de 100644 --- a/editor/editor_dock_manager.cpp +++ b/editor/editor_dock_manager.cpp @@ -509,7 +509,7 @@ void EditorDockManager::save_docks_to_config(Ref p_layout, const Str } for (int i = 0; i < hsplits.size(); i++) { - p_layout->set_value(p_section, "dock_hsplit_" + itos(i + 1), hsplits[i]->get_split_offset()); + p_layout->set_value(p_section, "dock_hsplit_" + itos(i + 1), int(hsplits[i]->get_split_offset() / EDSCALE)); } FileSystemDock::get_singleton()->save_layout_to_config(p_layout, p_section); @@ -605,7 +605,7 @@ void EditorDockManager::load_docks_from_config(Ref p_layout, const S continue; } int ofs = p_layout->get_value(p_section, "dock_hsplit_" + itos(i + 1)); - hsplits[i]->set_split_offset(ofs); + hsplits[i]->set_split_offset(ofs * EDSCALE); } FileSystemDock::get_singleton()->load_layout_from_config(p_layout, p_section); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index d3fa2ed716f4..1a3e6219f8b5 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -7555,8 +7555,8 @@ EditorNode::EditorNode() { default_layout->set_value(docks_section, "dock_split_" + itos(i + 1), 0); } default_layout->set_value(docks_section, "dock_hsplit_1", 0); - default_layout->set_value(docks_section, "dock_hsplit_2", 270 * EDSCALE); - default_layout->set_value(docks_section, "dock_hsplit_3", -270 * EDSCALE); + default_layout->set_value(docks_section, "dock_hsplit_2", 270); + default_layout->set_value(docks_section, "dock_hsplit_3", -270); default_layout->set_value(docks_section, "dock_hsplit_4", 0); _update_layouts_menu(); From 74f64aaf98beba74c8c7eedac152c4a50b336994 Mon Sep 17 00:00:00 2001 From: Marius Hanl Date: Sat, 31 Aug 2024 19:23:34 +0200 Subject: [PATCH 030/446] 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 8c07cefc194c..2f6798ab869f 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 a517ba8b43f7..e1d269a86e74 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 204636e128cd..42346a0c0bd6 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 d2866e9f041e..e2b1b7b34be7 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 a4a08d5b5e5f..f40307712d41 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 cc0f726b3a3c..f7a5d495c4bc 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 eb97337b3796..00ef6a684264 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 dfb87f43da53..bd30fc28d113 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 bbc689040a61..815cc0c8fe9b 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 52ba98b4d5c5..1c153b0451f9 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 b4d9644f167a..63c2c027c289 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 d7de5a722305..1222fd7c1fad 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 e0fac5d0c6e7..8e82d606052e 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 ea1756b65aee..8f646a762123 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 ae92365c3273..1d009637b7a6 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 3059d10c4c39..53bf4696d675 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 69b2f30c4067..3b2ad3330410 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 d47270841da0..f4409a865901 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 34cade9267d0..48bc8a054845 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 ea63e0710423..07848c61db6b 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 cfa0f0c35ce2..4294c93c9362 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 851ad858769b..386feae4f9bd 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 8f1177429234..017fa739679e 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 031/446] 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 5b23cf44d038..a8083c22d7fd 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 032/446] 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 bfd08cfc7b53..c24e110edaef 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 d2a9c2315ff6..ff25e416ae98 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 dabeaa6a4b9ed6f636d9480c82cc0c8e66162376 Mon Sep 17 00:00:00 2001 From: Hristo Iliev Date: Mon, 2 Sep 2024 15:00:57 +0300 Subject: [PATCH 033/446] Fix polygon node losing its UV toolbar by adding a call to the show method when assinging a node. Fixes #96238 --- editor/plugins/abstract_polygon_2d_editor.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 60d808952e08..804f9c607e75 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -748,7 +748,9 @@ AbstractPolygon2DEditor::AbstractPolygon2DEditor(bool p_wip_destructive) { } void AbstractPolygon2DEditorPlugin::edit(Object *p_object) { - polygon_editor->edit(Object::cast_to(p_object)); + Node *polygon_node = Object::cast_to(p_object); + polygon_editor->edit(polygon_node); + make_visible(polygon_node != nullptr); } bool AbstractPolygon2DEditorPlugin::handles(Object *p_object) const { From f82262eecb558accb926628aa95b6e66209dcad3 Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Mon, 2 Sep 2024 01:28:07 -0700 Subject: [PATCH 034/446] 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 2786c25e9adc..a242a0d1d8b4 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 c049acf557e9..de7ec2a4ca51 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 69973a34dd68..acb72c552faa 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 b3e6dcf54a6c..d347d4910296 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 73a61ff77f29..7763874d028a 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 07efafe13bff..795404919263 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 2934e4b5ee68..ccee5e8ca438 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 63399fb32bc4..f3f6bfa2f16f 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 359aaa48eea02f1fc00c746e106e83d523c8acea Mon Sep 17 00:00:00 2001 From: Rudolph Bester Date: Tue, 3 Sep 2024 07:12:51 +0200 Subject: [PATCH 035/446] Fixed OpenGL shadow textures not honoring texture type when reusing textures --- drivers/gles3/storage/light_storage.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp index aab1aadf02d3..9b976c220683 100644 --- a/drivers/gles3/storage/light_storage.cpp +++ b/drivers/gles3/storage/light_storage.cpp @@ -1521,6 +1521,11 @@ bool LightStorage::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_i uint64_t min_pass = 0; // Pass of the existing one, try to use the least recently used one (LRU fashion). for (int j = 0; j < sc; j++) { + if (sarr[j].owner_is_omni != is_omni) { + // Existing light instance type doesn't match new light instance type skip. + continue; + } + LightInstance *sli = light_instance_owner.get_or_null(sarr[j].owner); if (!sli) { // Found a released light instance. From ecc0ab8061c84811eb729b074fbfd3cfd9f5b9ac Mon Sep 17 00:00:00 2001 From: kobewi Date: Tue, 3 Sep 2024 23:07:19 +0200 Subject: [PATCH 036/446] Add EditorContextMenuPluginManager and refactor menu plugins --- doc/classes/EditorContextMenuPlugin.xml | 42 +++++- doc/classes/EditorPlugin.xml | 23 +-- editor/editor_data.cpp | 132 ----------------- editor/editor_data.h | 29 ---- editor/editor_node.cpp | 4 + editor/filesystem_dock.cpp | 38 +++-- editor/plugins/editor_context_menu_plugin.cpp | 134 +++++++++++++++++- editor/plugins/editor_context_menu_plugin.h | 55 ++++++- editor/plugins/editor_plugin.cpp | 18 +-- editor/plugins/editor_plugin.h | 14 +- editor/plugins/script_editor_plugin.cpp | 21 +-- editor/scene_tree_dock.cpp | 29 ++-- editor/scene_tree_dock.h | 1 + 13 files changed, 288 insertions(+), 252 deletions(-) diff --git a/doc/classes/EditorContextMenuPlugin.xml b/doc/classes/EditorContextMenuPlugin.xml index 7eeee3d7fd72..71c4ca0f9b9b 100644 --- a/doc/classes/EditorContextMenuPlugin.xml +++ b/doc/classes/EditorContextMenuPlugin.xml @@ -14,7 +14,7 @@ - Called when creating a context menu, custom options can be added by using the [method add_context_menu_item] function. + Called when creating a context menu, custom options can be added by using the [method add_context_menu_item] or [method add_context_menu_item_from_shortcut] functions. [param paths] contains currently selected paths (depending on menu), which can be used to conditionally add options. @@ -22,14 +22,29 @@ - - Add custom options to the context menu of the currently specified slot. - To trigger a [param shortcut] before the context menu is created, please additionally call the [method add_menu_shortcut] function. + Add custom option to the context menu of the plugin's specified slot. When the option is activated, [param callback] will be called. Callback should take single [Array] argument; array contents depend on context menu slot. [codeblock] func _popup_menu(paths): add_context_menu_item("File Custom options", handle, ICON) [/codeblock] + If you want to assign shortcut to the menu item, use [method add_context_menu_item_from_shortcut] instead. + + + + + + + + + Add custom option to the context menu of the plugin's specified slot. The option will have the [param shortcut] assigned and reuse its callback. The shortcut has to be registered beforehand with [method add_menu_shortcut]. + [codeblock] + func _init(): + add_menu_shortcut(SHORTCUT, handle) + + func _popup_menu(paths): + add_context_menu_item_from_shortcut("File Custom options", SHORTCUT, ICON) + [/codeblock] @@ -37,13 +52,26 @@ - To register the shortcut for the context menu, call this function within the [method Object._init] function, even if the context menu has not been created yet. - Note that this method should only be invoked from [method Object._init]; otherwise, the shortcut will not be registered correctly. + Registers a shortcut associated with the plugin's context menu. This method should be called once (e.g. in plugin's [method Object._init]). [param callback] will be called when user presses the specified [param shortcut] while the menu's context is in effect (e.g. FileSystem dock is focused). Callback should take single [Array] argument; array contents depend on context menu slot. [codeblock] func _init(): - add_menu_shortcut(SHORTCUT, handle); + add_menu_shortcut(SHORTCUT, handle) [/codeblock] + + + Context menu of Scene dock. [method _popup_menu] will be called with a list of paths to currently selected nodes, while option callback will receive the list of currently selected nodes. + + + Context menu of FileSystem dock. [method _popup_menu] and option callback will be called with list of paths of the currently selected files. + + + The "Create..." submenu of FileSystem dock's context menu. [method _popup_menu] and option callback will be called with list of paths of the currently selected files. + + + Context menu of Scene dock. [method _popup_menu] will be called with the path to the currently edited script, while option callback will receive reference to that script. + + diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index b3191e537863..de49764f0d8c 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -403,11 +403,11 @@ - + - Adds a plugin to the context menu. [param slot] is the position in the context menu where the plugin will be added. - Context menus are supported for three commonly used areas: the file system, scene tree, and editor script list panel. + Adds a plugin to the context menu. [param slot] is the context menu where the plugin will be added. + See [enum EditorContextMenuPlugin.ContextMenuSlot] for available context menus. A plugin instance can belong only to a single context menu slot. @@ -635,10 +635,9 @@ - - + - Removes a context menu plugin from the specified slot. + Removes the specified context menu plugin. @@ -891,17 +890,5 @@ Pass the [InputEvent] to other editor plugins except the main [Node3D] one. This can be used to prevent node selection changes and work with sub-gizmos instead. - - Context menu slot for the SceneTree. - - - Context menu slot for the FileSystem. - - - Context menu slot for the ScriptEditor file list. - - - Context menu slot for the FileSystem create submenu. - diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index e5caa6a35221..ee16c61c8972 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -522,138 +522,6 @@ EditorPlugin *EditorData::get_extension_editor_plugin(const StringName &p_class_ return plugin == nullptr ? nullptr : *plugin; } -void EditorData::add_context_menu_plugin(ContextMenuSlot p_slot, const Ref &p_plugin) { - ContextMenu cm; - cm.p_slot = p_slot; - cm.plugin = p_plugin; - p_plugin->start_idx = context_menu_plugins.size() * EditorContextMenuPlugin::MAX_ITEMS; - context_menu_plugins.push_back(cm); -} - -void EditorData::remove_context_menu_plugin(ContextMenuSlot p_slot, const Ref &p_plugin) { - for (int i = context_menu_plugins.size() - 1; i > -1; i--) { - if (context_menu_plugins[i].p_slot == p_slot && context_menu_plugins[i].plugin == p_plugin) { - context_menu_plugins.remove_at(i); - } - } -} - -int EditorData::match_context_menu_shortcut(ContextMenuSlot p_slot, const Ref &p_event) { - for (ContextMenu &cm : context_menu_plugins) { - if (cm.p_slot != p_slot) { - continue; - } - HashMap, Callable> &cms = cm.plugin->context_menu_shortcuts; - int shortcut_idx = 0; - for (KeyValue, Callable> &E : cms) { - const Ref &p_shortcut = E.key; - if (p_shortcut->matches_event(p_event)) { - return EditorData::CONTEXT_MENU_ITEM_ID_BASE + cm.plugin->start_idx + shortcut_idx; - } - shortcut_idx++; - } - } - return 0; -} - -void EditorData::add_options_from_plugins(PopupMenu *p_popup, ContextMenuSlot p_slot, const Vector &p_paths) { - bool add_separator = false; - - for (ContextMenu &cm : context_menu_plugins) { - if (cm.p_slot != p_slot) { - continue; - } - cm.plugin->clear_context_menu_items(); - cm.plugin->add_options(p_paths); - HashMap &items = cm.plugin->context_menu_items; - if (items.size() > 0 && !add_separator) { - add_separator = true; - p_popup->add_separator(); - } - for (KeyValue &E : items) { - EditorContextMenuPlugin::ContextMenuItem &item = E.value; - - if (item.icon.is_valid()) { - p_popup->add_icon_item(item.icon, item.item_name, item.idx); - const int icon_size = p_popup->get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor)); - p_popup->set_item_icon_max_width(-1, icon_size); - } else { - p_popup->add_item(item.item_name, item.idx); - } - if (item.shortcut.is_valid()) { - p_popup->set_item_shortcut(-1, item.shortcut, true); - } - } - } -} - -template -void EditorData::invoke_plugin_callback(ContextMenuSlot p_slot, int p_option, const T &p_arg) { - Variant arg = p_arg; - Variant *argptr = &arg; - - for (int i = 0; i < context_menu_plugins.size(); i++) { - if (context_menu_plugins[i].p_slot != p_slot || context_menu_plugins[i].plugin.is_null()) { - continue; - } - Ref plugin = context_menu_plugins[i].plugin; - - // Shortcut callback. - int shortcut_idx = 0; - int shortcut_base_idx = EditorData::CONTEXT_MENU_ITEM_ID_BASE + plugin->start_idx; - for (KeyValue, Callable> &E : plugin->context_menu_shortcuts) { - if (shortcut_base_idx + shortcut_idx == p_option) { - const Callable &callable = E.value; - Callable::CallError ce; - Variant result; - callable.callp((const Variant **)&argptr, 1, result, ce); - } - shortcut_idx++; - } - if (p_option < shortcut_base_idx + shortcut_idx) { - return; - } - - HashMap &items = plugin->context_menu_items; - for (KeyValue &E : items) { - EditorContextMenuPlugin::ContextMenuItem &item = E.value; - - if (p_option != item.idx || !item.callable.is_valid()) { - continue; - } - - Callable::CallError ce; - Variant result; - item.callable.callp((const Variant **)&argptr, 1, result, ce); - - if (ce.error != Callable::CallError::CALL_OK) { - String err = Variant::get_callable_error_text(item.callable, nullptr, 0, ce); - ERR_PRINT("Error calling function from context menu: " + err); - } - } - } - // Invoke submenu items. - if (p_slot == CONTEXT_SLOT_FILESYSTEM) { - invoke_plugin_callback(CONTEXT_SUBMENU_SLOT_FILESYSTEM_CREATE, p_option, p_arg); - } -} - -void EditorData::filesystem_options_pressed(ContextMenuSlot p_slot, int p_option, const Vector &p_selected) { - invoke_plugin_callback(p_slot, p_option, p_selected); -} - -void EditorData::scene_tree_options_pressed(ContextMenuSlot p_slot, int p_option, const List &p_selected) { - TypedArray nodes; - for (Node *selected : p_selected) { - nodes.append(selected); - } - invoke_plugin_callback(p_slot, p_option, nodes); -} - -void EditorData::script_editor_options_pressed(ContextMenuSlot p_slot, int p_option, const Ref &p_script) { - invoke_plugin_callback(p_slot, p_option, p_script); -} - void EditorData::add_custom_type(const String &p_type, const String &p_inherits, const Ref