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]; }