From 75eacba5cd2fbbfc318e4c510d501e2283fdd20b Mon Sep 17 00:00:00 2001
From: Haoyu Qiu <timothyqiu32@gmail.com>
Date: Wed, 17 Apr 2024 09:55:40 +0800
Subject: Add Camera3D preview in Inspector

---
 editor/plugins/camera_3d_editor_plugin.cpp       | 51 ++++++++++++++++--------
 editor/plugins/camera_3d_editor_plugin.h         | 27 +++++++++++--
 editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp | 20 +---------
 editor/plugins/gizmos/camera_3d_gizmo_plugin.h   |  1 -
 editor/plugins/node_3d_editor_plugin.cpp         | 18 +++++++++
 editor/plugins/node_3d_editor_plugin.h           |  2 +
 6 files changed, 79 insertions(+), 40 deletions(-)

(limited to 'editor')

diff --git a/editor/plugins/camera_3d_editor_plugin.cpp b/editor/plugins/camera_3d_editor_plugin.cpp
index b9555296b8..f738870ead 100644
--- a/editor/plugins/camera_3d_editor_plugin.cpp
+++ b/editor/plugins/camera_3d_editor_plugin.cpp
@@ -30,8 +30,11 @@
 
 #include "camera_3d_editor_plugin.h"
 
+#include "core/config/project_settings.h"
 #include "editor/editor_node.h"
 #include "node_3d_editor_plugin.h"
+#include "scene/gui/texture_rect.h"
+#include "scene/main/viewport.h"
 
 void Camera3DEditor::_node_removed(Node *p_node) {
 	if (p_node == node) {
@@ -79,9 +82,35 @@ Camera3DEditor::Camera3DEditor() {
 	preview->connect("pressed", callable_mp(this, &Camera3DEditor::_pressed));
 }
 
+void Camera3DPreview::_update_sub_viewport_size() {
+	sub_viewport->set_size(Node3DEditor::get_camera_viewport_size(camera));
+}
+
+Camera3DPreview::Camera3DPreview(Camera3D *p_camera) :
+		TexturePreview(nullptr, false), camera(p_camera), sub_viewport(memnew(SubViewport)) {
+	RenderingServer::get_singleton()->viewport_attach_camera(sub_viewport->get_viewport_rid(), camera->get_camera());
+	add_child(sub_viewport);
+
+	TextureRect *display = get_texture_display();
+	display->set_texture(sub_viewport->get_texture());
+	sub_viewport->connect("size_changed", callable_mp((CanvasItem *)display, &CanvasItem::queue_redraw));
+
+	ProjectSettings::get_singleton()->connect("settings_changed", callable_mp(this, &Camera3DPreview::_update_sub_viewport_size));
+	_update_sub_viewport_size();
+}
+
+bool EditorInspectorPluginCamera3DPreview::can_handle(Object *p_object) {
+	return Object::cast_to<Camera3D>(p_object) != nullptr;
+}
+
+void EditorInspectorPluginCamera3DPreview::parse_begin(Object *p_object) {
+	Camera3D *camera = Object::cast_to<Camera3D>(p_object);
+	Camera3DPreview *preview = memnew(Camera3DPreview(camera));
+	add_custom_control(preview);
+}
+
 void Camera3DEditorPlugin::edit(Object *p_object) {
 	Node3DEditor::get_singleton()->set_can_preview(Object::cast_to<Camera3D>(p_object));
-	//camera_editor->edit(Object::cast_to<Node>(p_object));
 }
 
 bool Camera3DEditorPlugin::handles(Object *p_object) const {
@@ -89,27 +118,15 @@ bool Camera3DEditorPlugin::handles(Object *p_object) const {
 }
 
 void Camera3DEditorPlugin::make_visible(bool p_visible) {
-	if (p_visible) {
-		//Node3DEditor::get_singleton()->set_can_preview(Object::cast_to<Camera3D>(p_object));
-	} else {
+	if (!p_visible) {
 		Node3DEditor::get_singleton()->set_can_preview(nullptr);
 	}
 }
 
 Camera3DEditorPlugin::Camera3DEditorPlugin() {
-	/*	camera_editor = memnew( CameraEditor );
-	EditorNode::get_singleton()->get_main_screen_control()->add_child(camera_editor);
-
-	camera_editor->set_anchor(SIDE_LEFT,Control::ANCHOR_END);
-	camera_editor->set_anchor(SIDE_RIGHT,Control::ANCHOR_END);
-	camera_editor->set_offset(SIDE_LEFT,60);
-	camera_editor->set_offset(SIDE_RIGHT,0);
-	camera_editor->set_offset(SIDE_TOP,0);
-	camera_editor->set_offset(SIDE_BOTTOM,10);
-
-
-	camera_editor->hide();
-*/
+	Ref<EditorInspectorPluginCamera3DPreview> plugin;
+	plugin.instantiate();
+	add_inspector_plugin(plugin);
 }
 
 Camera3DEditorPlugin::~Camera3DEditorPlugin() {
diff --git a/editor/plugins/camera_3d_editor_plugin.h b/editor/plugins/camera_3d_editor_plugin.h
index 2e4d8a1ee3..4f64bac051 100644
--- a/editor/plugins/camera_3d_editor_plugin.h
+++ b/editor/plugins/camera_3d_editor_plugin.h
@@ -32,7 +32,10 @@
 #define CAMERA_3D_EDITOR_PLUGIN_H
 
 #include "editor/plugins/editor_plugin.h"
-#include "scene/3d/camera_3d.h"
+#include "editor/plugins/texture_editor_plugin.h"
+
+class Camera3D;
+class SubViewport;
 
 class Camera3DEditor : public Control {
 	GDCLASS(Camera3DEditor, Control);
@@ -52,11 +55,29 @@ public:
 	Camera3DEditor();
 };
 
+class Camera3DPreview : public TexturePreview {
+	GDCLASS(Camera3DPreview, TexturePreview);
+
+	Camera3D *camera = nullptr;
+	SubViewport *sub_viewport = nullptr;
+
+	void _update_sub_viewport_size();
+
+public:
+	Camera3DPreview(Camera3D *p_camera);
+};
+
+class EditorInspectorPluginCamera3DPreview : public EditorInspectorPluginTexture {
+	GDCLASS(EditorInspectorPluginCamera3DPreview, EditorInspectorPluginTexture);
+
+public:
+	virtual bool can_handle(Object *p_object) override;
+	virtual void parse_begin(Object *p_object) override;
+};
+
 class Camera3DEditorPlugin : public EditorPlugin {
 	GDCLASS(Camera3DEditorPlugin, EditorPlugin);
 
-	//CameraEditor *camera_editor;
-
 public:
 	virtual String get_name() const override { return "Camera3D"; }
 	bool has_main_screen() const override { return false; }
diff --git a/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp
index 19dd45a3ea..afbf781683 100644
--- a/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/camera_3d_gizmo_plugin.cpp
@@ -46,24 +46,6 @@ Camera3DGizmoPlugin::Camera3DGizmoPlugin() {
 	create_handle_material("handles");
 }
 
-Size2i Camera3DGizmoPlugin::_get_viewport_size(Camera3D *p_camera) {
-	Viewport *viewport = p_camera->get_viewport();
-
-	Window *window = Object::cast_to<Window>(viewport);
-	if (window) {
-		return window->get_size();
-	}
-
-	SubViewport *sub_viewport = Object::cast_to<SubViewport>(viewport);
-	ERR_FAIL_NULL_V(sub_viewport, Size2i());
-
-	if (sub_viewport == EditorNode::get_singleton()->get_scene_root()) {
-		return Size2(GLOBAL_GET("display/window/size/viewport_width"), GLOBAL_GET("display/window/size/viewport_height"));
-	}
-
-	return sub_viewport->get_size();
-}
-
 bool Camera3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
 	return Object::cast_to<Camera3D>(p_spatial) != nullptr;
 }
@@ -163,7 +145,7 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 	Ref<Material> material = get_material("camera_material", p_gizmo);
 	Ref<Material> icon = get_material("camera_icon", p_gizmo);
 
-	const Size2i viewport_size = _get_viewport_size(camera);
+	const Size2i viewport_size = Node3DEditor::get_camera_viewport_size(camera);
 	const real_t viewport_aspect = viewport_size.x > 0 && viewport_size.y > 0 ? viewport_size.aspect() : 1.0;
 	const Size2 size_factor = viewport_aspect > 1.0 ? Size2(1.0, 1.0 / viewport_aspect) : Size2(viewport_aspect, 1.0);
 
diff --git a/editor/plugins/gizmos/camera_3d_gizmo_plugin.h b/editor/plugins/gizmos/camera_3d_gizmo_plugin.h
index ba65ebb8de..94238704c1 100644
--- a/editor/plugins/gizmos/camera_3d_gizmo_plugin.h
+++ b/editor/plugins/gizmos/camera_3d_gizmo_plugin.h
@@ -37,7 +37,6 @@ class Camera3DGizmoPlugin : public EditorNode3DGizmoPlugin {
 	GDCLASS(Camera3DGizmoPlugin, EditorNode3DGizmoPlugin);
 
 private:
-	static Size2i _get_viewport_size(Camera3D *p_camera);
 	static float _find_closest_angle_to_half_pi_arc(const Vector3 &p_from, const Vector3 &p_to, float p_arc_radius, const Transform3D &p_arc_xform);
 
 public:
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 4a418e62ca..66647058ca 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -8994,6 +8994,24 @@ void Node3DEditorPlugin::set_state(const Dictionary &p_state) {
 	spatial_editor->set_state(p_state);
 }
 
+Size2i Node3DEditor::get_camera_viewport_size(Camera3D *p_camera) {
+	Viewport *viewport = p_camera->get_viewport();
+
+	Window *window = Object::cast_to<Window>(viewport);
+	if (window) {
+		return window->get_size();
+	}
+
+	SubViewport *sub_viewport = Object::cast_to<SubViewport>(viewport);
+	ERR_FAIL_NULL_V(sub_viewport, Size2i());
+
+	if (sub_viewport == EditorNode::get_singleton()->get_scene_root()) {
+		return Size2(GLOBAL_GET("display/window/size/viewport_width"), GLOBAL_GET("display/window/size/viewport_height"));
+	}
+
+	return sub_viewport->get_size();
+}
+
 Vector3 Node3DEditor::snap_point(Vector3 p_target, Vector3 p_start) const {
 	if (is_snap_enabled()) {
 		real_t snap = get_translate_snap();
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 96210de403..1dbccbea59 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -841,6 +841,8 @@ protected:
 public:
 	static Node3DEditor *get_singleton() { return singleton; }
 
+	static Size2i get_camera_viewport_size(Camera3D *p_camera);
+
 	Vector3 snap_point(Vector3 p_target, Vector3 p_start = Vector3(0, 0, 0)) const;
 
 	float get_znear() const { return settings_znear->get_value(); }
-- 
cgit v1.2.3


From a54c6ce42d9a58f435e94ca6f9237172203ae637 Mon Sep 17 00:00:00 2001
From: Yahkub-R <62478788+Yahkub-R@users.noreply.github.com>
Date: Mon, 19 Aug 2024 06:09:30 -0400
Subject: Fix crash when re-importing model with AnimationPlayer panel open and
 node selected

---
 editor/plugins/animation_player_editor_plugin.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'editor')

diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 660e4647a1..acb2de185a 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -802,7 +802,7 @@ void AnimationPlayerEditor::set_state(const Dictionary &p_state) {
 					player->connect(SNAME("animation_list_changed"), callable_mp(this, &AnimationPlayerEditor::_animation_libraries_updated), CONNECT_DEFERRED);
 				}
 				if (!player->is_connected(SNAME("current_animation_changed"), callable_mp(this, &AnimationPlayerEditor::_current_animation_changed))) {
-					player->connect(SNAME("current_animation_changed"), callable_mp(this, &AnimationPlayerEditor::_current_animation_changed), CONNECT_DEFERRED);
+					player->connect(SNAME("current_animation_changed"), callable_mp(this, &AnimationPlayerEditor::_current_animation_changed));
 				}
 			}
 
-- 
cgit v1.2.3


From 1deb42ad8dd6429cde94f437675c0cff3f8dcb60 Mon Sep 17 00:00:00 2001
From: Saracen <SaracenOne@gmail.com>
Date: Sun, 1 Sep 2024 01:32:56 +0100
Subject: Improve behaviour of AnimationPlayer warnings.

---
 editor/animation_track_editor.cpp | 22 ++++++++++++++++++----
 editor/editor_node.cpp            |  9 ++++++---
 2 files changed, 24 insertions(+), 7 deletions(-)

(limited to 'editor')

diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 8c07cefc19..e83d6cb31d 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -1378,12 +1378,26 @@ void AnimationTimelineEdit::_anim_loop_pressed() {
 		undo_redo->add_undo_method(this, "update_values");
 		undo_redo->commit_action();
 	} else {
-		String base_path = animation->get_path();
-		if (FileAccess::exists(base_path + ".import")) {
-			EditorNode::get_singleton()->show_warning(TTR("Can't change loop mode on animation instanced from imported scene."));
+		String base = animation->get_path();
+		int srpos = base.find("::");
+		if (srpos != -1) {
+			base = animation->get_path().substr(0, srpos);
+		}
+
+		if (FileAccess::exists(base + ".import")) {
+			if (ResourceLoader::get_resource_type(base) == "PackedScene") {
+				EditorNode::get_singleton()->show_warning(TTR("Can't change loop mode on animation instanced from an imported scene.\n\nTo change this animation's loop mode, navigate to the scene's Advanced Import settings and select the animation.\nYou can then change the loop mode from the inspector menu."));
+			} else {
+				EditorNode::get_singleton()->show_warning(TTR("Can't change loop mode on animation instanced from an imported resource."));
+			}
 		} else {
-			EditorNode::get_singleton()->show_warning(TTR("Can't change loop mode on animation embedded in another scene."));
+			if (ResourceLoader::get_resource_type(base) == "PackedScene") {
+				EditorNode::get_singleton()->show_warning(TTR("Can't change loop mode on animation embedded in another scene.\n\nYou must open this scene and change the animation's loop mode from there."));
+			} else {
+				EditorNode::get_singleton()->show_warning(TTR("Can't change loop mode on animation embedded in another resource."));
+			}
 		}
+
 		update_values();
 	}
 }
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index d3fa2ed716..5fd02b2881 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -5200,7 +5200,8 @@ void EditorNode::show_accept(const String &p_text, const String &p_title) {
 		_close_save_scene_progress();
 		accept->set_ok_button_text(p_title);
 		accept->set_text(p_text);
-		EditorInterface::get_singleton()->popup_dialog_centered(accept);
+		accept->reset_size();
+		EditorInterface::get_singleton()->popup_dialog_centered_clamped(accept, Size2i(), 0.0);
 	}
 }
 
@@ -5210,7 +5211,8 @@ void EditorNode::show_save_accept(const String &p_text, const String &p_title) {
 		_close_save_scene_progress();
 		save_accept->set_ok_button_text(p_title);
 		save_accept->set_text(p_text);
-		EditorInterface::get_singleton()->popup_dialog_centered(save_accept);
+		save_accept->reset_size();
+		EditorInterface::get_singleton()->popup_dialog_centered_clamped(save_accept, Size2i(), 0.0);
 	}
 }
 
@@ -5219,7 +5221,8 @@ void EditorNode::show_warning(const String &p_text, const String &p_title) {
 		_close_save_scene_progress();
 		warning->set_text(p_text);
 		warning->set_title(p_title);
-		EditorInterface::get_singleton()->popup_dialog_centered(warning);
+		warning->reset_size();
+		EditorInterface::get_singleton()->popup_dialog_centered_clamped(warning, Size2i(), 0.0);
 	} else {
 		WARN_PRINT(p_title + " " + p_text);
 	}
-- 
cgit v1.2.3


From 3345f90bf39459a197334e5e066c4d96849e3d5f Mon Sep 17 00:00:00 2001
From: passivestar <60579014+passivestar@users.noreply.github.com>
Date: Mon, 7 Oct 2024 15:49:33 +0400
Subject: Fix plugin creation dialog script name tooltip

---
 editor/plugins/plugin_config_dialog.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'editor')

diff --git a/editor/plugins/plugin_config_dialog.cpp b/editor/plugins/plugin_config_dialog.cpp
index af9efda939..c3e87c508e 100644
--- a/editor/plugins/plugin_config_dialog.cpp
+++ b/editor/plugins/plugin_config_dialog.cpp
@@ -305,7 +305,7 @@ PluginConfigDialog::PluginConfigDialog() {
 	grid->add_child(script_name_label);
 
 	script_edit = memnew(LineEdit);
-	script_edit->set_tooltip_text(TTR("Optional. The path to the script (relative to the add-on folder). If left empty, will default to \"plugin.gd\"."));
+	script_edit->set_tooltip_text(TTR("Optional. The name of the script file. If left empty, will default to the subfolder name."));
 	script_edit->set_placeholder("\"plugin.gd\" -> res://addons/my_plugin/plugin.gd");
 	script_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
 	grid->add_child(script_edit);
-- 
cgit v1.2.3


From 891173b3ea6f9bca531100f17e912c4ce9091fad Mon Sep 17 00:00:00 2001
From: passivestar <60579014+passivestar@users.noreply.github.com>
Date: Sun, 7 Jul 2024 14:46:14 +0400
Subject: [macOS] Change the shortcut for Align Transform with View

---
 editor/plugins/node_3d_editor_plugin.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

(limited to 'editor')

diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index c6a0dfb888..2e14caed86 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -8650,7 +8650,12 @@ Node3DEditor::Node3DEditor() {
 	ED_SHORTCUT("spatial_editor/focus_origin", TTR("Focus Origin"), Key::O);
 	ED_SHORTCUT("spatial_editor/focus_selection", TTR("Focus Selection"), Key::F);
 	ED_SHORTCUT_ARRAY("spatial_editor/align_transform_with_view", TTR("Align Transform with View"),
-			{ int32_t(KeyModifierMask::ALT | KeyModifierMask::CMD_OR_CTRL | Key::KP_0), int32_t(KeyModifierMask::ALT | KeyModifierMask::CMD_OR_CTRL | Key::M) });
+			{ int32_t(KeyModifierMask::ALT | KeyModifierMask::CTRL | Key::KP_0),
+					int32_t(KeyModifierMask::ALT | KeyModifierMask::CTRL | Key::M),
+					int32_t(KeyModifierMask::ALT | KeyModifierMask::CTRL | Key::G) });
+	ED_SHORTCUT_OVERRIDE_ARRAY("spatial_editor/align_transform_with_view", "macos",
+			{ int32_t(KeyModifierMask::ALT | KeyModifierMask::META | Key::KP_0),
+					int32_t(KeyModifierMask::ALT | KeyModifierMask::META | Key::G) });
 	ED_SHORTCUT("spatial_editor/align_rotation_with_view", TTR("Align Rotation with View"), KeyModifierMask::ALT + KeyModifierMask::CMD_OR_CTRL + Key::F);
 	ED_SHORTCUT("spatial_editor/freelook_toggle", TTR("Toggle Freelook"), KeyModifierMask::SHIFT + Key::F);
 	ED_SHORTCUT("spatial_editor/decrease_fov", TTR("Decrease Field of View"), KeyModifierMask::CMD_OR_CTRL + Key::EQUAL); // Usually direct access key for `KEY_PLUS`.
-- 
cgit v1.2.3


From d5fbc7dab1d4d417e4b4f9e9db680135b4636055 Mon Sep 17 00:00:00 2001
From: kobewi <kobewi4e@gmail.com>
Date: Tue, 22 Oct 2024 15:52:29 +0200
Subject: Improve Scale Selection in Animation tab

---
 editor/animation_track_editor.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

(limited to 'editor')

diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 741d127ea2..ebaf368b5e 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -6586,6 +6586,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
 		case EDIT_SCALE_SELECTION:
 		case EDIT_SCALE_FROM_CURSOR: {
 			scale_dialog->popup_centered(Size2(200, 100) * EDSCALE);
+			scale->get_line_edit()->grab_focus();
 		} break;
 		case EDIT_SCALE_CONFIRM: {
 			if (selection.is_empty()) {
@@ -7806,10 +7807,13 @@ AnimationTrackEditor::AnimationTrackEditor() {
 	scale->set_min(-99999);
 	scale->set_max(99999);
 	scale->set_step(0.001);
+	scale->set_select_all_on_focus(true);
 	vbc->add_margin_child(TTR("Scale Ratio:"), scale);
-	scale_dialog->connect(SceneStringName(confirmed), callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_SCALE_CONFIRM));
+	scale_dialog->connect(SceneStringName(confirmed), callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_SCALE_CONFIRM), CONNECT_DEFERRED);
 	add_child(scale_dialog);
 
+	scale_dialog->register_text_enter(scale->get_line_edit());
+
 	//
 	ease_dialog = memnew(ConfirmationDialog);
 	ease_dialog->set_title(TTR("Select Transition and Easing"));
-- 
cgit v1.2.3


From 893ce62967b08e337a72ecd965caf837d2117f2b Mon Sep 17 00:00:00 2001
From: yds <ydeltastar@gmail.com>
Date: Sat, 26 Oct 2024 18:41:16 -0300
Subject: Fix `ColorPicker`'s remote synchronization when typing values

---
 editor/editor_properties.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'editor')

diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 158ea4b8a7..68ebffbc69 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -2628,7 +2628,7 @@ EditorPropertyColor::EditorPropertyColor() {
 	add_child(picker);
 	picker->set_flat(true);
 	picker->connect("color_changed", callable_mp(this, &EditorPropertyColor::_color_changed));
-	picker->connect("popup_closed", callable_mp(this, &EditorPropertyColor::_popup_closed));
+	picker->connect("popup_closed", callable_mp(this, &EditorPropertyColor::_popup_closed), CONNECT_DEFERRED);
 	picker->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(picker->get_picker()));
 	picker->get_popup()->connect("about_to_popup", callable_mp(this, &EditorPropertyColor::_picker_opening));
 }
-- 
cgit v1.2.3


From 56d01fb46731c07503ee80ff774fa9aab4522e82 Mon Sep 17 00:00:00 2001
From: Pablo Andres Fuente <pablo.andres.fuente@gmail.com>
Date: Thu, 24 Oct 2024 09:42:43 -0300
Subject: Show file names in the remove files confirmation dialog

Closes #85261

Co-authored-by: jsjtxietian <jsjtxietian@outlook.com>
---
 editor/dependency_editor.cpp | 46 +++++++++++++++++++++++++++++++++++++++++---
 editor/dependency_editor.h   |  4 ++++
 2 files changed, 47 insertions(+), 3 deletions(-)

(limited to 'editor')

diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index 8ba5811ffa..c9f0bd1f24 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -527,6 +527,20 @@ void DependencyRemoveDialog::_build_removed_dependency_tree(const Vector<Removed
 	}
 }
 
+void DependencyRemoveDialog::_show_files_to_delete_list() {
+	files_to_delete_list->clear();
+
+	for (const String &s : dirs_to_delete) {
+		String t = s.trim_prefix("res://");
+		files_to_delete_list->add_item(t, Ref<Texture2D>(), false);
+	}
+
+	for (const String &s : files_to_delete) {
+		String t = s.trim_prefix("res://");
+		files_to_delete_list->add_item(t, Ref<Texture2D>(), false);
+	}
+}
+
 void DependencyRemoveDialog::show(const Vector<String> &p_folders, const Vector<String> &p_files) {
 	all_remove_files.clear();
 	dirs_to_delete.clear();
@@ -543,21 +557,24 @@ void DependencyRemoveDialog::show(const Vector<String> &p_folders, const Vector<
 		files_to_delete.push_back(p_files[i]);
 	}
 
+	_show_files_to_delete_list();
+
 	Vector<RemovedDependency> removed_deps;
 	_find_all_removed_dependencies(EditorFileSystem::get_singleton()->get_filesystem(), removed_deps);
 	_find_localization_remaps_of_removed_files(removed_deps);
 	removed_deps.sort();
 	if (removed_deps.is_empty()) {
-		owners->hide();
+		vb_owners->hide();
 		text->set_text(TTR("Remove the selected files from the project? (Cannot be undone.)\nDepending on your filesystem configuration, the files will either be moved to the system trash or deleted permanently."));
 		reset_size();
 		popup_centered();
 	} else {
 		_build_removed_dependency_tree(removed_deps);
-		owners->show();
+		vb_owners->show();
 		text->set_text(TTR("The files being removed are required by other resources in order for them to work.\nRemove them anyway? (Cannot be undone.)\nDepending on your filesystem configuration, the files will either be moved to the system trash or deleted permanently."));
 		popup_centered(Size2(500, 350));
 	}
+
 	EditorFileSystem::get_singleton()->scan_changes();
 }
 
@@ -666,15 +683,38 @@ DependencyRemoveDialog::DependencyRemoveDialog() {
 	set_ok_button_text(TTR("Remove"));
 
 	VBoxContainer *vb = memnew(VBoxContainer);
+	vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
 	add_child(vb);
 
 	text = memnew(Label);
 	vb->add_child(text);
 
+	Label *files_to_delete_label = memnew(Label);
+	files_to_delete_label->set_theme_type_variation("HeaderSmall");
+	files_to_delete_label->set_text(TTR("Files to be deleted:"));
+	vb->add_child(files_to_delete_label);
+
+	files_to_delete_list = memnew(ItemList);
+	files_to_delete_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+	files_to_delete_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+	files_to_delete_list->set_custom_minimum_size(Size2(0, 94) * EDSCALE);
+	vb->add_child(files_to_delete_list);
+
+	vb_owners = memnew(VBoxContainer);
+	vb_owners->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+	vb_owners->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+	vb->add_child(vb_owners);
+
+	Label *owners_label = memnew(Label);
+	owners_label->set_theme_type_variation("HeaderSmall");
+	owners_label->set_text(TTR("Dependencies of files to be deleted:"));
+	vb_owners->add_child(owners_label);
+
 	owners = memnew(Tree);
 	owners->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
 	owners->set_hide_root(true);
-	vb->add_child(owners);
+	owners->set_custom_minimum_size(Size2(0, 94) * EDSCALE);
+	vb_owners->add_child(owners);
 	owners->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 }
 
diff --git a/editor/dependency_editor.h b/editor/dependency_editor.h
index 0256f39979..93954cbd97 100644
--- a/editor/dependency_editor.h
+++ b/editor/dependency_editor.h
@@ -31,6 +31,7 @@
 #ifndef DEPENDENCY_EDITOR_H
 #define DEPENDENCY_EDITOR_H
 
+#include "scene/gui/box_container.h"
 #include "scene/gui/dialogs.h"
 #include "scene/gui/item_list.h"
 #include "scene/gui/tab_container.h"
@@ -98,6 +99,8 @@ class DependencyRemoveDialog : public ConfirmationDialog {
 
 	Label *text = nullptr;
 	Tree *owners = nullptr;
+	VBoxContainer *vb_owners = nullptr;
+	ItemList *files_to_delete_list = nullptr;
 
 	HashMap<String, String> all_remove_files;
 	Vector<String> dirs_to_delete;
@@ -122,6 +125,7 @@ class DependencyRemoveDialog : public ConfirmationDialog {
 	void _find_all_removed_dependencies(EditorFileSystemDirectory *efsd, Vector<RemovedDependency> &p_removed);
 	void _find_localization_remaps_of_removed_files(Vector<RemovedDependency> &p_removed);
 	void _build_removed_dependency_tree(const Vector<RemovedDependency> &p_removed);
+	void _show_files_to_delete_list();
 
 	void ok_pressed() override;
 
-- 
cgit v1.2.3


From f5b49af99fb63980ab05d8f909621393e4bfc2a6 Mon Sep 17 00:00:00 2001
From: "Silc Lizard (Tokage) Renew"
 <61938263+TokageItLab@users.noreply.github.com>
Date: Sat, 5 Oct 2024 06:00:39 +0900
Subject: Add RetargetModifier3D for realtime retarget to keep original rest

---
 editor/icons/RetargetModifier3D.svg                |   1 +
 .../3d/post_import_plugin_skeleton_renamer.cpp     |   2 +-
 .../3d/post_import_plugin_skeleton_rest_fixer.cpp  | 227 +++++++++++++++++++--
 ...post_import_plugin_skeleton_track_organizer.cpp |  42 +++-
 editor/import/3d/resource_importer_scene.cpp       |   1 +
 5 files changed, 254 insertions(+), 19 deletions(-)
 create mode 100644 editor/icons/RetargetModifier3D.svg

(limited to 'editor')

diff --git a/editor/icons/RetargetModifier3D.svg b/editor/icons/RetargetModifier3D.svg
new file mode 100644
index 0000000000..2ca7af6c6e
--- /dev/null
+++ b/editor/icons/RetargetModifier3D.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#fc7f7f"><path d="m11.667 4.166h-3.334c-1.841 0-3.333 1.492-3.333 3.334.003 1.188.638 2.283 1.667 2.877v2.956c0 .597.317 1.146.833 1.444.254.146.54.221.833.221v.002h3.334v-.002c.293 0 .579-.075.833-.221.516-.299.833-.851.833-1.444v-2.956c1.028-.594 1.664-1.689 1.667-2.877 0-1.842-1.492-3.334-3.333-3.334zm-2.5 4.166h1.666v.834h-1.666zm-2.5-.832c0-.461.372-.834.833-.834s.833.373.833.834-.372.832-.833.832-.833-.371-.833-.832zm5.833 3.223v2.61h-.833v-.833h-.834v.833h-1.666v-.833h-.834v.833h-.833v-2.608-.725h.833v.832h.834v-.832h1.666v.832h.834v-.832h.833zm0-2.391c-.461 0-.833-.371-.833-.832s.372-.834.833-.834.833.373.833.834-.372.832-.833.832z"/><path d="m4.418 9.334h-.085v.833h-.833v-2.608-.725h.567c.323-2.072 2.104-3.668 4.266-3.668h2.445c-.473-1.263-1.682-2.166-3.111-2.166h-3.334c-1.841 0-3.333 1.492-3.333 3.334.003 1.188.638 2.283 1.667 2.877v2.956c0 .597.317 1.146.833 1.444.254.146.54.221.833.221v.002h1.334v-.929c-.538-.421-.962-.962-1.249-1.571zm-1.751-5c0-.461.372-.834.833-.834s.833.373.833.834-.372.832-.833.832-.833-.371-.833-.832z"/></g></svg>
\ No newline at end of file
diff --git a/editor/import/3d/post_import_plugin_skeleton_renamer.cpp b/editor/import/3d/post_import_plugin_skeleton_renamer.cpp
index 3f6bfdcf05..700b2bc719 100644
--- a/editor/import/3d/post_import_plugin_skeleton_renamer.cpp
+++ b/editor/import/3d/post_import_plugin_skeleton_renamer.cpp
@@ -39,7 +39,7 @@
 
 void PostImportPluginSkeletonRenamer::get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) {
 	if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) {
-		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/bone_renamer/rename_bones"), true));
+		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/bone_renamer/rename_bones", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
 		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/bone_renamer/unique_node/make_unique"), true));
 		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::STRING, "retarget/bone_renamer/unique_node/skeleton_name"), "GeneralSkeleton"));
 	}
diff --git a/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp
index 64bec0532b..82940f9cef 100644
--- a/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp
+++ b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp
@@ -33,6 +33,7 @@
 #include "editor/import/3d/scene_import_settings.h"
 #include "scene/3d/bone_attachment_3d.h"
 #include "scene/3d/importer_mesh_instance_3d.h"
+#include "scene/3d/retarget_modifier_3d.h"
 #include "scene/3d/skeleton_3d.h"
 #include "scene/animation/animation_player.h"
 #include "scene/resources/bone_map.h"
@@ -42,8 +43,18 @@ void PostImportPluginSkeletonRestFixer::get_internal_import_options(InternalImpo
 		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/apply_node_transforms"), true));
 		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/normalize_position_tracks"), true));
 		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/reset_all_bone_poses_after_import"), true));
-		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/overwrite_axis", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
+
+		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "retarget/rest_fixer/retarget_method", PROPERTY_HINT_ENUM, "None,Overwrite Axis,Use Retarget Modifier", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1));
 		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/keep_global_rest_on_leftovers"), true));
+		String skeleton_bones_must_be_renamed_warning = String(
+				"The skeleton modifier option uses SkeletonProfile as a list of bone names and retargets by name matching. Without renaming, retargeting by modifier will not work and the track path of the animation will be broken and it will be not playbacked correctly."); // TODO: translate.
+		r_options->push_back(ResourceImporter::ImportOption(
+				PropertyInfo(
+						Variant::STRING, U"retarget/rest_fixer/\u26A0_validation_warning/skeleton_bones_must_be_renamed",
+						PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY),
+				Variant(skeleton_bones_must_be_renamed_warning)));
+		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/use_global_pose"), true));
+		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::STRING, "retarget/rest_fixer/original_skeleton_name"), "OriginalSkeleton"));
 		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/fix_silhouette/enable", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
 		// TODO: PostImportPlugin need to be implemented such as validate_option(PropertyInfo &property, const Dictionary &p_options).
 		// get_internal_option_visibility() is not sufficient because it can only retrieve options implemented in the core and can only read option values.
@@ -63,7 +74,11 @@ Variant PostImportPluginSkeletonRestFixer::get_internal_option_visibility(Intern
 				}
 			}
 		} else if (p_option == "retarget/rest_fixer/keep_global_rest_on_leftovers") {
-			return bool(p_options["retarget/rest_fixer/overwrite_axis"]);
+			return int(p_options["retarget/rest_fixer/retarget_method"]) == 1;
+		} else if (p_option == "retarget/rest_fixer/original_skeleton_name" || p_option == "retarget/rest_fixer/use_global_pose") {
+			return int(p_options["retarget/rest_fixer/retarget_method"]) == 2;
+		} else if (p_option.begins_with("retarget/") && p_option.ends_with("skeleton_bones_must_be_renamed")) {
+			return int(p_options["retarget/rest_fixer/retarget_method"]) == 2 && bool(p_options["retarget/bone_renamer/rename_bones"]) == false;
 		}
 	}
 	return true;
@@ -147,7 +162,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 				src_skeleton->set_bone_pose_position(src_idx, src_skeleton->get_bone_pose_position(src_idx) * scl);
 			}
 
-			// Fix animation.
+			// Fix animation by changing node transform.
 			bones_to_process = src_skeleton->get_parentless_bones();
 			{
 				TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
@@ -224,6 +239,10 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 				List<StringName> anims;
 				ap->get_animation_list(&anims);
 				for (const StringName &name : anims) {
+					if (String(name).contains("/")) {
+						continue; // Avoid animation library which may be created by importer dynamically.
+					}
+
 					Ref<Animation> anim = ap->get_animation(name);
 					int track_len = anim->get_track_count();
 
@@ -454,8 +473,13 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 			}
 		}
 
-		// Overwrite axis.
-		if (bool(p_options["retarget/rest_fixer/overwrite_axis"])) {
+		bool is_using_modifier = int(p_options["retarget/rest_fixer/retarget_method"]) == 2;
+		bool is_using_global_pose = bool(p_options["retarget/rest_fixer/use_global_pose"]);
+		Skeleton3D *orig_skeleton = nullptr;
+		Skeleton3D *profile_skeleton = nullptr;
+
+		// Retarget in some way.
+		if (int(p_options["retarget/rest_fixer/retarget_method"]) > 0) {
 			LocalVector<Transform3D> old_skeleton_rest;
 			LocalVector<Transform3D> old_skeleton_global_rest;
 			for (int i = 0; i < src_skeleton->get_bone_count(); i++) {
@@ -463,11 +487,151 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 				old_skeleton_global_rest.push_back(src_skeleton->get_bone_global_rest(i));
 			}
 
+			// Build structure for modifier.
+			if (is_using_modifier) {
+				orig_skeleton = src_skeleton;
+
+				// Duplicate src_skeleton to modify animation tracks, it will memdelele after that animation track modification.
+				src_skeleton = memnew(Skeleton3D);
+				for (int i = 0; i < orig_skeleton->get_bone_count(); i++) {
+					src_skeleton->add_bone(orig_skeleton->get_bone_name(i));
+					src_skeleton->set_bone_rest(i, orig_skeleton->get_bone_rest(i));
+					src_skeleton->set_bone_pose(i, orig_skeleton->get_bone_pose(i));
+				}
+				for (int i = 0; i < orig_skeleton->get_bone_count(); i++) {
+					src_skeleton->set_bone_parent(i, orig_skeleton->get_bone_parent(i));
+				}
+				src_skeleton->set_motion_scale(orig_skeleton->get_motion_scale());
+
+				// Rename orig_skeleton (previous src_skeleton), since it is not animated by animation track with GeneralSkeleton.
+				String original_skeleton_name = String(p_options["retarget/rest_fixer/original_skeleton_name"]);
+				String skel_name = orig_skeleton->get_name();
+				ERR_FAIL_COND_MSG(original_skeleton_name.is_empty(), "Original skeleton name cannot be empty.");
+				ERR_FAIL_COND_MSG(original_skeleton_name == skel_name, "Original skeleton name must be different from unique skeleton name.");
+
+				// Rename profile skeleton to be general skeleton.
+				profile_skeleton = memnew(Skeleton3D);
+				bool is_unique = orig_skeleton->is_unique_name_in_owner();
+				if (is_unique) {
+					orig_skeleton->set_unique_name_in_owner(false);
+				}
+				orig_skeleton->set_name(original_skeleton_name);
+				profile_skeleton->set_name(skel_name);
+				if (is_unique) {
+					profile_skeleton->set_unique_name_in_owner(true);
+				}
+				// Build profile skeleton bones.
+				int len = profile->get_bone_size();
+				for (int i = 0; i < len; i++) {
+					profile_skeleton->add_bone(profile->get_bone_name(i));
+					profile_skeleton->set_bone_rest(i, profile->get_reference_pose(i));
+				}
+				for (int i = 0; i < len; i++) {
+					int target_parent = profile_skeleton->find_bone(profile->get_bone_parent(i));
+					if (target_parent >= 0) {
+						profile_skeleton->set_bone_parent(i, target_parent);
+					}
+				}
+				for (int i = 0; i < len; i++) {
+					Vector3 origin;
+					int found = orig_skeleton->find_bone(profile->get_bone_name(i));
+					String parent_name = profile->get_bone_parent(i);
+					if (found >= 0) {
+						origin = orig_skeleton->get_bone_global_rest(found).origin;
+						if (profile->get_bone_name(i) != profile->get_root_bone()) {
+							int src_parent = -1;
+							while (src_parent < 0 && !parent_name.is_empty()) {
+								src_parent = orig_skeleton->find_bone(parent_name);
+								parent_name = profile->get_bone_parent(profile->find_bone(parent_name));
+							}
+							if (src_parent >= 0) {
+								Transform3D parent_grest = orig_skeleton->get_bone_global_rest(src_parent);
+								origin = origin - parent_grest.origin;
+							}
+						}
+					}
+					int target_parent = profile_skeleton->find_bone(profile->get_bone_parent(i));
+					if (target_parent >= 0) {
+						origin = profile_skeleton->get_bone_global_rest(target_parent).basis.get_rotation_quaternion().xform_inv(origin);
+					}
+					profile_skeleton->set_bone_rest(i, Transform3D(profile_skeleton->get_bone_rest(i).basis, origin));
+				}
+				profile_skeleton->set_motion_scale(orig_skeleton->get_motion_scale());
+				profile_skeleton->reset_bone_poses();
+				// Make structure with modifier.
+				Node *owner = p_node->get_owner();
+
+				Node *pr = orig_skeleton->get_parent();
+				pr->add_child(profile_skeleton);
+				profile_skeleton->set_owner(owner);
+
+				RetargetModifier3D *mod = memnew(RetargetModifier3D);
+				profile_skeleton->add_child(mod);
+				mod->set_owner(owner);
+				mod->set_name("RetargetModifier3D");
+
+				orig_skeleton->set_owner(nullptr);
+				orig_skeleton->reparent(mod, false);
+				orig_skeleton->set_owner(owner);
+				orig_skeleton->set_unique_name_in_owner(true);
+
+				mod->set_use_global_pose(is_using_global_pose);
+				mod->set_profile(profile);
+
+				// Fix skeleton name in animation.
+				// Mapped skeleton is animated by %GenerarSkeleton:RenamedBoneName.
+				// Unmapped skeleton is animated by %OriginalSkeleton:OriginalBoneName.
+				if (is_using_modifier) {
+					TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
+					String general_skeleton_pathname = UNIQUE_NODE_PREFIX + profile_skeleton->get_name();
+					while (nodes.size()) {
+						AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back());
+						List<StringName> anims;
+						ap->get_animation_list(&anims);
+						for (const StringName &name : anims) {
+							Ref<Animation> anim = ap->get_animation(name);
+							int track_len = anim->get_track_count();
+							for (int i = 0; i < track_len; i++) {
+								if (anim->track_get_path(i).get_name_count() == 0) {
+									return;
+								}
+								if (anim->track_get_path(i).get_name(0) == general_skeleton_pathname) {
+									bool replace = false;
+									if (anim->track_get_path(i).get_subname_count() > 0) {
+										int found = profile_skeleton->find_bone(anim->track_get_path(i).get_concatenated_subnames());
+										if (found < 0) {
+											replace = true;
+										}
+									} else {
+										replace = true;
+									}
+									if (replace) {
+										String path_string = UNIQUE_NODE_PREFIX + original_skeleton_name;
+										if (anim->track_get_path(i).get_name_count() > 1) {
+											Vector<StringName> names = anim->track_get_path(i).get_names();
+											names.remove_at(0);
+											for (int j = 0; j < names.size(); j++) {
+												path_string += "/" + names[i].operator String();
+											}
+										}
+										if (anim->track_get_path(i).get_subname_count() > 0) {
+											path_string = path_string + String(":") + anim->track_get_path(i).get_concatenated_subnames();
+										}
+										anim->track_set_path(i, path_string);
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+
 			bool keep_global_rest_leftovers = bool(p_options["retarget/rest_fixer/keep_global_rest_on_leftovers"]);
 
 			// Scan hierarchy and populate a whitelist of unmapped bones without mapped descendants.
+			// When both is_using_modifier and is_using_global_pose are enabled, this array is used for detecting warning.
 			Vector<int> keep_bone_rest;
-			if (keep_global_rest_leftovers) {
+			if (is_using_modifier || keep_global_rest_leftovers) {
 				Vector<int> bones_to_process = src_skeleton->get_parentless_bones();
 				while (bones_to_process.size() > 0) {
 					int src_idx = bones_to_process[0];
@@ -526,12 +690,14 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 					if (src_parent_idx >= 0) {
 						src_pg = src_skeleton->get_bone_global_rest(src_parent_idx).basis;
 					}
-
 					int prof_idx = profile->find_bone(src_bone_name);
 					if (prof_idx >= 0) {
-						tgt_rot = src_pg.inverse() * prof_skeleton->get_bone_global_rest(prof_idx).basis; // Mapped bone uses reference pose.
+						// Mapped bone uses reference pose.
+						// It is fine to change rest here even though is_using_modifier is enabled, since next process is aborted with unmapped bones.
+						tgt_rot = src_pg.inverse() * prof_skeleton->get_bone_global_rest(prof_idx).basis;
 					} else if (keep_global_rest_leftovers && keep_bone_rest.has(src_idx)) {
-						tgt_rot = src_pg.inverse() * old_skeleton_global_rest[src_idx].basis; // Non-Mapped bone without mapped children keeps global rest.
+						// Non-Mapped bones without mapped children keeps global rest.
+						tgt_rot = src_pg.inverse() * old_skeleton_global_rest[src_idx].basis;
 					}
 				}
 
@@ -548,7 +714,8 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 				src_skeleton->set_bone_rest(src_idx, Transform3D(tgt_rot, diff.xform(src_skeleton->get_bone_rest(src_idx).origin)));
 			}
 
-			// Fix animation.
+			// Fix animation by changing rest.
+			bool warning_detected = false;
 			{
 				TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
 				while (nodes.size()) {
@@ -573,7 +740,9 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 							ERR_CONTINUE(!node);
 
 							Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
-							if (!track_skeleton || track_skeleton != src_skeleton) {
+							if (!track_skeleton ||
+									(is_using_modifier && track_skeleton != profile_skeleton && track_skeleton != orig_skeleton) ||
+									(!is_using_modifier && track_skeleton != src_skeleton)) {
 								continue;
 							}
 
@@ -584,6 +753,16 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 
 							int bone_idx = src_skeleton->find_bone(bn);
 
+							if (is_using_modifier) {
+								int prof_idx = profile->find_bone(bn);
+								if (prof_idx < 0) {
+									if (keep_bone_rest.has(bone_idx)) {
+										warning_detected = true;
+									}
+									continue; // If is_using_modifier, the original skeleton rest is not changed.
+								}
+							}
+
 							Transform3D old_rest = old_skeleton_rest[bone_idx];
 							Transform3D new_rest = src_skeleton->get_bone_rest(bone_idx);
 							Transform3D old_pg;
@@ -629,6 +808,13 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 					}
 				}
 			}
+			if (is_using_global_pose && warning_detected) {
+				// TODO:
+				// Theoretically, if A and its conversion are calculated correctly taking into account the difference in the number of bones,
+				// there is no need to disable use_global_pose, but this is probably a fairly niche case.
+				WARN_PRINT_ED("Animated extra bone between mapped bones detected, consider disabling Use Global Pose option to prevent that the pose origin be overridden by the RetargetModifier3D.");
+			}
+
 			if (p_options.has("retarget/rest_fixer/reset_all_bone_poses_after_import") && !bool(p_options["retarget/rest_fixer/reset_all_bone_poses_after_import"])) {
 				// If Reset All Bone Poses After Import is disabled, preserve the original bone pose, adjusted for the new bone rolls.
 				for (int bone_idx = 0; bone_idx < src_skeleton->get_bone_count(); bone_idx++) {
@@ -654,6 +840,11 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 				}
 			}
 
+			if (is_using_modifier) {
+				memdelete(src_skeleton);
+				src_skeleton = profile_skeleton;
+			}
+
 			is_rest_changed = true;
 		}
 
@@ -681,7 +872,9 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 						ERR_CONTINUE(!node);
 
 						Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
-						if (!track_skeleton || track_skeleton != src_skeleton) {
+						if (!track_skeleton ||
+								(is_using_modifier && track_skeleton != profile_skeleton && track_skeleton != orig_skeleton) ||
+								(!is_using_modifier && track_skeleton != src_skeleton)) {
 							continue;
 						}
 
@@ -696,7 +889,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 			}
 		}
 
-		if (is_rest_changed) {
+		if (!is_using_modifier && is_rest_changed) {
 			// Fix skin.
 			{
 				HashSet<Ref<Skin>> mutated_skins;
@@ -766,6 +959,14 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 					src_skeleton->set_bone_pose_rotation(i, fixed_rest.basis.get_rotation_quaternion());
 					src_skeleton->set_bone_pose_scale(i, fixed_rest.basis.get_scale());
 				}
+				if (orig_skeleton) {
+					for (int i = 0; i < orig_skeleton->get_bone_count(); i++) {
+						Transform3D fixed_rest = orig_skeleton->get_bone_rest(i);
+						orig_skeleton->set_bone_pose_position(i, fixed_rest.origin);
+						orig_skeleton->set_bone_pose_rotation(i, fixed_rest.basis.get_rotation_quaternion());
+						orig_skeleton->set_bone_pose_scale(i, fixed_rest.basis.get_scale());
+					}
+				}
 			}
 		}
 
diff --git a/editor/import/3d/post_import_plugin_skeleton_track_organizer.cpp b/editor/import/3d/post_import_plugin_skeleton_track_organizer.cpp
index 53bcc59fcb..98312d3521 100644
--- a/editor/import/3d/post_import_plugin_skeleton_track_organizer.cpp
+++ b/editor/import/3d/post_import_plugin_skeleton_track_organizer.cpp
@@ -39,7 +39,7 @@ void PostImportPluginSkeletonTrackOrganizer::get_internal_import_options(Interna
 	if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) {
 		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/remove_tracks/except_bone_transform"), false));
 		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/remove_tracks/unimportant_positions"), true));
-		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/remove_tracks/unmapped_bones"), false));
+		r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "retarget/remove_tracks/unmapped_bones", PROPERTY_HINT_ENUM, "None,Remove,Separate Library"), 0));
 	}
 }
 
@@ -61,9 +61,9 @@ void PostImportPluginSkeletonTrackOrganizer::internal_process(InternalImportCate
 		}
 		bool remove_except_bone = bool(p_options["retarget/remove_tracks/except_bone_transform"]);
 		bool remove_positions = bool(p_options["retarget/remove_tracks/unimportant_positions"]);
-		bool remove_unmapped_bones = bool(p_options["retarget/remove_tracks/unmapped_bones"]);
+		int separate_unmapped_bones = int(p_options["retarget/remove_tracks/unmapped_bones"]);
 
-		if (!remove_positions && !remove_unmapped_bones) {
+		if (!remove_positions && separate_unmapped_bones == 0) {
 			return;
 		}
 
@@ -72,10 +72,16 @@ void PostImportPluginSkeletonTrackOrganizer::internal_process(InternalImportCate
 			AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back());
 			List<StringName> anims;
 			ap->get_animation_list(&anims);
+
+			Ref<AnimationLibrary> unmapped_al;
+			unmapped_al.instantiate();
+
 			for (const StringName &name : anims) {
 				Ref<Animation> anim = ap->get_animation(name);
 				int track_len = anim->get_track_count();
 				Vector<int> remove_indices;
+				Vector<int> mapped_bone_indices;
+				Vector<int> unmapped_bone_indices;
 				for (int i = 0; i < track_len; i++) {
 					String track_path = String(anim->track_get_path(i).get_concatenated_names());
 					Node *node = (ap->get_node(ap->get_root_node()))->get_node(NodePath(track_path));
@@ -96,16 +102,19 @@ void PostImportPluginSkeletonTrackOrganizer::internal_process(InternalImportCate
 						StringName bn = anim->track_get_path(i).get_subname(0);
 						if (bn) {
 							int prof_idx = profile->find_bone(bone_map->find_profile_bone_name(bn));
-							if (remove_unmapped_bones && prof_idx < 0) {
-								remove_indices.push_back(i);
+							if (prof_idx < 0) {
+								unmapped_bone_indices.push_back(i);
 								continue;
 							}
 							if (remove_positions && anim->track_get_type(i) == Animation::TYPE_POSITION_3D && prof_idx >= 0) {
 								StringName prof_bn = profile->get_bone_name(prof_idx);
 								if (prof_bn == profile->get_root_bone() || prof_bn == profile->get_scale_base_bone()) {
+									mapped_bone_indices.push_back(i);
 									continue;
 								}
 								remove_indices.push_back(i);
+							} else {
+								mapped_bone_indices.push_back(i);
 							}
 						}
 					}
@@ -114,11 +123,34 @@ void PostImportPluginSkeletonTrackOrganizer::internal_process(InternalImportCate
 					}
 				}
 
+				if (separate_unmapped_bones == 2 && !unmapped_bone_indices.is_empty()) {
+					Ref<Animation> unmapped_anim = anim->duplicate();
+					Vector<int> to_delete;
+					to_delete.append_array(mapped_bone_indices);
+					to_delete.append_array(remove_indices);
+					to_delete.sort();
+					to_delete.reverse();
+					for (int E : to_delete) {
+						unmapped_anim->remove_track(E);
+					}
+					unmapped_al->add_animation(name, unmapped_anim);
+				}
+
+				if (separate_unmapped_bones >= 1) {
+					remove_indices.append_array(unmapped_bone_indices);
+					remove_indices.sort();
+				}
 				remove_indices.reverse();
 				for (int i = 0; i < remove_indices.size(); i++) {
 					anim->remove_track(remove_indices[i]);
 				}
 			}
+
+			if (unmapped_al->get_animation_list_size() == 0) {
+				unmapped_al.unref();
+			} else if (separate_unmapped_bones == 2) {
+				ap->add_animation_library("unmapped_bones", unmapped_al);
+			}
 		}
 	}
 }
diff --git a/editor/import/3d/resource_importer_scene.cpp b/editor/import/3d/resource_importer_scene.cpp
index cb348f713c..c0175c61a1 100644
--- a/editor/import/3d/resource_importer_scene.cpp
+++ b/editor/import/3d/resource_importer_scene.cpp
@@ -2314,6 +2314,7 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor
 		}
 	}
 
+	// TODO: If there are more than 2 or equal get_internal_option_visibility method, visibility state is broken.
 	for (int i = 0; i < post_importer_plugins.size(); i++) {
 		Variant ret = post_importer_plugins.write[i]->get_internal_option_visibility(EditorScenePostImportPlugin::InternalImportCategory(p_category), _scene_import_type, p_option, p_options);
 		if (ret.get_type() == Variant::BOOL) {
-- 
cgit v1.2.3


From 6ba86c3852dffecb1aaa9dfcbef58e8559bba95e Mon Sep 17 00:00:00 2001
From: passivestar <60579014+passivestar@users.noreply.github.com>
Date: Tue, 19 Nov 2024 08:19:05 +0400
Subject: Disable the debugger thread selector when there's nothing to select

---
 editor/debugger/script_editor_debugger.cpp | 1 +
 1 file changed, 1 insertion(+)

(limited to 'editor')

diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index da59450dd0..416e6f07dd 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -1062,6 +1062,7 @@ void ScriptEditorDebugger::_update_buttons_state() {
 	for (KeyValue<uint64_t, ThreadDebugged> &I : threads_debugged) {
 		threadss.push_back(&I.value);
 	}
+	threads->set_disabled(threadss.is_empty());
 
 	threadss.sort_custom<ThreadSort>();
 	threads->clear();
-- 
cgit v1.2.3


From 0ff5d5fd046bda499648259642c16f677d439c74 Mon Sep 17 00:00:00 2001
From: passivestar <60579014+passivestar@users.noreply.github.com>
Date: Sun, 6 Oct 2024 17:10:05 +0400
Subject: Add theme type variations for secondary Trees and ItemLists

---
 editor/create_dialog.cpp                         | 2 ++
 editor/debugger/editor_performance_profiler.cpp  | 1 +
 editor/debugger/editor_profiler.cpp              | 1 +
 editor/debugger/editor_visual_profiler.cpp       | 1 +
 editor/debugger/script_editor_debugger.cpp       | 2 ++
 editor/editor_asset_installer.cpp                | 1 +
 editor/editor_audio_buses.cpp                    | 1 +
 editor/editor_feature_profile.cpp                | 1 +
 editor/editor_sectioned_inspector.cpp            | 1 +
 editor/export/project_export.cpp                 | 1 +
 editor/filesystem_dock.cpp                       | 1 +
 editor/gui/editor_file_dialog.cpp                | 2 ++
 editor/plugins/script_editor_plugin.cpp          | 3 +++
 editor/plugins/shader_editor_plugin.cpp          | 1 +
 editor/plugins/shader_file_editor_plugin.cpp     | 1 +
 editor/plugins/skeleton_3d_editor_plugin.cpp     | 1 +
 editor/plugins/sprite_frames_editor_plugin.cpp   | 1 +
 editor/plugins/theme_editor_plugin.cpp           | 2 ++
 editor/plugins/tiles/atlas_merging_dialog.cpp    | 1 +
 editor/plugins/tiles/tile_map_layer_editor.cpp   | 2 ++
 editor/plugins/tiles/tile_set_editor.cpp         | 2 ++
 editor/plugins/version_control_editor_plugin.cpp | 1 +
 editor/plugins/visual_shader_editor_plugin.cpp   | 1 +
 editor/themes/editor_theme_manager.cpp           | 4 ++++
 24 files changed, 35 insertions(+)

(limited to 'editor')

diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 2273014f72..c66adb63e8 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -764,6 +764,7 @@ CreateDialog::CreateDialog() {
 	favorites->connect("cell_selected", callable_mp(this, &CreateDialog::_favorite_selected));
 	favorites->connect("item_activated", callable_mp(this, &CreateDialog::_favorite_activated));
 	favorites->add_theme_constant_override("draw_guides", 1);
+	favorites->set_theme_type_variation("TreeSecondary");
 	SET_DRAG_FORWARDING_GCD(favorites, CreateDialog);
 	fav_vb->add_margin_child(TTR("Favorites:"), favorites, true);
 
@@ -779,6 +780,7 @@ CreateDialog::CreateDialog() {
 	recent->connect(SceneStringName(item_selected), callable_mp(this, &CreateDialog::_history_selected));
 	recent->connect("item_activated", callable_mp(this, &CreateDialog::_history_activated));
 	recent->add_theme_constant_override("draw_guides", 1);
+	recent->set_theme_type_variation("ItemListSecondary");
 
 	VBoxContainer *vbc = memnew(VBoxContainer);
 	vbc->set_custom_minimum_size(Size2(300, 0) * EDSCALE);
diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp
index 1ea9a66534..457e60b145 100644
--- a/editor/debugger/editor_performance_profiler.cpp
+++ b/editor/debugger/editor_performance_profiler.cpp
@@ -401,6 +401,7 @@ EditorPerformanceProfiler::EditorPerformanceProfiler() {
 	monitor_tree->connect("item_edited", callable_mp(this, &EditorPerformanceProfiler::_monitor_select));
 	monitor_tree->create_item();
 	monitor_tree->set_hide_root(true);
+	monitor_tree->set_theme_type_variation("TreeSecondary");
 	add_child(monitor_tree);
 
 	monitor_draw = memnew(Control);
diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp
index 33fa208f70..87e5796793 100644
--- a/editor/debugger/editor_profiler.cpp
+++ b/editor/debugger/editor_profiler.cpp
@@ -712,6 +712,7 @@ EditorProfiler::EditorProfiler() {
 	variables->set_column_expand(2, false);
 	variables->set_column_clip_content(2, true);
 	variables->set_column_custom_minimum_width(2, 50 * EDSCALE);
+	variables->set_theme_type_variation("TreeSecondary");
 	variables->connect("item_edited", callable_mp(this, &EditorProfiler::_item_edited));
 
 	graph = memnew(TextureRect);
diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp
index 9a83277e99..0b2304b060 100644
--- a/editor/debugger/editor_visual_profiler.cpp
+++ b/editor/debugger/editor_visual_profiler.cpp
@@ -807,6 +807,7 @@ EditorVisualProfiler::EditorVisualProfiler() {
 	variables->set_column_expand(2, false);
 	variables->set_column_clip_content(2, true);
 	variables->set_column_custom_minimum_width(2, 75 * EDSCALE);
+	variables->set_theme_type_variation("TreeSecondary");
 	variables->connect("cell_selected", callable_mp(this, &EditorVisualProfiler::_item_selected));
 
 	graph = memnew(TextureRect);
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index da59450dd0..2c077e2d4c 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -1921,6 +1921,7 @@ ScriptEditorDebugger::ScriptEditorDebugger() {
 		stack_dump->set_column_title(0, TTR("Stack Frames"));
 		stack_dump->set_hide_root(true);
 		stack_dump->set_v_size_flags(SIZE_EXPAND_FILL);
+		stack_dump->set_theme_type_variation("TreeSecondary");
 		stack_dump->connect("cell_selected", callable_mp(this, &ScriptEditorDebugger::_stack_dump_frame_selected));
 		stack_vb->add_child(stack_dump);
 
@@ -1956,6 +1957,7 @@ ScriptEditorDebugger::ScriptEditorDebugger() {
 		breakpoints_tree->set_allow_reselect(true);
 		breakpoints_tree->set_allow_rmb_select(true);
 		breakpoints_tree->set_hide_root(true);
+		breakpoints_tree->set_theme_type_variation("TreeSecondary");
 		breakpoints_tree->connect("item_mouse_selected", callable_mp(this, &ScriptEditorDebugger::_breakpoints_item_rmb_selected));
 		breakpoints_tree->create_item();
 
diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index 72755e8943..5035900fe8 100644
--- a/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
@@ -735,6 +735,7 @@ EditorAssetInstaller::EditorAssetInstaller() {
 	source_tree->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
 	source_tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 	source_tree->connect("item_edited", callable_mp(this, &EditorAssetInstaller::_item_checked_cbk));
+	source_tree->set_theme_type_variation("TreeSecondary");
 	source_tree_vb->add_child(source_tree);
 
 	VBoxContainer *destination_tree_vb = memnew(VBoxContainer);
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index 0649272216..103a649dc3 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -959,6 +959,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
 	effects->set_allow_rmb_select(true);
 	effects->set_focus_mode(FOCUS_CLICK);
 	effects->set_allow_reselect(true);
+	effects->set_theme_type_variation("TreeSecondary");
 	effects->connect(SceneStringName(gui_input), callable_mp(this, &EditorAudioBus::_effects_gui_input));
 
 	send = memnew(OptionButton);
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index 9cf10c0ecb..9b6c387f18 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -989,6 +989,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
 	class_list->connect("cell_selected", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_selected));
 	class_list->connect("item_edited", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_edited), CONNECT_DEFERRED);
 	class_list->connect("item_collapsed", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_collapsed));
+	class_list->set_theme_type_variation("TreeSecondary");
 	// It will be displayed once the user creates or chooses a profile.
 	class_list_vbc->hide();
 
diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp
index d88cc4d5fa..75eace833e 100644
--- a/editor/editor_sectioned_inspector.cpp
+++ b/editor/editor_sectioned_inspector.cpp
@@ -353,6 +353,7 @@ SectionedInspector::SectionedInspector() :
 	sections->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
 	sections->set_v_size_flags(SIZE_EXPAND_FILL);
 	sections->set_hide_root(true);
+	sections->set_theme_type_variation("TreeSecondary");
 
 	left_vb->add_child(sections, true);
 
diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp
index 8ae4b856a0..df1fa306c8 100644
--- a/editor/export/project_export.cpp
+++ b/editor/export/project_export.cpp
@@ -1411,6 +1411,7 @@ ProjectExportDialog::ProjectExportDialog() {
 	preset_vb->add_child(mc);
 	mc->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 	presets = memnew(ItemList);
+	presets->set_theme_type_variation("ItemListSecondary");
 	presets->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
 	SET_DRAG_FORWARDING_GCD(presets, ProjectExportDialog);
 	mc->add_child(presets);
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index c7e12d1f3b..0de2f5252c 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -4146,6 +4146,7 @@ FileSystemDock::FileSystemDock() {
 	files = memnew(FileSystemList);
 	files->set_v_size_flags(SIZE_EXPAND_FILL);
 	files->set_select_mode(ItemList::SELECT_MULTI);
+	files->set_theme_type_variation("ItemListSecondary");
 	SET_DRAG_FORWARDING_GCD(files, FileSystemDock);
 	files->connect("item_clicked", callable_mp(this, &FileSystemDock::_file_list_item_clicked));
 	files->connect(SceneStringName(gui_input), callable_mp(this, &FileSystemDock::_file_list_gui_input));
diff --git a/editor/gui/editor_file_dialog.cpp b/editor/gui/editor_file_dialog.cpp
index 0381609804..2e86bfb337 100644
--- a/editor/gui/editor_file_dialog.cpp
+++ b/editor/gui/editor_file_dialog.cpp
@@ -2317,6 +2317,7 @@ EditorFileDialog::EditorFileDialog() {
 	favorites->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
 	fav_vb->add_child(favorites);
 	favorites->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+	favorites->set_theme_type_variation("ItemListSecondary");
 	favorites->connect(SceneStringName(item_selected), callable_mp(this, &EditorFileDialog::_favorite_selected));
 
 	VBoxContainer *rec_vb = memnew(VBoxContainer);
@@ -2326,6 +2327,7 @@ EditorFileDialog::EditorFileDialog() {
 	recent = memnew(ItemList);
 	recent->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
 	recent->set_allow_reselect(true);
+	recent->set_theme_type_variation("ItemListSecondary");
 	rec_vb->add_margin_child(TTR("Recent:"), recent, true);
 	recent->connect(SceneStringName(item_selected), callable_mp(this, &EditorFileDialog::_recent_selected));
 
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 49ecbac751..a7c925f74f 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -4154,6 +4154,7 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) {
 	scripts_vbox->add_child(script_list);
 	script_list->set_custom_minimum_size(Size2(100, 60) * EDSCALE); //need to give a bit of limit to avoid it from disappearing
 	script_list->set_v_size_flags(SIZE_EXPAND_FILL);
+	script_list->set_theme_type_variation("ItemListSecondary");
 	script_split->set_split_offset(200 * EDSCALE);
 	_sort_list_on_update = true;
 	script_list->connect("item_clicked", callable_mp(this, &ScriptEditor::_script_list_clicked), CONNECT_DEFERRED);
@@ -4197,6 +4198,7 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) {
 
 	members_overview = memnew(ItemList);
 	members_overview->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
+	members_overview->set_theme_type_variation("ItemListSecondary");
 	overview_vbox->add_child(members_overview);
 
 	members_overview->set_allow_reselect(true);
@@ -4206,6 +4208,7 @@ ScriptEditor::ScriptEditor(WindowWrapper *p_wrapper) {
 
 	help_overview = memnew(ItemList);
 	help_overview->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
+	help_overview->set_theme_type_variation("ItemListSecondary");
 	overview_vbox->add_child(help_overview);
 	help_overview->set_allow_reselect(true);
 	help_overview->set_custom_minimum_size(Size2(0, 60) * EDSCALE); //need to give a bit of limit to avoid it from disappearing
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 5166619f90..3c6d2e8844 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -821,6 +821,7 @@ ShaderEditorPlugin::ShaderEditorPlugin() {
 	shader_list = memnew(ItemList);
 	shader_list->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
 	shader_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+	shader_list->set_theme_type_variation("ItemListSecondary");
 	left_panel->add_child(shader_list);
 	shader_list->connect(SceneStringName(item_selected), callable_mp(this, &ShaderEditorPlugin::_shader_selected));
 	shader_list->connect("item_clicked", callable_mp(this, &ShaderEditorPlugin::_shader_list_clicked));
diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp
index d2fd9b1cc0..25a02d60ef 100644
--- a/editor/plugins/shader_file_editor_plugin.cpp
+++ b/editor/plugins/shader_file_editor_plugin.cpp
@@ -257,6 +257,7 @@ ShaderFileEditor::ShaderFileEditor() {
 	versions->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
 	versions->connect(SceneStringName(item_selected), callable_mp(this, &ShaderFileEditor::_version_selected));
 	versions->set_custom_minimum_size(Size2i(200 * EDSCALE, 0));
+	versions->set_theme_type_variation("TreeSecondary");
 	main_hs->add_child(versions);
 
 	VBoxContainer *main_vb = memnew(VBoxContainer);
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 369a1fc864..1a7c42534a 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -1103,6 +1103,7 @@ void Skeleton3DEditor::create_editors() {
 	joint_tree->set_v_size_flags(SIZE_EXPAND_FILL);
 	joint_tree->set_h_size_flags(SIZE_EXPAND_FILL);
 	joint_tree->set_allow_rmb_select(true);
+	joint_tree->set_theme_type_variation("TreeSecondary");
 	SET_DRAG_FORWARDING_GCD(joint_tree, Skeleton3DEditor);
 	s_con->add_child(joint_tree);
 
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index f29ace1d15..968256d4c9 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -1956,6 +1956,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
 	// HACK: The cell_selected signal is emitted before the FPS spinbox loses focus and applies the change.
 	animations->connect("cell_selected", callable_mp(this, &SpriteFramesEditor::_animation_selected), CONNECT_DEFERRED);
 	animations->connect("item_edited", callable_mp(this, &SpriteFramesEditor::_animation_name_edited));
+	animations->set_theme_type_variation("TreeSecondary");
 	animations->set_allow_reselect(true);
 
 	add_anim->set_shortcut_context(animations);
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index de75ed8c12..3ba3c196ad 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -938,6 +938,7 @@ ThemeItemImportTree::ThemeItemImportTree() {
 	import_items_tree->set_column_custom_minimum_width(IMPORT_ITEM_DATA, 80 * EDSCALE);
 	import_items_tree->set_column_clip_content(1, true);
 	import_items_tree->set_column_clip_content(2, true);
+	import_items_tree->set_theme_type_variation("TreeSecondary");
 
 	ScrollContainer *import_bulk_sc = memnew(ScrollContainer);
 	import_bulk_sc->set_custom_minimum_size(Size2(260.0, 0.0) * EDSCALE);
@@ -1937,6 +1938,7 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito
 	edit_dialog_side_vb->add_child(edit_type_list);
 	edit_type_list->connect(SceneStringName(item_selected), callable_mp(this, &ThemeItemEditorDialog::_edited_type_selected));
 	edit_type_list->connect("button_clicked", callable_mp(this, &ThemeItemEditorDialog::_edited_type_button_pressed));
+	edit_type_list->set_theme_type_variation("TreeSecondary");
 
 	Label *edit_add_type_label = memnew(Label);
 	edit_add_type_label->set_text(TTR("Add Type:"));
diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp
index e25005f996..0322957422 100644
--- a/editor/plugins/tiles/atlas_merging_dialog.cpp
+++ b/editor/plugins/tiles/atlas_merging_dialog.cpp
@@ -318,6 +318,7 @@ AtlasMergingDialog::AtlasMergingDialog() {
 	atlas_merging_atlases_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST_WITH_MIPMAPS);
 	atlas_merging_atlases_list->set_custom_minimum_size(Size2(100, 200));
 	atlas_merging_atlases_list->set_select_mode(ItemList::SELECT_MULTI);
+	atlas_merging_atlases_list->set_theme_type_variation("ItemListSecondary");
 	atlas_merging_atlases_list->connect("multi_selected", callable_mp(this, &AtlasMergingDialog::_update_texture).unbind(2));
 	atlas_merging_h_split_container->add_child(atlas_merging_atlases_list);
 
diff --git a/editor/plugins/tiles/tile_map_layer_editor.cpp b/editor/plugins/tiles/tile_map_layer_editor.cpp
index 16d4ee6f68..52e3784eb4 100644
--- a/editor/plugins/tiles/tile_map_layer_editor.cpp
+++ b/editor/plugins/tiles/tile_map_layer_editor.cpp
@@ -2415,6 +2415,7 @@ TileMapLayerEditorTilesPlugin::TileMapLayerEditorTilesPlugin() {
 	sources_list->set_stretch_ratio(0.25);
 	sources_list->set_custom_minimum_size(Size2(70, 0) * EDSCALE);
 	sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
+	sources_list->set_theme_type_variation("ItemListSecondary");
 	sources_list->connect(SceneStringName(item_selected), callable_mp(this, &TileMapLayerEditorTilesPlugin::_update_source_display).unbind(1));
 	sources_list->connect(SceneStringName(item_selected), callable_mp(TilesEditorUtils::get_singleton(), &TilesEditorUtils::set_sources_lists_current));
 	sources_list->connect("item_activated", callable_mp(TilesEditorUtils::get_singleton(), &TilesEditorUtils::display_tile_set_editor_panel).unbind(1));
@@ -3531,6 +3532,7 @@ TileMapLayerEditorTerrainsPlugin::TileMapLayerEditorTerrainsPlugin() {
 	terrains_tree->set_custom_minimum_size(Size2(70, 0) * EDSCALE);
 	terrains_tree->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
 	terrains_tree->set_hide_root(true);
+	terrains_tree->set_theme_type_variation("ItemListSecondary");
 	terrains_tree->connect(SceneStringName(item_selected), callable_mp(this, &TileMapLayerEditorTerrainsPlugin::_update_tiles_list));
 	tilemap_tab_terrains->add_child(terrains_tree);
 
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index 6f473d1b60..dd64e38370 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -861,6 +861,7 @@ TileSetEditor::TileSetEditor() {
 	sources_list->set_fixed_icon_size(Size2(60, 60) * EDSCALE);
 	sources_list->set_h_size_flags(SIZE_EXPAND_FILL);
 	sources_list->set_v_size_flags(SIZE_EXPAND_FILL);
+	sources_list->set_theme_type_variation("ItemListSecondary");
 	sources_list->connect(SceneStringName(item_selected), callable_mp(this, &TileSetEditor::_source_selected));
 	sources_list->connect(SceneStringName(item_selected), callable_mp(TilesEditorUtils::get_singleton(), &TilesEditorUtils::set_sources_lists_current));
 	sources_list->connect(SceneStringName(visibility_changed), callable_mp(TilesEditorUtils::get_singleton(), &TilesEditorUtils::synchronize_sources_list).bind(sources_list, source_sort_button));
@@ -946,6 +947,7 @@ TileSetEditor::TileSetEditor() {
 	patterns_item_list->set_max_text_lines(2);
 	patterns_item_list->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size));
 	patterns_item_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+	patterns_item_list->set_theme_type_variation("ItemListSecondary");
 	patterns_item_list->connect(SceneStringName(gui_input), callable_mp(this, &TileSetEditor::_patterns_item_list_gui_input));
 	main_vb->add_child(patterns_item_list);
 	patterns_item_list->hide();
diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp
index 815664c608..3a3d25ba9f 100644
--- a/editor/plugins/version_control_editor_plugin.cpp
+++ b/editor/plugins/version_control_editor_plugin.cpp
@@ -1294,6 +1294,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
 	commit_list->set_columns(2); // Commit msg, author
 	commit_list->set_column_custom_minimum_width(0, 40);
 	commit_list->set_column_custom_minimum_width(1, 20);
+	commit_list->set_theme_type_variation("TreeSecondary");
 	commit_list->connect(SceneStringName(item_selected), callable_mp(this, &VersionControlEditorPlugin::_load_diff).bind(commit_list));
 	version_commit_dock->add_child(commit_list);
 
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 8249596045..55118b7ea7 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -6676,6 +6676,7 @@ VisualShaderEditor::VisualShaderEditor() {
 	parameters->set_h_size_flags(SIZE_EXPAND_FILL);
 	parameters->set_v_size_flags(SIZE_EXPAND_FILL);
 	parameters->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
+	parameters->set_theme_type_variation("TreeSecondary");
 	parameters->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_param_selected));
 	parameters->connect("nothing_selected", callable_mp(this, &VisualShaderEditor::_param_unselected));
 	sc->add_child(parameters);
diff --git a/editor/themes/editor_theme_manager.cpp b/editor/themes/editor_theme_manager.cpp
index 32079f3753..617ad24299 100644
--- a/editor/themes/editor_theme_manager.cpp
+++ b/editor/themes/editor_theme_manager.cpp
@@ -2132,6 +2132,10 @@ void EditorThemeManager::_populate_editor_styles(const Ref<EditorTheme> &p_theme
 
 		// EditorValidationPanel.
 		p_theme->set_stylebox(SceneStringName(panel), "EditorValidationPanel", p_config.tree_panel_style);
+
+		// Secondary trees and item lists.
+		p_theme->set_type_variation("TreeSecondary", "Tree");
+		p_theme->set_type_variation("ItemListSecondary", "ItemList");
 	}
 
 	// Editor inspector.
-- 
cgit v1.2.3


From 289e548e3477afe73a509cd3888b0dbb716735cb Mon Sep 17 00:00:00 2001
From: kobewi <kobewi4e@gmail.com>
Date: Fri, 22 Nov 2024 01:09:24 +0100
Subject: Untangle ColorPicker includes

---
 editor/editor_properties.cpp                   | 1 +
 editor/plugins/node_3d_editor_plugin.cpp       | 1 +
 editor/plugins/script_editor_plugin.cpp        | 2 ++
 editor/plugins/script_text_editor.cpp          | 1 +
 editor/plugins/theme_editor_plugin.cpp         | 2 ++
 editor/plugins/theme_editor_preview.cpp        | 6 ++++++
 editor/plugins/visual_shader_editor_plugin.cpp | 1 +
 7 files changed, 14 insertions(+)

(limited to 'editor')

diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 2b2b32eb22..9b3304254b 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -52,6 +52,7 @@
 #include "scene/3d/fog_volume.h"
 #include "scene/3d/gpu_particles_3d.h"
 #include "scene/gui/color_picker.h"
+#include "scene/gui/grid_container.h"
 #include "scene/main/window.h"
 #include "scene/resources/font.h"
 #include "scene/resources/mesh.h"
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 810d1674ca..2e50b7c019 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -92,6 +92,7 @@
 #include "scene/gui/center_container.h"
 #include "scene/gui/color_picker.h"
 #include "scene/gui/flow_container.h"
+#include "scene/gui/separator.h"
 #include "scene/gui/split_container.h"
 #include "scene/gui/subviewport_container.h"
 #include "scene/resources/3d/sky_material.h"
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 49ecbac751..2ed819baf4 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -64,6 +64,8 @@
 #include "editor/themes/editor_scale.h"
 #include "editor/themes/editor_theme_manager.h"
 #include "editor/window_wrapper.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/texture_rect.h"
 #include "scene/main/node.h"
 #include "scene/main/window.h"
 #include "script_text_editor.h"
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index cf586c792e..a28d709b15 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -40,6 +40,7 @@
 #include "editor/editor_string_names.h"
 #include "editor/gui/editor_toaster.h"
 #include "editor/themes/editor_scale.h"
+#include "scene/gui/menu_button.h"
 #include "scene/gui/rich_text_label.h"
 #include "scene/gui/split_container.h"
 
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index de75ed8c12..b5ddf2f48b 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -48,6 +48,8 @@
 #include "scene/gui/option_button.h"
 #include "scene/gui/panel_container.h"
 #include "scene/gui/scroll_container.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/spin_box.h"
 #include "scene/gui/split_container.h"
 #include "scene/gui/tab_bar.h"
 #include "scene/gui/tab_container.h"
diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp
index ea5e8a8ad7..3790b23f76 100644
--- a/editor/plugins/theme_editor_preview.cpp
+++ b/editor/plugins/theme_editor_preview.cpp
@@ -41,9 +41,15 @@
 #include "scene/gui/check_button.h"
 #include "scene/gui/color_picker.h"
 #include "scene/gui/color_rect.h"
+#include "scene/gui/label.h"
 #include "scene/gui/margin_container.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/panel.h"
 #include "scene/gui/progress_bar.h"
 #include "scene/gui/scroll_container.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/spin_box.h"
 #include "scene/gui/tab_container.h"
 #include "scene/gui/text_edit.h"
 #include "scene/gui/tree.h"
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 8249596045..28f2913f0b 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -59,6 +59,7 @@
 #include "scene/gui/rich_text_label.h"
 #include "scene/gui/separator.h"
 #include "scene/gui/split_container.h"
+#include "scene/gui/texture_rect.h"
 #include "scene/gui/tree.h"
 #include "scene/gui/view_panner.h"
 #include "scene/main/window.h"
-- 
cgit v1.2.3


From 74611a74d1ae8af26fd889a6f2c83ba42198c6aa Mon Sep 17 00:00:00 2001
From: Saracen <SaracenOne@gmail.com>
Date: Wed, 4 Sep 2024 00:57:51 +0100
Subject: Generate editor thumbnails on imported scenes.

---
 editor/editor_interface.cpp                  | 156 +++++++++++++++++++++++++++
 editor/editor_interface.h                    |   2 +
 editor/editor_resource_preview.cpp           |  23 +++-
 editor/import/3d/resource_importer_scene.cpp |  11 ++
 editor/import/3d/resource_importer_scene.h   |   1 +
 5 files changed, 192 insertions(+), 1 deletion(-)

(limited to 'editor')

diff --git a/editor/editor_interface.cpp b/editor/editor_interface.cpp
index e85258df50..3cdcc91ae9 100644
--- a/editor/editor_interface.cpp
+++ b/editor/editor_interface.cpp
@@ -31,6 +31,7 @@
 #include "editor_interface.h"
 #include "editor_interface.compat.inc"
 
+#include "core/config/project_settings.h"
 #include "editor/editor_command_palette.h"
 #include "editor/editor_feature_profile.h"
 #include "editor/editor_main_screen.h"
@@ -50,6 +51,10 @@
 #include "editor/property_selector.h"
 #include "editor/themes/editor_scale.h"
 #include "main/main.h"
+#include "plugins/editor_preview_plugins.h"
+#include "scene/3d/light_3d.h"
+#include "scene/3d/mesh_instance_3d.h"
+#include "scene/3d/world_environment.h"
 #include "scene/gui/box_container.h"
 #include "scene/gui/control.h"
 #include "scene/main/window.h"
@@ -98,6 +103,27 @@ EditorUndoRedoManager *EditorInterface::get_editor_undo_redo() const {
 	return EditorUndoRedoManager::get_singleton();
 }
 
+AABB EditorInterface::_calculate_aabb_for_scene(Node *p_node, AABB &p_scene_aabb) {
+	MeshInstance3D *mesh_node = Object::cast_to<MeshInstance3D>(p_node);
+	if (mesh_node && mesh_node->get_mesh().is_valid()) {
+		Transform3D accum_xform;
+		Node3D *base = mesh_node;
+		while (base) {
+			accum_xform = base->get_transform() * accum_xform;
+			base = Object::cast_to<Node3D>(base->get_parent());
+		}
+
+		AABB aabb = accum_xform.xform(mesh_node->get_mesh()->get_aabb());
+		p_scene_aabb.merge_with(aabb);
+	}
+
+	for (int i = 0; i < p_node->get_child_count(); i++) {
+		p_scene_aabb = _calculate_aabb_for_scene(p_node->get_child(i), p_scene_aabb);
+	}
+
+	return p_scene_aabb;
+}
+
 TypedArray<Texture2D> EditorInterface::_make_mesh_previews(const TypedArray<Mesh> &p_meshes, int p_preview_size) {
 	Vector<Ref<Mesh>> meshes;
 
@@ -203,6 +229,136 @@ Vector<Ref<Texture2D>> EditorInterface::make_mesh_previews(const Vector<Ref<Mesh
 	return textures;
 }
 
+void EditorInterface::make_scene_preview(const String &p_path, Node *p_scene, int p_preview_size) {
+	ERR_FAIL_NULL_MSG(p_scene, "The provided scene is null.");
+	ERR_FAIL_COND_MSG(p_scene->is_inside_tree(), "The scene must not be inside the tree.");
+	ERR_FAIL_COND_MSG(!Engine::get_singleton()->is_editor_hint(), "This function can only be called from the editor.");
+
+	SubViewport *sub_viewport_node = memnew(SubViewport);
+	AABB scene_aabb;
+	scene_aabb = _calculate_aabb_for_scene(p_scene, scene_aabb);
+
+	sub_viewport_node->set_update_mode(SubViewport::UPDATE_ALWAYS);
+	sub_viewport_node->set_size(Vector2i(p_preview_size, p_preview_size));
+	sub_viewport_node->set_transparent_background(false);
+	Ref<World3D> world;
+	world.instantiate();
+	sub_viewport_node->set_world_3d(world);
+
+	EditorNode::get_singleton()->add_child(sub_viewport_node);
+	Ref<Environment> env;
+	env.instantiate();
+	env->set_background(Environment::BG_CLEAR_COLOR);
+
+	Ref<CameraAttributesPractical> camera_attributes;
+	camera_attributes.instantiate();
+
+	Node3D *root = memnew(Node3D);
+	root->set_name("Root");
+	sub_viewport_node->add_child(root);
+
+	Camera3D *camera = memnew(Camera3D);
+	camera->set_environment(env);
+	camera->set_attributes(camera_attributes);
+	camera->set_name("Camera3D");
+	root->add_child(camera);
+	camera->set_current(true);
+
+	camera->set_position(Vector3(0.0, 0.0, 3.0));
+
+	DirectionalLight3D *light = memnew(DirectionalLight3D);
+	light->set_name("Light");
+	DirectionalLight3D *light2 = memnew(DirectionalLight3D);
+	light2->set_name("Light2");
+	light2->set_color(Color(0.7, 0.7, 0.7, 1.0));
+
+	root->add_child(light);
+	root->add_child(light2);
+
+	sub_viewport_node->add_child(p_scene);
+
+	// Calculate the camera and lighting position based on the size of the scene.
+	Vector3 center = scene_aabb.get_center();
+	float camera_size = scene_aabb.get_longest_axis_size();
+
+	const float cam_rot_x = -Math_PI / 4;
+	const float cam_rot_y = -Math_PI / 4;
+
+	camera->set_orthogonal(camera_size * 2.0, 0.0001, camera_size * 2.0);
+
+	Transform3D xf;
+	xf.basis = Basis(Vector3(0, 1, 0), cam_rot_y) * Basis(Vector3(1, 0, 0), cam_rot_x);
+	xf.origin = center;
+	xf.translate_local(0, 0, camera_size);
+
+	camera->set_transform(xf);
+
+	Transform3D xform;
+	xform.basis = Basis().rotated(Vector3(0, 1, 0), -Math_PI / 6);
+	xform.basis = Basis().rotated(Vector3(1, 0, 0), Math_PI / 6) * xform.basis;
+
+	light->set_transform(xform * Transform3D().looking_at(Vector3(-2, -1, -1), Vector3(0, 1, 0)));
+	light2->set_transform(xform * Transform3D().looking_at(Vector3(+1, -1, -2), Vector3(0, 1, 0)));
+
+	// Update the renderer to get the screenshot.
+	DisplayServer::get_singleton()->process_events();
+	Main::iteration();
+	Main::iteration();
+
+	// Get the texture.
+	Ref<Texture2D> texture = sub_viewport_node->get_texture();
+	ERR_FAIL_COND_MSG(texture.is_null(), "Failed to get texture from sub_viewport_node.");
+
+	// Remove the initial scene node.
+	sub_viewport_node->remove_child(p_scene);
+
+	// Cleanup the viewport.
+	if (sub_viewport_node) {
+		if (sub_viewport_node->get_parent()) {
+			sub_viewport_node->get_parent()->remove_child(sub_viewport_node);
+		}
+		sub_viewport_node->queue_free();
+		sub_viewport_node = nullptr;
+	}
+
+	// Now generate the cache image.
+	Ref<Image> img = texture->get_image();
+	if (img.is_valid() && img->get_width() > 0 && img->get_height() > 0) {
+		img = img->duplicate();
+
+		int preview_size = EDITOR_GET("filesystem/file_dialog/thumbnail_size");
+		preview_size *= EDSCALE;
+
+		int vp_size = MIN(img->get_width(), img->get_height());
+		int x = (img->get_width() - vp_size) / 2;
+		int y = (img->get_height() - vp_size) / 2;
+
+		if (vp_size < preview_size) {
+			img->crop_from_point(x, y, vp_size, vp_size);
+		} else {
+			int ratio = vp_size / preview_size;
+			int size = preview_size * MAX(1, ratio / 2);
+
+			x = (img->get_width() - size) / 2;
+			y = (img->get_height() - size) / 2;
+
+			img->crop_from_point(x, y, size, size);
+			img->resize(preview_size, preview_size, Image::INTERPOLATE_LANCZOS);
+		}
+		img->convert(Image::FORMAT_RGB8);
+
+		String temp_path = EditorPaths::get_singleton()->get_cache_dir();
+		String cache_base = ProjectSettings::get_singleton()->globalize_path(p_path).md5_text();
+		cache_base = temp_path.path_join("resthumb-" + cache_base);
+
+		post_process_preview(img);
+		img->save_png(cache_base + ".png");
+	}
+
+	EditorResourcePreview::get_singleton()->check_for_invalidation(p_path);
+	EditorFileSystem::get_singleton()->emit_signal(SNAME("filesystem_changed"));
+}
+
 void EditorInterface::set_plugin_enabled(const String &p_plugin, bool p_enabled) {
 	EditorNode::get_singleton()->set_addon_plugin_enabled(p_plugin, p_enabled, true);
 }
diff --git a/editor/editor_interface.h b/editor/editor_interface.h
index 2ae77331b1..92d9812003 100644
--- a/editor/editor_interface.h
+++ b/editor/editor_interface.h
@@ -79,6 +79,7 @@ class EditorInterface : public Object {
 	// Editor tools.
 
 	TypedArray<Texture2D> _make_mesh_previews(const TypedArray<Mesh> &p_meshes, int p_preview_size);
+	AABB _calculate_aabb_for_scene(Node *p_node, AABB &p_scene_aabb);
 
 protected:
 	static void _bind_methods();
@@ -107,6 +108,7 @@ public:
 	EditorUndoRedoManager *get_editor_undo_redo() const;
 
 	Vector<Ref<Texture2D>> make_mesh_previews(const Vector<Ref<Mesh>> &p_meshes, Vector<Transform3D> *p_transforms, int p_preview_size);
+	void make_scene_preview(const String &p_path, Node *p_scene, int p_preview_size);
 
 	void set_plugin_enabled(const String &p_plugin, bool p_enabled);
 	bool is_plugin_enabled(const String &p_plugin) const;
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index 4dca3b33af..32c44133e0 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -147,6 +147,10 @@ void EditorResourcePreview::_preview_ready(const String &p_path, int p_hash, con
 
 		if (!p_path.begins_with("ID:")) {
 			modified_time = FileAccess::get_modified_time(p_path);
+			String import_path = p_path + ".import";
+			if (FileAccess::exists(import_path)) {
+				modified_time = MAX(modified_time, FileAccess::get_modified_time(import_path));
+			}
 		}
 
 		Item item;
@@ -237,7 +241,14 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<
 			}
 			Ref<FileAccess> f = FileAccess::open(cache_base + ".txt", FileAccess::WRITE);
 			ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + cache_base + ".txt'. Check user write permissions.");
-			_write_preview_cache(f, thumbnail_size, has_small_texture, FileAccess::get_modified_time(p_item.path), FileAccess::get_md5(p_item.path), p_metadata);
+
+			uint64_t modtime = FileAccess::get_modified_time(p_item.path);
+			String import_path = p_item.path + ".import";
+			if (FileAccess::exists(import_path)) {
+				modtime = MAX(modtime, FileAccess::get_modified_time(import_path));
+			}
+
+			_write_preview_cache(f, thumbnail_size, has_small_texture, modtime, FileAccess::get_md5(p_item.path), p_metadata);
 		}
 	}
 
@@ -298,6 +309,11 @@ void EditorResourcePreview::_iterate() {
 		_generate_preview(texture, small_texture, item, cache_base, preview_metadata);
 	} else {
 		uint64_t modtime = FileAccess::get_modified_time(item.path);
+		String import_path = item.path + ".import";
+		if (FileAccess::exists(import_path)) {
+			modtime = MAX(modtime, FileAccess::get_modified_time(import_path));
+		}
+
 		int tsize;
 		bool has_small_texture;
 		uint64_t last_modtime;
@@ -513,6 +529,11 @@ void EditorResourcePreview::check_for_invalidation(const String &p_path) {
 
 		if (cache.has(p_path)) {
 			uint64_t modified_time = FileAccess::get_modified_time(p_path);
+			String import_path = p_path + ".import";
+			if (FileAccess::exists(import_path)) {
+				modified_time = MAX(modified_time, FileAccess::get_modified_time(import_path));
+			}
+
 			if (modified_time != cache[p_path].modified_time) {
 				cache.erase(p_path);
 				call_invalidated = true;
diff --git a/editor/import/3d/resource_importer_scene.cpp b/editor/import/3d/resource_importer_scene.cpp
index 86af9caf26..6c45d89125 100644
--- a/editor/import/3d/resource_importer_scene.cpp
+++ b/editor/import/3d/resource_importer_scene.cpp
@@ -34,6 +34,7 @@
 #include "core/io/dir_access.h"
 #include "core/io/resource_saver.h"
 #include "core/object/script_language.h"
+#include "editor/editor_interface.h"
 #include "editor/editor_node.h"
 #include "editor/editor_settings.h"
 #include "editor/import/3d/scene_import_settings.h"
@@ -2814,6 +2815,15 @@ void ResourceImporterScene::_optimize_track_usage(AnimationPlayer *p_player, Ani
 	}
 }
 
+void ResourceImporterScene::_generate_editor_preview_for_scene(const String &p_path, Node *p_scene) {
+	if (!Engine::get_singleton()->is_editor_hint()) {
+		return;
+	}
+	ERR_FAIL_COND_MSG(p_path.is_empty(), "Path is empty, cannot generate preview.");
+	ERR_FAIL_NULL_MSG(p_scene, "Scene is null, cannot generate preview.");
+	EditorInterface::get_singleton()->make_scene_preview(p_path, p_scene, 1024);
+}
+
 Node *ResourceImporterScene::pre_import(const String &p_source_file, const HashMap<StringName, Variant> &p_options) {
 	Ref<EditorSceneFormatImporter> importer;
 	String ext = p_source_file.get_extension().to_lower();
@@ -3164,6 +3174,7 @@ Error ResourceImporterScene::import(ResourceUID::ID p_source_id, const String &p
 		print_verbose("Saving scene to: " + p_save_path + ".scn");
 		err = ResourceSaver::save(packer, p_save_path + ".scn", flags); //do not take over, let the changed files reload themselves
 		ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save scene to file '" + p_save_path + ".scn'.");
+		_generate_editor_preview_for_scene(p_source_file, scene);
 	} else {
 		ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unknown scene import type: " + _scene_import_type);
 	}
diff --git a/editor/import/3d/resource_importer_scene.h b/editor/import/3d/resource_importer_scene.h
index b2f5fab0eb..6868baf023 100644
--- a/editor/import/3d/resource_importer_scene.h
+++ b/editor/import/3d/resource_importer_scene.h
@@ -236,6 +236,7 @@ class ResourceImporterScene : public ResourceImporter {
 	};
 
 	void _optimize_track_usage(AnimationPlayer *p_player, AnimationImportTracks *p_track_actions);
+	void _generate_editor_preview_for_scene(const String &p_path, Node *p_scene);
 
 	String _scene_import_type = "PackedScene";
 
-- 
cgit v1.2.3


From 0fc082e1ee3af5bb6a4b52f85756d24dc02b230f Mon Sep 17 00:00:00 2001
From: Jamie Greunbaum <jamie.greunbaum@battybovine.com>
Date: Tue, 2 Apr 2024 03:26:10 -0400
Subject: Add CollisionShape3D custom debug colours

This allows changing the display colour of a CollisionShape3D node on a per-shape basis.
It also adds the ability to display a solid coloured preview of a CollisionShape3D.

Closes https://github.com/godotengine/godot-proposals/issues/906
---
 .../gizmos/collision_shape_3d_gizmo_plugin.cpp     | 75 +++++++++++++++++-----
 .../gizmos/collision_shape_3d_gizmo_plugin.h       |  2 +
 editor/plugins/node_3d_editor_gizmos.cpp           |  7 +-
 3 files changed, 62 insertions(+), 22 deletions(-)

(limited to 'editor')

diff --git a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp
index 573c686d57..b92abbcf79 100644
--- a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp
@@ -49,17 +49,47 @@
 
 CollisionShape3DGizmoPlugin::CollisionShape3DGizmoPlugin() {
 	helper.instantiate();
-	const Color gizmo_color = SceneTree::get_singleton()->get_debug_collisions_color();
-	create_material("shape_material", gizmo_color);
-	const float gizmo_value = gizmo_color.get_v();
-	const Color gizmo_color_disabled = Color(gizmo_value, gizmo_value, gizmo_value, 0.65);
-	create_material("shape_material_disabled", gizmo_color_disabled);
+
+	create_collision_material("shape_material", 2.0);
+	create_collision_material("shape_material_arraymesh", 0.0625);
+
+	create_collision_material("shape_material_disabled", 0.0625);
+	create_collision_material("shape_material_arraymesh_disabled", 0.015625);
+
 	create_handle_material("handles");
 }
 
 CollisionShape3DGizmoPlugin::~CollisionShape3DGizmoPlugin() {
 }
 
+void CollisionShape3DGizmoPlugin::create_collision_material(const String &p_name, float p_alpha) {
+	Vector<Ref<StandardMaterial3D>> mats;
+
+	const Color collision_color(1.0, 1.0, 1.0, p_alpha);
+
+	for (int i = 0; i < 4; i++) {
+		bool instantiated = i < 2;
+
+		Ref<StandardMaterial3D> material = memnew(StandardMaterial3D);
+
+		Color color = collision_color;
+		color.a *= instantiated ? 0.25 : 1.0;
+
+		material->set_albedo(color);
+		material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+		material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
+		material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MIN + 1);
+		material->set_cull_mode(StandardMaterial3D::CULL_BACK);
+		material->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true);
+		material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+		material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
+
+		mats.push_back(material);
+	}
+
+	materials[p_name] = mats;
+}
+
 bool CollisionShape3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
 	return Object::cast_to<CollisionShape3D>(p_spatial) != nullptr;
 }
@@ -311,9 +341,20 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 		return;
 	}
 
-	const Ref<Material> material =
+	const Ref<StandardMaterial3D> material =
 			get_material(!cs->is_disabled() ? "shape_material" : "shape_material_disabled", p_gizmo);
-	Ref<Material> handles_material = get_material("handles");
+	const Ref<StandardMaterial3D> material_arraymesh =
+			get_material(!cs->is_disabled() ? "shape_material_arraymesh" : "shape_material_arraymesh_disabled", p_gizmo);
+	const Ref<Material> handles_material = get_material("handles");
+
+	const Color collision_color = cs->is_disabled() ? Color(1.0, 1.0, 1.0, 0.75) : cs->get_debug_color();
+
+	if (cs->get_debug_fill_enabled()) {
+		Ref<ArrayMesh> array_mesh = s->get_debug_arraymesh_faces(collision_color);
+		if (array_mesh.is_valid()) {
+			p_gizmo->add_mesh(array_mesh, material_arraymesh);
+		}
+	}
 
 	if (Object::cast_to<SphereShape3D>(*s)) {
 		Ref<SphereShape3D> sp = s;
@@ -351,7 +392,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 			collision_segments.push_back(Vector3(b.x, b.y, 0));
 		}
 
-		p_gizmo->add_lines(points, material);
+		p_gizmo->add_lines(points, material, false, collision_color);
 		p_gizmo->add_collision_segments(collision_segments);
 		Vector<Vector3> handles;
 		handles.push_back(Vector3(r, 0, 0));
@@ -374,7 +415,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 
 		const Vector<Vector3> handles = helper->box_get_handles(bs->get_size());
 
-		p_gizmo->add_lines(lines, material);
+		p_gizmo->add_lines(lines, material, false, collision_color);
 		p_gizmo->add_collision_segments(lines);
 		p_gizmo->add_handles(handles, handles_material);
 	}
@@ -412,7 +453,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 			points.push_back(Vector3(b.y, b.x, 0) + dud);
 		}
 
-		p_gizmo->add_lines(points, material);
+		p_gizmo->add_lines(points, material, false, collision_color);
 
 		Vector<Vector3> collision_segments;
 
@@ -476,7 +517,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 			}
 		}
 
-		p_gizmo->add_lines(points, material);
+		p_gizmo->add_lines(points, material, false, collision_color);
 
 		Vector<Vector3> collision_segments;
 
@@ -531,7 +572,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 			p.normal * p.d + p.normal * 3
 		};
 
-		p_gizmo->add_lines(points, material);
+		p_gizmo->add_lines(points, material, false, collision_color);
 		p_gizmo->add_collision_segments(points);
 	}
 
@@ -549,7 +590,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 					lines.write[i * 2 + 0] = md.vertices[md.edges[i].vertex_a];
 					lines.write[i * 2 + 1] = md.vertices[md.edges[i].vertex_b];
 				}
-				p_gizmo->add_lines(lines, material);
+				p_gizmo->add_lines(lines, material, false, collision_color);
 				p_gizmo->add_collision_segments(lines);
 			}
 		}
@@ -558,7 +599,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 	if (Object::cast_to<ConcavePolygonShape3D>(*s)) {
 		Ref<ConcavePolygonShape3D> cs2 = s;
 		Ref<ArrayMesh> mesh = cs2->get_debug_mesh();
-		p_gizmo->add_mesh(mesh, material);
+		p_gizmo->add_lines(cs2->get_debug_mesh_lines(), material, false, collision_color);
 		p_gizmo->add_collision_segments(cs2->get_debug_mesh_lines());
 	}
 
@@ -569,7 +610,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 			Vector3(),
 			Vector3(0, 0, rs->get_length())
 		};
-		p_gizmo->add_lines(points, material);
+		p_gizmo->add_lines(points, material, false, collision_color);
 		p_gizmo->add_collision_segments(points);
 		Vector<Vector3> handles;
 		handles.push_back(Vector3(0, 0, rs->get_length()));
@@ -579,7 +620,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 	if (Object::cast_to<HeightMapShape3D>(*s)) {
 		Ref<HeightMapShape3D> hms = s;
 
-		Ref<ArrayMesh> mesh = hms->get_debug_mesh();
-		p_gizmo->add_mesh(mesh, material);
+		Vector<Vector3> lines = hms->get_debug_mesh_lines();
+		p_gizmo->add_lines(lines, material, false, collision_color);
 	}
 }
diff --git a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.h b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.h
index 464012acf9..09590fba58 100644
--- a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.h
+++ b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.h
@@ -38,6 +38,8 @@ class Gizmo3DHelper;
 class CollisionShape3DGizmoPlugin : public EditorNode3DGizmoPlugin {
 	GDCLASS(CollisionShape3DGizmoPlugin, EditorNode3DGizmoPlugin);
 
+	void create_collision_material(const String &p_name, float p_alpha);
+
 	Ref<Gizmo3DHelper> helper;
 
 public:
diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index 8aff3c9aec..b716e925cb 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -292,14 +292,11 @@ void EditorNode3DGizmo::add_vertices(const Vector<Vector3> &p_vertices, const Re
 
 	Vector<Color> color;
 	color.resize(p_vertices.size());
+	const Color vertex_color = (is_selected() ? Color(1, 1, 1, 0.8) : Color(1, 1, 1, 0.2)) * p_modulate;
 	{
 		Color *w = color.ptrw();
 		for (int i = 0; i < p_vertices.size(); i++) {
-			if (is_selected()) {
-				w[i] = Color(1, 1, 1, 0.8) * p_modulate;
-			} else {
-				w[i] = Color(1, 1, 1, 0.2) * p_modulate;
-			}
+			w[i] = vertex_color;
 		}
 	}
 
-- 
cgit v1.2.3


From 612981c1ea7d1beb927b53a2e4056827ed6ca32a Mon Sep 17 00:00:00 2001
From: smix8 <52464204+smix8@users.noreply.github.com>
Date: Mon, 27 Nov 2023 19:37:52 +0100
Subject: Add ShadowCastingSetting to MeshLibrary / GridMap items

Adds ShadowCastingSetting to MeshLibrary / GridMap items.
---
 editor/plugins/mesh_library_editor_plugin.cpp | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

(limited to 'editor')

diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp
index 6f79ab0529..39401e2738 100644
--- a/editor/plugins/mesh_library_editor_plugin.cpp
+++ b/editor/plugins/mesh_library_editor_plugin.cpp
@@ -156,6 +156,25 @@ void MeshLibraryEditor::_import_scene_parse_node(Ref<MeshLibrary> p_library, Has
 	}
 	p_library->set_item_mesh(item_id, item_mesh);
 
+	GeometryInstance3D::ShadowCastingSetting gi3d_cast_shadows_setting = mesh_instance_node->get_cast_shadows_setting();
+	switch (gi3d_cast_shadows_setting) {
+		case GeometryInstance3D::ShadowCastingSetting::SHADOW_CASTING_SETTING_OFF: {
+			p_library->set_item_mesh_cast_shadow(item_id, RS::ShadowCastingSetting::SHADOW_CASTING_SETTING_OFF);
+		} break;
+		case GeometryInstance3D::ShadowCastingSetting::SHADOW_CASTING_SETTING_ON: {
+			p_library->set_item_mesh_cast_shadow(item_id, RS::ShadowCastingSetting::SHADOW_CASTING_SETTING_ON);
+		} break;
+		case GeometryInstance3D::ShadowCastingSetting::SHADOW_CASTING_SETTING_DOUBLE_SIDED: {
+			p_library->set_item_mesh_cast_shadow(item_id, RS::ShadowCastingSetting::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
+		} break;
+		case GeometryInstance3D::ShadowCastingSetting::SHADOW_CASTING_SETTING_SHADOWS_ONLY: {
+			p_library->set_item_mesh_cast_shadow(item_id, RS::ShadowCastingSetting::SHADOW_CASTING_SETTING_SHADOWS_ONLY);
+		} break;
+		default: {
+			p_library->set_item_mesh_cast_shadow(item_id, RS::ShadowCastingSetting::SHADOW_CASTING_SETTING_ON);
+		} break;
+	}
+
 	Transform3D item_mesh_transform;
 	if (p_apply_xforms) {
 		item_mesh_transform = mesh_instance_node->get_transform();
-- 
cgit v1.2.3