From d613138aa4f0463635189da4549913a09a8f43a7 Mon Sep 17 00:00:00 2001 From: Robert Yevdokimov <105675984+ryevdokimov@users.noreply.github.com> Date: Sun, 8 Feb 2026 18:52:08 -0500 Subject: [PATCH] Fix gizmo rotation arc and applied transform not being in sync --- editor/scene/3d/node_3d_editor_plugin.cpp | 55 ++++++++++++----------- editor/scene/3d/node_3d_editor_plugin.h | 2 +- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/editor/scene/3d/node_3d_editor_plugin.cpp b/editor/scene/3d/node_3d_editor_plugin.cpp index d652cdb0da..c98bddd504 100644 --- a/editor/scene/3d/node_3d_editor_plugin.cpp +++ b/editor/scene/3d/node_3d_editor_plugin.cpp @@ -1478,6 +1478,7 @@ bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, b _compute_edit(p_screenpos); _edit.plane = TRANSFORM_VIEW; _edit.accumulated_rotation_angle = 0.0; + _edit.rotation_angle = 0.0; _edit.rotation_axis = _get_camera_normal(); _edit.view_axis_local = spatial_editor->get_gizmo_transform().basis.xform_inv(_get_camera_normal()).normalized(); _edit.gizmo_initiated = true; @@ -1493,6 +1494,7 @@ bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, b _edit.is_trackball = true; _edit.show_rotation_line = false; _edit.accumulated_rotation_angle = 0.0; + _edit.rotation_angle = 0.0; _edit.rotation_axis = _get_camera_normal(); _edit.gizmo_initiated = true; spatial_editor->select_gizmo_highlight_axis(-1); @@ -1507,6 +1509,7 @@ bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, b _compute_edit(p_screenpos); _edit.plane = TransformPlane(TRANSFORM_X_AXIS + col_axis); _edit.accumulated_rotation_angle = 0.0; + _edit.rotation_angle = 0.0; _edit.rotation_axis = gt.basis.get_column(col_axis).normalized(); _edit.gizmo_initiated = true; } @@ -2752,7 +2755,7 @@ void Node3DEditorViewport::_sinput(const Ref &p_event) { _edit.initial_click_vector = Vector3(); _edit.previous_rotation_vector = Vector3(); _edit.accumulated_rotation_angle = 0.0; - _edit.display_rotation_angle = 0.0; + _edit.rotation_angle = 0.0; set_message(vformat(TTR("Rotating %s degrees."), String::num(0, 0))); } surface->queue_redraw(); @@ -3833,7 +3836,7 @@ void Node3DEditorViewport::_draw() { } const int segments = 64; - float display_angle = _edit.display_rotation_angle; + float display_angle = _edit.rotation_angle; float abs_angle = Math::abs(display_angle); if (abs_angle > Math::TAU) { @@ -3861,12 +3864,11 @@ void Node3DEditorViewport::_draw() { Vector3 point1_3d = _edit.center + gizmo_scale * rotation_radius * (right * Math::cos(angle1) + forward * Math::sin(angle1)); Vector3 point2_3d = _edit.center + gizmo_scale * rotation_radius * (right * Math::cos(angle2) + forward * Math::sin(angle2)); - Point2 center_2d = center; Point2 point1_2d = point_to_screen(point1_3d); Point2 point2_2d = point_to_screen(point2_3d); Vector triangle_points; - triangle_points.push_back(center_2d); + triangle_points.push_back(center); triangle_points.push_back(point1_2d); triangle_points.push_back(point2_2d); @@ -5679,7 +5681,7 @@ void Node3DEditorViewport::begin_transform(TransformMode p_mode, bool instant) { _edit.initial_click_vector = Vector3(); _edit.previous_rotation_vector = Vector3(); _edit.accumulated_rotation_angle = 0.0; - _edit.display_rotation_angle = 0.0; + _edit.rotation_angle = 0.0; _edit.gizmo_initiated = false; switch (p_mode) { case TRANSFORM_ROTATE: @@ -6039,25 +6041,12 @@ void Node3DEditorViewport::update_transform(bool p_shift) { } _edit.previous_rotation_vector = current_rotation_vector; _edit.accumulated_rotation_angle = 0.0; - _edit.display_rotation_angle = 0.0; + _edit.rotation_angle = 0.0; } static const float orthogonal_threshold = Math::cos(Math::deg_to_rad(85.0f)); bool axis_is_orthogonal = Math::abs(plane.normal.dot(global_axis)) < orthogonal_threshold; - double angle = 0.0f; - if (axis_is_orthogonal) { - _edit.show_rotation_line = false; - Vector3 projection_axis = plane.normal.cross(global_axis); - Vector3 delta = intersection - click; - float projection = delta.dot(projection_axis); - angle = (projection * (Math::PI / 2.0f)) / (gizmo_scale * GIZMO_CIRCLE_SIZE); - } else { - _edit.show_rotation_line = true; - Vector3 click_axis = (click - _edit.center).normalized(); - angle = click_axis.signed_angle_to(current_rotation_vector, global_axis); - } - if (_edit.previous_rotation_vector != Vector3()) { double delta_angle = _edit.previous_rotation_vector.signed_angle_to(current_rotation_vector, global_axis); _edit.accumulated_rotation_angle += delta_angle; @@ -6067,16 +6056,28 @@ void Node3DEditorViewport::update_transform(bool p_shift) { bool snapping = _edit.snap || spatial_editor->is_snap_enabled(); if (snapping) { snap = spatial_editor->get_rotate_snap(); - _edit.display_rotation_angle = Math::deg_to_rad(Math::snapped(Math::rad_to_deg(_edit.accumulated_rotation_angle), snap)); - } else { - _edit.display_rotation_angle = _edit.accumulated_rotation_angle; + snap_step_decimals = Math::range_step_decimals(snap); } - angle = Math::snapped(Math::rad_to_deg(angle), snap); - set_message(vformat(TTR("Rotating %s degrees."), String::num(angle, snap_step_decimals))); - angle = Math::deg_to_rad(angle); + + if (axis_is_orthogonal) { + _edit.show_rotation_line = false; + Vector3 projection_axis = plane.normal.cross(global_axis); + Vector3 delta = intersection - click; + float projection = delta.dot(projection_axis); + double orth_angle = (projection * (Math::PI / 2.0f)) / (gizmo_scale * GIZMO_CIRCLE_SIZE); + _edit.rotation_angle = snapping + ? Math::deg_to_rad(Math::snapped(Math::rad_to_deg(orth_angle), snap)) + : orth_angle; + } else { + _edit.show_rotation_line = true; + _edit.rotation_angle = snapping + ? Math::deg_to_rad(Math::snapped(Math::rad_to_deg(_edit.accumulated_rotation_angle), snap)) + : _edit.accumulated_rotation_angle; + } + set_message(vformat(TTR("Rotating %s degrees."), String::num(Math::rad_to_deg(_edit.rotation_angle), snap_step_decimals))); Vector3 compute_axis = local_coords ? local_axis : global_axis; - apply_transform(compute_axis, angle); + apply_transform(compute_axis, _edit.rotation_angle); } break; default: { } @@ -6157,7 +6158,7 @@ void Node3DEditorViewport::finish_transform() { _edit.initial_click_vector = Vector3(); _edit.previous_rotation_vector = Vector3(); _edit.accumulated_rotation_angle = 0.0; - _edit.display_rotation_angle = 0.0; + _edit.rotation_angle = 0.0; _edit.gizmo_initiated = false; spatial_editor->set_local_coords_enabled(_edit.original_local); spatial_editor->update_transform_gizmo(); diff --git a/editor/scene/3d/node_3d_editor_plugin.h b/editor/scene/3d/node_3d_editor_plugin.h index 48ea7e5a05..6fbb53b250 100644 --- a/editor/scene/3d/node_3d_editor_plugin.h +++ b/editor/scene/3d/node_3d_editor_plugin.h @@ -404,7 +404,7 @@ private: Vector3 rotation_axis; Vector3 view_axis_local; double accumulated_rotation_angle = 0.0; - double display_rotation_angle = 0.0; + double rotation_angle = 0.0; Vector3 initial_click_vector; Vector3 previous_rotation_vector; bool gizmo_initiated = false;