Skip to content

Commit 8cd5659

Browse files
committed
Merge pull request #107530 from ryevdokimov/freelook-redirect-viewport
Fix freelook in 3D when multiple viewports are open
2 parents b720cbc + 7e5ccad commit 8cd5659

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

editor/plugins/node_3d_editor_plugin.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1671,6 +1671,33 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
16711671
}
16721672
}
16731673

1674+
// Helper function to redirect mouse events to the active freelook viewport
1675+
static bool _redirect_freelook_input(const Ref<InputEvent> &p_event, Node3DEditorViewport *p_exclude_viewport = nullptr) {
1676+
if (Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED) {
1677+
return false;
1678+
}
1679+
1680+
Node3DEditor *editor = Node3DEditor::get_singleton();
1681+
if (!editor->get_freelook_viewport()) {
1682+
return false;
1683+
}
1684+
1685+
Node3DEditorViewport *freelook_vp = editor->get_freelook_viewport();
1686+
if (freelook_vp == p_exclude_viewport) {
1687+
return false;
1688+
}
1689+
1690+
Ref<InputEventMouse> mouse_event = p_event;
1691+
if (!mouse_event.is_valid()) {
1692+
return false;
1693+
}
1694+
1695+
Control *target_surface = freelook_vp->get_surface();
1696+
1697+
target_surface->emit_signal(SceneStringName(gui_input), p_event);
1698+
return true;
1699+
}
1700+
16741701
// This is only active during instant transforms,
16751702
// to capture and wrap mouse events outside the control.
16761703
void Node3DEditorViewport::input(const Ref<InputEvent> &p_event) {
@@ -1688,6 +1715,10 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
16881715
return; //do NONE
16891716
}
16901717

1718+
if (_redirect_freelook_input(p_event, this)) {
1719+
return;
1720+
}
1721+
16911722
EditorPlugin::AfterGUIInput after = EditorPlugin::AFTER_GUI_INPUT_PASS;
16921723
{
16931724
EditorNode *en = EditorNode::get_singleton();
@@ -2702,13 +2733,17 @@ void Node3DEditorViewport::set_freelook_active(bool active_now) {
27022733

27032734
previous_mouse_position = get_local_mouse_position();
27042735

2736+
spatial_editor->set_freelook_viewport(this);
2737+
27052738
// Hide mouse like in an FPS (warping doesn't work)
27062739
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
27072740

27082741
} else if (freelook_active && !active_now) {
27092742
// Sync camera cursor to cursor to "cut" interpolation jumps due to changing referential
27102743
cursor = camera_cursor;
27112744

2745+
spatial_editor->set_freelook_viewport(nullptr);
2746+
27122747
// Restore mouse
27132748
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
27142749

@@ -5990,6 +6025,10 @@ Node3DEditorViewport::~Node3DEditorViewport() {
59906025
void Node3DEditorViewportContainer::gui_input(const Ref<InputEvent> &p_event) {
59916026
ERR_FAIL_COND(p_event.is_null());
59926027

6028+
if (_redirect_freelook_input(p_event)) {
6029+
return;
6030+
}
6031+
59936032
Ref<InputEventMouseButton> mb = p_event;
59946033

59956034
if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) {
@@ -6084,7 +6123,7 @@ void Node3DEditorViewportContainer::_notification(int p_what) {
60846123
} break;
60856124

60866125
case NOTIFICATION_DRAW: {
6087-
if (mouseover) {
6126+
if (mouseover && Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED) {
60886127
Ref<Texture2D> h_grabber = get_theme_icon(SNAME("grabber"), SNAME("HSplitContainer"));
60896128
Ref<Texture2D> v_grabber = get_theme_icon(SNAME("grabber"), SNAME("VSplitContainer"));
60906129

editor/plugins/node_3d_editor_plugin.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ class Node3DEditorViewport : public Control {
560560

561561
SubViewport *get_viewport_node() { return viewport; }
562562
Camera3D *get_camera_3d() { return camera; } // return the default camera object.
563+
Control *get_surface() { return surface; }
563564

564565
Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p_index);
565566
~Node3DEditorViewport();
@@ -825,6 +826,8 @@ class Node3DEditor : public VBoxContainer {
825826

826827
Node3D *selected = nullptr;
827828

829+
Node3DEditorViewport *freelook_viewport = nullptr;
830+
828831
void _request_gizmo(Object *p_obj);
829832
void _request_gizmo_for_id(ObjectID p_id);
830833
void _set_subgizmo_selection(Object *p_obj, Ref<Node3DGizmo> p_gizmo, int p_id, Transform3D p_transform = Transform3D());
@@ -1025,6 +1028,9 @@ class Node3DEditor : public VBoxContainer {
10251028
}
10261029
Node3DEditorViewport *get_last_used_viewport();
10271030

1031+
void set_freelook_viewport(Node3DEditorViewport *p_viewport) { freelook_viewport = p_viewport; }
1032+
Node3DEditorViewport *get_freelook_viewport() const { return freelook_viewport; }
1033+
10281034
void add_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin);
10291035
void remove_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin);
10301036

0 commit comments

Comments
 (0)