Merge pull request #105791 from ryevdokimov/cancel-navigation

Add the ability to cancel pan/zoom/orbit navigation
This commit is contained in:
Thaddeus Crews 2026-03-09 15:18:26 -05:00
commit 88cd7ab378
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
5 changed files with 52 additions and 11 deletions

View file

@ -464,7 +464,7 @@ void ViewportRotationControl::_process_drag(Ref<InputEventWithModifiers> p_event
if (Input::get_singleton()->get_mouse_mode() == Input::MouseMode::MOUSE_MODE_VISIBLE) {
Input::get_singleton()->set_mouse_mode(Input::MouseMode::MOUSE_MODE_CAPTURED);
orbiting_mouse_start = p_position;
viewport->previous_cursor = viewport->view_3d_controller->cursor;
saved_cursor = viewport->view_3d_controller->cursor;
}
viewport->view_3d_controller->cursor_orbit(p_event, p_relative_position);
focused_axis = -1;
@ -483,7 +483,7 @@ void ViewportRotationControl::gui_input(const Ref<InputEvent> &p_event) {
if (Input::get_singleton()->get_mouse_mode() == Input::MouseMode::MOUSE_MODE_CAPTURED) {
Input::get_singleton()->set_mouse_mode(Input::MouseMode::MOUSE_MODE_VISIBLE);
Input::get_singleton()->warp_mouse(orbiting_mouse_start);
viewport->view_3d_controller->cursor = viewport->previous_cursor;
viewport->view_3d_controller->cursor = saved_cursor;
gizmo_activated = false;
}
}
@ -502,7 +502,7 @@ void ViewportRotationControl::gui_input(const Ref<InputEvent> &p_event) {
if (Input::get_singleton()->get_mouse_mode() == Input::MouseMode::MOUSE_MODE_CAPTURED) {
Input::get_singleton()->set_mouse_mode(Input::MouseMode::MOUSE_MODE_VISIBLE);
Input::get_singleton()->warp_mouse(orbiting_mouse_start);
viewport->view_3d_controller->cursor = viewport->previous_cursor;
viewport->view_3d_controller->cursor = saved_cursor;
gizmo_activated = false;
}
}
@ -1740,7 +1740,11 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
// Several parts of the 3D navigation are handled here.
bool was_navigating = view_3d_controller->is_navigating();
view_3d_controller->gui_input(p_event, surface->get_global_rect());
if (was_navigating && !view_3d_controller->is_navigating()) {
return;
}
Ref<InputEventMouseButton> b = p_event;

View file

@ -89,6 +89,7 @@ class ViewportRotationControl : public Control {
Vector<int> axis_menu_options;
Vector2i orbiting_mouse_start;
Point2 original_mouse_pos;
View3DController::Cursor saved_cursor;
int orbiting_index = -1;
int focused_axis = -2;
bool gizmo_activated = false;
@ -368,8 +369,6 @@ private:
void _freelook_changed();
void _freelook_speed_scaled();
View3DController::Cursor previous_cursor; // Storing previous cursor state for canceling purposes.
real_t zoom_indicator_delay;
int zoom_failed_attempts_count = 0;

View file

@ -1424,12 +1424,6 @@ void RuntimeNodeSelect::_cursor_interpolated() {
}
bool RuntimeNodeSelect::_handle_3d_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> b = p_event;
if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT) {
view_3d_controller->set_freelook_enabled(b->is_pressed());
return true;
}
Window *root = SceneTree::get_singleton()->get_root();
ERR_FAIL_COND_V(!root->is_camera_3d_override_enabled(), true);
@ -1451,6 +1445,12 @@ bool RuntimeNodeSelect::_handle_3d_input(const Ref<InputEvent> &p_event) {
return true;
}
Ref<InputEventMouseButton> b = p_event;
if (b.is_valid() && b->get_button_index() == MouseButton::RIGHT) {
view_3d_controller->set_freelook_enabled(b->is_pressed());
return true;
}
Ref<InputEventKey> k = p_event;
if (k.is_valid() && k->get_physical_keycode() == Key::ESCAPE) {
view_3d_controller->set_freelook_enabled(false);

View file

@ -120,6 +120,11 @@ View3DController::NavigationMode View3DController::_get_nav_mode_from_shortcuts(
bool View3DController::gui_input(const Ref<InputEvent> &p_event, const Rect2 &p_surface_rect) {
Ref<InputEventMouseButton> b = p_event;
if (b.is_valid()) {
if (b->get_button_index() == MouseButton::RIGHT && b->is_pressed() && navigating) {
cancel_navigation();
return true;
}
const real_t zoom_factor = 1 + (ZOOM_FREELOOK_MULTIPLIER - 1) * b->get_factor();
switch (b->get_button_index()) {
case MouseButton::WHEEL_UP: {
@ -168,6 +173,18 @@ bool View3DController::gui_input(const Ref<InputEvent> &p_event, const Rect2 &p_
Ref<InputEventMouseMotion> m = p_event;
if (m.is_valid()) {
if (m->get_button_mask() == MouseButtonMask::NONE) {
navigation_cancelled = false;
}
if (navigation_cancelled) {
return false;
}
if (!navigating) {
previous_cursor = cursor;
}
NavigationMode nav_mode = NAV_MODE_NONE;
if (m->get_button_mask().has_flag(MouseButtonMask::LEFT)) {
@ -229,10 +246,14 @@ bool View3DController::gui_input(const Ref<InputEvent> &p_event, const Rect2 &p_
} break;
default: {
navigating = false;
return false;
}
}
if (!freelook) {
navigating = true;
}
return true;
}
@ -283,6 +304,12 @@ bool View3DController::gui_input(const Ref<InputEvent> &p_event, const Rect2 &p_
return true;
}
Ref<InputEventKey> k = p_event;
if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == Key::ESCAPE && navigating) {
cancel_navigation();
return true;
}
bool pressed = false;
float old_fov_scale = cursor.fov_scale;
@ -306,6 +333,12 @@ bool View3DController::gui_input(const Ref<InputEvent> &p_event, const Rect2 &p_
return pressed;
}
void View3DController::cancel_navigation() {
navigating = false;
navigation_cancelled = true;
cursor = previous_cursor;
}
void View3DController::cursor_pan(const Ref<InputEventWithModifiers> &p_event, const Vector2 &p_relative) {
float pan_speed = translation_sensitivity / 150.0;
if (p_event.is_valid() && navigation_scheme == NAV_SCHEME_MAYA && p_event->is_shift_pressed()) {

View file

@ -171,6 +171,10 @@ public:
private:
Cursor cursor_interp; // That one may be interpolated (don't modify this one except for smoothing purposes).
Cursor previous_cursor; // Storing previous cursor state for canceling purposes.
bool navigating = false;
bool navigation_cancelled = false;
void cancel_navigation();
protected:
static void _bind_methods();
@ -249,6 +253,7 @@ private:
public:
bool gui_input(const Ref<InputEvent> &p_event, const Rect2 &p_surface_rect);
bool is_navigating() const { return navigating; }
void cursor_pan(const Ref<InputEventWithModifiers> &p_event, const Vector2 &p_relative);
void cursor_look(const Ref<InputEventWithModifiers> &p_event, const Vector2 &p_relative);