diff --git a/editor/scene/3d/node_3d_editor_plugin.cpp b/editor/scene/3d/node_3d_editor_plugin.cpp index e59c5ec6fb10..41faeeb1b2a4 100644 --- a/editor/scene/3d/node_3d_editor_plugin.cpp +++ b/editor/scene/3d/node_3d_editor_plugin.cpp @@ -251,7 +251,7 @@ void ViewportNavigationControl::_update_navigation() { Vector3 forward; if (viewport->view_3d_controller->get_freelook_scheme() == View3DController::FreelookScheme::FREELOOK_FULLY_AXIS_LOCKED) { - // Forward/backward keys will always go straight forward/backward, never moving on the Y axis. + // Forward/backward keys will always go horizontally forward/backward, never moving on the Y axis. forward = Vector3(0, 0, delta_normalized.y).rotated(Vector3(0, 1, 0), viewport->camera->get_rotation().y); } else { // Forward/backward keys will be relative to the camera pitch. @@ -2945,7 +2945,11 @@ void Node3DEditorViewport::_sinput(const Ref &p_event) { // Freelook doesn't work in orthogonal mode or when previewing without pilot mode. if (!view_3d_controller->is_orthogonal() && !(previewing && !pilot_preview_enabled) && ED_IS_SHORTCUT("spatial_editor/freelook_toggle", event_mod)) { - view_3d_controller->set_freelook_enabled(!view_3d_controller->is_freelook_enabled()); + // Only allow Shift+F to toggle freelook off if right mouse button is not pressed. + // This lets users press Shift and F independently during right-mouse-activated freelook. + if (!view_3d_controller->is_freelook_enabled() || !Input::get_singleton()->is_mouse_button_pressed(MouseButton::RIGHT)) { + view_3d_controller->set_freelook_enabled(!view_3d_controller->is_freelook_enabled()); + } } else if (k->get_keycode() == Key::ESCAPE) { view_3d_controller->set_freelook_enabled(false); } @@ -3593,6 +3597,10 @@ void Node3DEditorViewport::_update_view_3d_controller(bool p_update_all) { view_3d_controller->set_shortcut(View3DController::SHORTCUT_FREELOOK_RIGHT, ED_GET_SHORTCUT("spatial_editor/freelook_right")); view_3d_controller->set_shortcut(View3DController::SHORTCUT_FREELOOK_UP, ED_GET_SHORTCUT("spatial_editor/freelook_up")); view_3d_controller->set_shortcut(View3DController::SHORTCUT_FREELOOK_DOWN, ED_GET_SHORTCUT("spatial_editor/freelook_down")); + view_3d_controller->set_shortcut(View3DController::SHORTCUT_FREELOOK_GLOBAL_UP, ED_GET_SHORTCUT("spatial_editor/freelook_global_up")); + view_3d_controller->set_shortcut(View3DController::SHORTCUT_FREELOOK_GLOBAL_DOWN, ED_GET_SHORTCUT("spatial_editor/freelook_global_down")); + view_3d_controller->set_shortcut(View3DController::SHORTCUT_FREELOOK_LOCAL_UP, ED_GET_SHORTCUT("spatial_editor/freelook_local_up")); + view_3d_controller->set_shortcut(View3DController::SHORTCUT_FREELOOK_LOCAL_DOWN, ED_GET_SHORTCUT("spatial_editor/freelook_local_down")); view_3d_controller->set_shortcut(View3DController::SHORTCUT_FREELOOK_SPEED_MOD, ED_GET_SHORTCUT("spatial_editor/freelook_speed_modifier")); view_3d_controller->set_shortcut(View3DController::SHORTCUT_FREELOOK_SLOW_MOD, ED_GET_SHORTCUT("spatial_editor/freelook_slow_modifier")); @@ -6258,6 +6266,12 @@ void Node3DEditorViewport::register_shortcut_action(const String &p_path, const sc->connect_changed(callable_mp(this, &Node3DEditorViewport::shortcut_changed_callback).bind(sc, p_path)); } +void Node3DEditorViewport::register_shortcuts_action(const String &p_path, const String &p_name, const PackedInt32Array &p_keycodes, bool p_physical) { + Ref sc = ED_SHORTCUT_ARRAY(p_path, p_name, p_keycodes, p_physical); + shortcut_changed_callback(sc, p_path); + sc->connect_changed(callable_mp(this, &Node3DEditorViewport::shortcut_changed_callback).bind(sc, p_path)); +} + // Update the action in the InputMap to the provided shortcut events. void Node3DEditorViewport::shortcut_changed_callback(const Ref p_shortcut, const String &p_shortcut_path) { InputMap *im = InputMap::get_singleton(); @@ -6310,8 +6324,13 @@ void Node3DEditorViewport::_load_viewport_inputs() { register_shortcut_action("spatial_editor/freelook_backwards", TTRC("Freelook Backwards"), Key::S, true); register_shortcut_action("spatial_editor/freelook_up", TTRC("Freelook Up"), Key::E, true); register_shortcut_action("spatial_editor/freelook_down", TTRC("Freelook Down"), Key::Q, true); + register_shortcut_action("spatial_editor/freelook_global_up", TTRC("Freelook Global Up"), Key::SPACE, true); + register_shortcuts_action("spatial_editor/freelook_global_down", TTRC("Freelook Global Down"), { int32_t(Key::CTRL), int32_t(Key::META) }, true); + register_shortcut_action("spatial_editor/freelook_local_up", TTRC("Freelook Local Up"), Key::R, true); + register_shortcut_action("spatial_editor/freelook_local_down", TTRC("Freelook Local Down"), Key::F, true); register_shortcut_action("spatial_editor/freelook_speed_modifier", TTRC("Freelook Speed Modifier"), Key::SHIFT); register_shortcut_action("spatial_editor/freelook_slow_modifier", TTRC("Freelook Slow Modifier"), Key::ALT); + register_shortcut_action("spatial_editor/freelook_toggle", TTRC("Toggle Freelook"), KeyModifierMask::SHIFT | Key::F); } Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p_index) { @@ -10201,7 +10220,6 @@ Node3DEditor::Node3DEditor() { { 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", TTRC("Align Rotation with View"), KeyModifierMask::ALT + KeyModifierMask::CMD_OR_CTRL + Key::F); - ED_SHORTCUT("spatial_editor/freelook_toggle", TTRC("Toggle Freelook"), KeyModifierMask::SHIFT + Key::F); ED_SHORTCUT("spatial_editor/decrease_fov", TTRC("Decrease Field of View"), KeyModifierMask::CMD_OR_CTRL + Key::EQUAL); // Usually direct access key for `KEY_PLUS`. ED_SHORTCUT("spatial_editor/increase_fov", TTRC("Increase Field of View"), KeyModifierMask::CMD_OR_CTRL + Key::MINUS); ED_SHORTCUT("spatial_editor/reset_fov", TTRC("Reset Field of View to Default"), KeyModifierMask::CMD_OR_CTRL + Key::KEY_0); diff --git a/editor/scene/3d/node_3d_editor_plugin.h b/editor/scene/3d/node_3d_editor_plugin.h index bca59fe7f289..cb1a3126a576 100644 --- a/editor/scene/3d/node_3d_editor_plugin.h +++ b/editor/scene/3d/node_3d_editor_plugin.h @@ -476,6 +476,7 @@ class Node3DEditorViewport : public Control { void _load_viewport_inputs(); void register_shortcut_action(const String &p_path, const String &p_name, Key p_keycode, bool p_physical = false); + void register_shortcuts_action(const String &p_path, const String &p_name, const PackedInt32Array &p_keycodes, bool p_physical = false); void shortcut_changed_callback(const Ref p_shortcut, const String &p_shortcut_path); // Supported rendering methods for advanced debug draw mode items. diff --git a/scene/debugger/view_3d_controller.cpp b/scene/debugger/view_3d_controller.cpp index 03ba53a21eaf..ae47d91cd024 100644 --- a/scene/debugger/view_3d_controller.cpp +++ b/scene/debugger/view_3d_controller.cpp @@ -545,11 +545,12 @@ void View3DController::update_freelook(const float p_delta) { forward = Vector3(0, 0, -1).rotated(Vector3(0, 1, 0), camera_transform.get_basis().get_euler().y); } else { // Forward/backward keys will be relative to the camera pitch. - forward = camera_transform.basis.xform(Vector3(0, 0, -1)); + forward = -camera_transform.basis.get_column(2); } - const Vector3 right = camera_transform.basis.xform(Vector3(1, 0, 0)); + const Vector3 right = camera_transform.basis.get_column(0); + Vector3 local_up = camera_transform.basis.get_column(1); Vector3 up; if (freelook_scheme == View3DController::FREELOOK_PARTIALLY_AXIS_LOCKED || freelook_scheme == View3DController::FREELOOK_FULLY_AXIS_LOCKED) { // Up/down keys will always go up/down regardless of camera pitch. @@ -578,6 +579,21 @@ void View3DController::update_freelook(const float p_delta) { if (_is_shortcut_pressed(SHORTCUT_FREELOOK_DOWN)) { direction -= up; } + if (_is_shortcut_pressed(SHORTCUT_FREELOOK_GLOBAL_UP)) { + direction += Vector3(0, 1, 0); + } + if (_is_shortcut_pressed(SHORTCUT_FREELOOK_GLOBAL_DOWN)) { + direction -= Vector3(0, 1, 0); + } + if (_is_shortcut_pressed(SHORTCUT_FREELOOK_LOCAL_UP)) { + direction += local_up; + } + if (_is_shortcut_pressed(SHORTCUT_FREELOOK_LOCAL_DOWN)) { + // Avoid conflict with Shift+F to toggle freelook (alternative to right click). + if (Input::get_singleton()->is_mouse_button_pressed(MouseButton::RIGHT) || !Input::get_singleton()->is_action_pressed("spatial_editor/freelook_toggle")) { + direction -= local_up; + } + } real_t speed = freelook_speed; diff --git a/scene/debugger/view_3d_controller.h b/scene/debugger/view_3d_controller.h index c61c78c86512..672baa3daa84 100644 --- a/scene/debugger/view_3d_controller.h +++ b/scene/debugger/view_3d_controller.h @@ -134,6 +134,10 @@ class View3DController : public RefCounted { SHORTCUT_FREELOOK_DOWN, SHORTCUT_FREELOOK_SPEED_MOD, SHORTCUT_FREELOOK_SLOW_MOD, + SHORTCUT_FREELOOK_GLOBAL_UP, + SHORTCUT_FREELOOK_GLOBAL_DOWN, + SHORTCUT_FREELOOK_LOCAL_UP, + SHORTCUT_FREELOOK_LOCAL_DOWN, SHORTCUT_MAX, };