From 3518b0dc5a53a5426a1c34d9cd4a73c7ecd62510 Mon Sep 17 00:00:00 2001
From: Robert Yevdokimov <105675984+ryevdokimov@users.noreply.github.com>
Date: Wed, 7 Jan 2026 20:59:25 -0500
Subject: [PATCH] Keep other parts of transform gizmo visible when rotating in
local mode
---
doc/classes/EditorSettings.xml | 3 ++
editor/scene/3d/node_3d_editor_plugin.cpp | 37 ++++++++++++++++++++---
editor/scene/3d/node_3d_editor_plugin.h | 4 +++
editor/settings/editor_settings.cpp | 3 +-
4 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml
index e577c05144..f7f598f101 100644
--- a/doc/classes/EditorSettings.xml
+++ b/doc/classes/EditorSettings.xml
@@ -503,6 +503,9 @@
The color to use for the selection box that surrounds selected nodes in the 3D editor viewport. The color's alpha channel influences the selection box's opacity.
+
+ If checked, the transform gizmo remains visible during rotation in that transform mode.
+
The color to use for the AABB gizmo that displays the [GeometryInstance3D]'s custom [AABB].
diff --git a/editor/scene/3d/node_3d_editor_plugin.cpp b/editor/scene/3d/node_3d_editor_plugin.cpp
index 6611dbcd19..29c91368d5 100644
--- a/editor/scene/3d/node_3d_editor_plugin.cpp
+++ b/editor/scene/3d/node_3d_editor_plugin.cpp
@@ -4602,9 +4602,34 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
return;
}
- bool hide_during_rotation = _is_rotation_arc_visible();
+ bool local_coords = spatial_editor->are_local_coords_enabled();
+ bool arc_visible = _is_rotation_arc_visible();
+ int show_gizmo_flags = EDITOR_GET("editors/3d/show_gizmo_during_rotation");
- bool show_gizmo = spatial_editor->is_gizmo_visible() && !_edit.instant && transform_gizmo_visible && !collision_reposition && !hide_during_rotation;
+ bool keep_gizmo_visible = arc_visible && ((local_coords && (show_gizmo_flags & Node3DEditor::TRANSFORM_MODE_LOCAL)) || (!local_coords && (show_gizmo_flags & Node3DEditor::TRANSFORM_MODE_GLOBAL)));
+ bool hide_gizmo_during_rotation = arc_visible && !keep_gizmo_visible;
+
+ int arc_replaces_ring = -1;
+ if (keep_gizmo_visible) {
+ switch (_edit.plane) {
+ case TRANSFORM_X_AXIS:
+ arc_replaces_ring = 0;
+ break;
+ case TRANSFORM_Y_AXIS:
+ arc_replaces_ring = 1;
+ break;
+ case TRANSFORM_Z_AXIS:
+ arc_replaces_ring = 2;
+ break;
+ case TRANSFORM_VIEW:
+ arc_replaces_ring = 3;
+ break;
+ default:
+ break;
+ }
+ }
+
+ bool show_gizmo = spatial_editor->is_gizmo_visible() && !_edit.instant && transform_gizmo_visible && !collision_reposition && !hide_gizmo_during_rotation;
bool show_rotate_gizmo = show_gizmo && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_TRANSFORM || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE);
for (int i = 0; i < 3; i++) {
@@ -4619,7 +4644,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
RenderingServer::get_singleton()->instance_set_transform(move_plane_gizmo_instance[i], axis_angle);
RenderingServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], show_gizmo && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_TRANSFORM || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE));
RenderingServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], axis_angle);
- RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], show_rotate_gizmo);
+ RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], show_rotate_gizmo && i != arc_replaces_ring);
RenderingServer::get_singleton()->instance_set_transform(scale_gizmo_instance[i], axis_angle);
RenderingServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], show_gizmo && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE));
RenderingServer::get_singleton()->instance_set_transform(scale_plane_gizmo_instance[i], axis_angle);
@@ -4629,9 +4654,11 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
Transform3D view_rotation_xform = xform;
view_rotation_xform.orthonormalize();
- view_rotation_xform.basis.scale(scale);
+ bool shrink_view_ring = arc_replaces_ring >= 0 && arc_replaces_ring < 3;
+ Vector3 view_ring_scale = shrink_view_ring ? scale * (GIZMO_CIRCLE_SIZE / GIZMO_VIEW_ROTATION_SIZE) : scale;
+ view_rotation_xform.basis.scale(view_ring_scale);
RenderingServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[3], view_rotation_xform);
- RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[3], show_rotate_gizmo);
+ RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[3], show_rotate_gizmo && arc_replaces_ring != 3);
bool show_axes = spatial_editor->is_gizmo_visible() && _edit.mode != TRANSFORM_NONE;
RenderingServer *rs = RenderingServer::get_singleton();
diff --git a/editor/scene/3d/node_3d_editor_plugin.h b/editor/scene/3d/node_3d_editor_plugin.h
index 7a1db01d52..de5f2a9842 100644
--- a/editor/scene/3d/node_3d_editor_plugin.h
+++ b/editor/scene/3d/node_3d_editor_plugin.h
@@ -677,7 +677,11 @@ public:
TOOL_OPT_LOCAL_COORDS,
TOOL_OPT_USE_SNAP,
TOOL_OPT_MAX
+ };
+ enum TransformMode {
+ TRANSFORM_MODE_GLOBAL = 1,
+ TRANSFORM_MODE_LOCAL = 2,
};
private:
diff --git a/editor/settings/editor_settings.cpp b/editor/settings/editor_settings.cpp
index 158df9dd9a..0412cdaebc 100644
--- a/editor/settings/editor_settings.cpp
+++ b/editor/settings/editor_settings.cpp
@@ -964,7 +964,8 @@ void EditorSettings::_load_defaults(Ref p_extra_config) {
// 3D: Manipulator
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "editors/3d/manipulator_gizmo_size", 80, "16,160,1");
- EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/manipulator_gizmo_opacity", 0.9, "0,1,0.01")
+ EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/3d/manipulator_gizmo_opacity", 0.9, "0,1,0.01");
+ EDITOR_SETTING(Variant::INT, PROPERTY_HINT_FLAGS, "editors/3d/show_gizmo_during_rotation", 2, "Global,Local");
// 2D
_initial_set("editors/2d/grid_color", Color(1.0, 1.0, 1.0, 0.07), true);