@@ -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.
16761703void 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() {
59906025void 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
0 commit comments