From afb58396966f2c0e71d73fc30a325df064d99667 Mon Sep 17 00:00:00 2001 From: "Silc Lizard (Tokage) Renew" <61938263+TokageItLab@users.noreply.github.com> Date: Tue, 3 Feb 2026 11:16:56 +0900 Subject: [PATCH] Make trackball rotation optional as toggle option of Node3DEditorTool Co-authored-by: ryevdokimov --- editor/icons/Trackball.svg | 1 + editor/scene/3d/node_3d_editor_plugin.cpp | 28 ++++++++++++++++++----- editor/scene/3d/node_3d_editor_plugin.h | 12 +++++++--- 3 files changed, 32 insertions(+), 9 deletions(-) create mode 100644 editor/icons/Trackball.svg diff --git a/editor/icons/Trackball.svg b/editor/icons/Trackball.svg new file mode 100644 index 0000000000..0b6ffe5c5b --- /dev/null +++ b/editor/icons/Trackball.svg @@ -0,0 +1 @@ + diff --git a/editor/scene/3d/node_3d_editor_plugin.cpp b/editor/scene/3d/node_3d_editor_plugin.cpp index 350e090a2b..1a7625ed40 100644 --- a/editor/scene/3d/node_3d_editor_plugin.cpp +++ b/editor/scene/3d/node_3d_editor_plugin.cpp @@ -1465,7 +1465,7 @@ bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, b if (Math::abs(distance_ray_to_center - view_rotation_radius) < circumference_tolerance && ray_length_to_center > 0) { view_rotation_selected = true; - } else if (distance_ray_to_center < gizmo_scale * (GIZMO_CIRCLE_SIZE - GIZMO_RING_HALF_WIDTH) && ray_length_to_center > 0) { + } else if (spatial_editor->is_trackball_enabled() && distance_ray_to_center < gizmo_scale * (GIZMO_CIRCLE_SIZE - GIZMO_RING_HALF_WIDTH) && ray_length_to_center > 0) { trackball_selected = true; } } @@ -7136,6 +7136,7 @@ Dictionary Node3DEditor::get_state() const { Dictionary d; d["snap_enabled"] = snap_enabled; + d["trackball_enabled"] = trackball_enabled; d["translate_snap"] = snap_translate_value; d["rotate_snap"] = snap_rotate_value; d["scale_snap"] = snap_scale_value; @@ -7216,6 +7217,11 @@ void Node3DEditor::set_state(const Dictionary &p_state) { tool_option_button[TOOL_OPT_USE_SNAP]->set_pressed(d["snap_enabled"]); } + if (d.has("trackball_enabled")) { + trackball_enabled = d["trackball_enabled"]; + tool_option_button[TOOL_OPT_USE_TRACKBALL]->set_pressed(d["trackball_enabled"]); + } + if (d.has("translate_snap")) { snap_translate_value = d["translate_snap"]; } @@ -7463,6 +7469,11 @@ void Node3DEditor::_menu_item_toggled(bool pressed, int p_option) { tool_option_button[TOOL_OPT_USE_SNAP]->set_pressed(pressed); snap_enabled = pressed; } break; + + case MENU_TOOL_USE_TRACKBALL: { + tool_option_button[TOOL_OPT_USE_TRACKBALL]->set_pressed(pressed); + trackball_enabled = pressed; + } break; } } @@ -9057,6 +9068,7 @@ void Node3DEditor::_update_theme() { tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_button_icon(get_editor_theme_icon(SNAME("Object"))); tool_option_button[TOOL_OPT_USE_SNAP]->set_button_icon(get_editor_theme_icon(SNAME("Snap"))); + tool_option_button[TOOL_OPT_USE_TRACKBALL]->set_button_icon(get_editor_theme_icon(SNAME("Trackball"))); view_layout_menu->get_popup()->set_item_icon(view_layout_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_editor_theme_icon(SNAME("Panels1"))); view_layout_menu->get_popup()->set_item_icon(view_layout_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_editor_theme_icon(SNAME("Panels2"))); @@ -9873,16 +9885,11 @@ Node3DEditor::Node3DEditor() { viewport_environment.instantiate(); VBoxContainer *vbc = this; - custom_camera = nullptr; ERR_FAIL_COND_MSG(singleton != nullptr, "A Node3DEditor singleton already exists."); singleton = this; editor_selection = EditorNode::get_singleton()->get_editor_selection(); editor_selection->add_editor_plugin(this); - snap_enabled = false; - snap_key_enabled = false; - tool_mode = TOOL_MODE_TRANSFORM; - MarginContainer *toolbar_margin = memnew(MarginContainer); toolbar_margin->set_theme_type_variation("MainToolBarMargin"); vbc->add_child(toolbar_margin); @@ -10023,6 +10030,15 @@ Node3DEditor::Node3DEditor() { tool_option_button[TOOL_OPT_USE_SNAP]->set_shortcut_context(this); tool_option_button[TOOL_OPT_USE_SNAP]->set_accessibility_name(TTRC("Use Snap")); + tool_option_button[TOOL_OPT_USE_TRACKBALL] = memnew(Button); + main_menu_hbox->add_child(tool_option_button[TOOL_OPT_USE_TRACKBALL]); + tool_option_button[TOOL_OPT_USE_TRACKBALL]->set_toggle_mode(true); + tool_option_button[TOOL_OPT_USE_TRACKBALL]->set_theme_type_variation(SceneStringName(FlatButton)); + tool_option_button[TOOL_OPT_USE_TRACKBALL]->connect(SceneStringName(toggled), callable_mp(this, &Node3DEditor::_menu_item_toggled).bind(MENU_TOOL_USE_TRACKBALL)); + tool_option_button[TOOL_OPT_USE_TRACKBALL]->set_shortcut(ED_SHORTCUT("spatial_editor/trackball", TTRC("Use Trackball"), Key::U)); + tool_option_button[TOOL_OPT_USE_TRACKBALL]->set_shortcut_context(this); + tool_option_button[TOOL_OPT_USE_TRACKBALL]->set_accessibility_name(TTRC("Use Trackball")); + main_menu_hbox->add_child(memnew(VSeparator)); sun_button = memnew(Button); sun_button->set_tooltip_text(TTRC("Toggle preview sunlight.\nIf a DirectionalLight3D node is added to the scene, preview sunlight is disabled.")); diff --git a/editor/scene/3d/node_3d_editor_plugin.h b/editor/scene/3d/node_3d_editor_plugin.h index 0f169cee6f..f3d1a984b8 100644 --- a/editor/scene/3d/node_3d_editor_plugin.h +++ b/editor/scene/3d/node_3d_editor_plugin.h @@ -679,6 +679,7 @@ public: enum ToolOptions { TOOL_OPT_LOCAL_COORDS, TOOL_OPT_USE_SNAP, + TOOL_OPT_USE_TRACKBALL, TOOL_OPT_MAX }; @@ -700,7 +701,7 @@ private: ///// - ToolMode tool_mode; + ToolMode tool_mode = TOOL_MODE_TRANSFORM; RID origin_mesh; RID origin_multimesh; @@ -778,6 +779,7 @@ private: MENU_TOOL_LIST_SELECT, MENU_TOOL_LOCAL_COORDS, MENU_TOOL_USE_SNAP, + MENU_TOOL_USE_TRACKBALL, MENU_TRANSFORM_CONFIGURE_SNAP, MENU_TRANSFORM_DIALOG, MENU_VIEW_USE_1_VIEWPORT, @@ -811,12 +813,14 @@ private: ConfirmationDialog *xform_dialog = nullptr; ConfirmationDialog *settings_dialog = nullptr; - bool snap_enabled; - bool snap_key_enabled; + bool snap_enabled = false; + bool snap_key_enabled = false; EditorSpinSlider *snap_translate = nullptr; EditorSpinSlider *snap_rotate = nullptr; EditorSpinSlider *snap_scale = nullptr; + bool trackball_enabled = false; + LineEdit *xform_translate[3]; LineEdit *xform_rotate[3]; LineEdit *xform_scale[3]; @@ -996,6 +1000,8 @@ public: real_t get_rotate_snap() const; real_t get_scale_snap() const; + bool is_trackball_enabled() const { return trackball_enabled; } + Ref get_move_gizmo(int idx) const { return move_gizmo[idx]; } Ref get_axis_gizmo(int idx) const { return axis_gizmo[idx]; } Ref get_move_plane_gizmo(int idx) const { return move_plane_gizmo[idx]; }