1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-10 13:00:37 +00:00

Fix freelook in 3D when multiple viewports are open

This commit is contained in:
Robert Yevdokimov
2025-06-14 14:10:23 +04:00
parent 1218a16de5
commit 7e5ccada9c
2 changed files with 46 additions and 1 deletions

View File

@@ -1671,6 +1671,33 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
}
}
// Helper function to redirect mouse events to the active freelook viewport
static bool _redirect_freelook_input(const Ref<InputEvent> &p_event, Node3DEditorViewport *p_exclude_viewport = nullptr) {
if (Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED) {
return false;
}
Node3DEditor *editor = Node3DEditor::get_singleton();
if (!editor->get_freelook_viewport()) {
return false;
}
Node3DEditorViewport *freelook_vp = editor->get_freelook_viewport();
if (freelook_vp == p_exclude_viewport) {
return false;
}
Ref<InputEventMouse> mouse_event = p_event;
if (!mouse_event.is_valid()) {
return false;
}
Control *target_surface = freelook_vp->get_surface();
target_surface->emit_signal(SceneStringName(gui_input), p_event);
return true;
}
// This is only active during instant transforms,
// to capture and wrap mouse events outside the control.
void Node3DEditorViewport::input(const Ref<InputEvent> &p_event) {
@@ -1688,6 +1715,10 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
return; //do NONE
}
if (_redirect_freelook_input(p_event, this)) {
return;
}
EditorPlugin::AfterGUIInput after = EditorPlugin::AFTER_GUI_INPUT_PASS;
{
EditorNode *en = EditorNode::get_singleton();
@@ -2702,6 +2733,8 @@ void Node3DEditorViewport::set_freelook_active(bool active_now) {
previous_mouse_position = get_local_mouse_position();
spatial_editor->set_freelook_viewport(this);
// Hide mouse like in an FPS (warping doesn't work)
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
@@ -2709,6 +2742,8 @@ void Node3DEditorViewport::set_freelook_active(bool active_now) {
// Sync camera cursor to cursor to "cut" interpolation jumps due to changing referential
cursor = camera_cursor;
spatial_editor->set_freelook_viewport(nullptr);
// Restore mouse
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
@@ -5990,6 +6025,10 @@ Node3DEditorViewport::~Node3DEditorViewport() {
void Node3DEditorViewportContainer::gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
if (_redirect_freelook_input(p_event)) {
return;
}
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) {
@@ -6084,7 +6123,7 @@ void Node3DEditorViewportContainer::_notification(int p_what) {
} break;
case NOTIFICATION_DRAW: {
if (mouseover) {
if (mouseover && Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED) {
Ref<Texture2D> h_grabber = get_theme_icon(SNAME("grabber"), SNAME("HSplitContainer"));
Ref<Texture2D> v_grabber = get_theme_icon(SNAME("grabber"), SNAME("VSplitContainer"));