diff options
Diffstat (limited to 'scene/main/viewport.cpp')
-rw-r--r-- | scene/main/viewport.cpp | 151 |
1 files changed, 95 insertions, 56 deletions
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 86992c38f0..0633d194f7 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -148,7 +148,7 @@ void ViewportTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_viewport_path_in_scene", "path"), &ViewportTexture::set_viewport_path_in_scene); ClassDB::bind_method(D_METHOD("get_viewport_path_in_scene"), &ViewportTexture::get_viewport_path_in_scene); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "viewport_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Viewport"), "set_viewport_path_in_scene", "get_viewport_path_in_scene"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "viewport_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Viewport", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT), "set_viewport_path_in_scene", "get_viewport_path_in_scene"); } ViewportTexture::ViewportTexture() { @@ -189,7 +189,7 @@ Viewport::GUI::GUI() { dragging = false; mouse_focus = NULL; mouse_click_grabber = NULL; - mouse_focus_button = -1; + mouse_focus_mask = 0; key_focus = NULL; mouse_over = NULL; @@ -435,7 +435,7 @@ void Viewport::_notification(int p_what) { } } - if (!has_mouse_motion) { + if (!has_mouse_motion && physics_has_last_mousepos) { Ref<InputEventMouseMotion> mm; mm.instance(); mm->set_global_position(physics_last_mousepos); @@ -465,6 +465,7 @@ void Viewport::_notification(int p_what) { pos = mm->get_position(); motion_tested = true; + physics_has_last_mousepos = true; physics_last_mousepos = pos; physics_last_mouse_state.alt = mm->get_alt(); physics_last_mouse_state.shift = mm->get_shift(); @@ -643,7 +644,7 @@ void Viewport::_notification(int p_what) { } } - if (!motion_tested && camera && physics_last_mousepos != Vector2(1e20, 1e20)) { + if (!motion_tested && camera && physics_has_last_mousepos) { //test anyway for mouseenter/exit because objects might move Vector3 from = camera->project_ray_origin(physics_last_mousepos); @@ -671,15 +672,7 @@ void Viewport::_notification(int p_what) { case SceneTree::NOTIFICATION_WM_FOCUS_OUT: { if (gui.mouse_focus) { //if mouse is being pressed, send a release event - Ref<InputEventMouseButton> mb; - mb.instance(); - mb->set_position(gui.mouse_focus->get_local_mouse_position()); - mb->set_global_position(gui.mouse_focus->get_local_mouse_position()); - mb->set_button_index(gui.mouse_focus_button); - mb->set_pressed(false); - Control *c = gui.mouse_focus; - gui.mouse_focus = NULL; - c->call_multilevel(SceneStringNames::get_singleton()->_gui_input, mb); + _drop_mouse_focus(); } } break; } @@ -1686,10 +1679,10 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (mb->is_pressed()) { Size2 pos = mpos; - if (gui.mouse_focus && mb->get_button_index() != gui.mouse_focus_button) { - - //do not steal mouse focus and stuff + if (gui.mouse_focus_mask) { + //do not steal mouse focus and stuff while a focus mask exists + gui.mouse_focus_mask |= 1 << (mb->get_button_index() - 1); //add the button to the mask } else { bool is_handled = false; @@ -1734,7 +1727,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { */ gui.mouse_focus = _gui_find_control(pos); - gui.mouse_focus_button = mb->get_button_index(); + gui.mouse_focus_mask = 1 << (mb->get_button_index() - 1); + gui.last_mouse_focus = gui.mouse_focus; if (!gui.mouse_focus) { return; @@ -1755,7 +1749,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { mb->set_position(pos); #ifdef DEBUG_ENABLED - if (ScriptDebugger::get_singleton()) { + if (ScriptDebugger::get_singleton() && gui.mouse_focus) { Array arr; arr.push_back(gui.mouse_focus->get_path()); @@ -1788,7 +1782,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { } } - if (gui.mouse_focus->can_process()) { + if (gui.mouse_focus && gui.mouse_focus->can_process()) { _gui_call_input(gui.mouse_focus, mb); } @@ -1837,6 +1831,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { //change mouse accordingly } + gui.mouse_focus_mask &= ~(1 << (mb->get_button_index() - 1)); //remove from mask + if (!gui.mouse_focus) { //release event is only sent if a mouse focus (previously pressed button) exists return; @@ -1852,12 +1848,11 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Control *mouse_focus = gui.mouse_focus; //disable mouse focus if needed before calling input, this makes popups on mouse press event work better, as the release will never be received otherwise - if (mb->get_button_index() == gui.mouse_focus_button) { + if (gui.mouse_focus_mask == 0) { gui.mouse_focus = NULL; - gui.mouse_focus_button = -1; } - if (mouse_focus->can_process()) { + if (mouse_focus && mouse_focus->can_process()) { _gui_call_input(mouse_focus, mb); } @@ -1900,7 +1895,14 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (gui.drag_data.get_type() != Variant::NIL) { gui.mouse_focus = NULL; + gui.mouse_focus_mask = 0; + break; } else { + if (gui.drag_preview != NULL) { + ERR_PRINT("Don't set a drag preview and return null data. Preview was deleted and drag request ignored."); + memdelete(gui.drag_preview); + gui.drag_preview = NULL; + } gui.dragging = false; } @@ -1955,10 +1957,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { // If the mouse is over a menu button, this menu will open automatically // if there is already a pop-up menu open at the same hierarchical level. - if (popup_menu_parent && menu_button && - popup_menu_parent->get_icon().is_null() && - menu_button->get_icon().is_null() && - (popup_menu->get_parent()->get_parent()->is_a_parent_of(menu_button) || + if (popup_menu_parent && menu_button && popup_menu_parent->is_switch_on_hover() && + !menu_button->is_disabled() && menu_button->is_switch_on_hover() && + (popup_menu_parent->get_parent()->is_a_parent_of(menu_button) || menu_button->get_parent()->is_a_parent_of(popup_menu))) { popup_menu->notification(Control::NOTIFICATION_MODAL_CLOSE); @@ -2065,7 +2066,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { OS::get_singleton()->set_cursor_shape((OS::CursorShape)cursor_shape); - if (over->can_process()) { + if (over && over->can_process()) { _gui_call_input(over, mm); } @@ -2115,14 +2116,14 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { set_input_as_handled(); return; } - } else if (gui.mouse_focus) { + } else if (touch_event->get_index() == 0 && gui.last_mouse_focus) { - if (gui.mouse_focus->can_process()) { + if (gui.last_mouse_focus->can_process()) { touch_event = touch_event->xformed_by(Transform2D()); //make a copy touch_event->set_position(gui.focus_inv_xform.xform(pos)); - _gui_call_input(gui.mouse_focus, touch_event); + _gui_call_input(gui.last_mouse_focus, touch_event); } set_input_as_handled(); return; @@ -2406,7 +2407,7 @@ void Viewport::_gui_unfocus_control(Control *p_control) { void Viewport::_gui_hid_control(Control *p_control) { if (gui.mouse_focus == p_control) { - gui.mouse_focus = NULL; + _drop_mouse_focus(); } /* ??? @@ -2433,8 +2434,10 @@ void Viewport::_gui_hid_control(Control *p_control) { void Viewport::_gui_remove_control(Control *p_control) { - if (gui.mouse_focus == p_control) + if (gui.mouse_focus == p_control) { gui.mouse_focus = NULL; + gui.mouse_focus_mask = 0; + } if (gui.key_focus == p_control) gui.key_focus = NULL; if (gui.mouse_over == p_control) @@ -2483,6 +2486,27 @@ void Viewport::_gui_accept_event() { set_input_as_handled(); } +void Viewport::_drop_mouse_focus() { + + Control *c = gui.mouse_focus; + int mask = gui.mouse_focus_mask; + gui.mouse_focus = NULL; + gui.mouse_focus_mask = 0; + + for (int i = 0; i < 3; i++) { + + if (mask & (1 << i)) { + Ref<InputEventMouseButton> mb; + mb.instance(); + mb->set_position(c->get_local_mouse_position()); + mb->set_global_position(c->get_local_mouse_position()); + mb->set_button_index(i + 1); + mb->set_pressed(false); + c->call_multilevel(SceneStringNames::get_singleton()->_gui_input, mb); + } + } +} + List<Control *>::Element *Viewport::_gui_show_modal(Control *p_control) { gui.modal_stack.push_back(p_control); @@ -2492,15 +2516,8 @@ List<Control *>::Element *Viewport::_gui_show_modal(Control *p_control) { p_control->_modal_set_prev_focus_owner(0); if (gui.mouse_focus && !p_control->is_a_parent_of(gui.mouse_focus) && !gui.mouse_click_grabber) { - Ref<InputEventMouseButton> mb; - mb.instance(); - mb->set_position(gui.mouse_focus->get_local_mouse_position()); - mb->set_global_position(gui.mouse_focus->get_local_mouse_position()); - mb->set_button_index(gui.mouse_focus_button); - mb->set_pressed(false); - Control *c = gui.mouse_focus; - gui.mouse_focus = NULL; - c->call_multilevel(SceneStringNames::get_singleton()->_gui_input, mb); + + _drop_mouse_focus(); } return gui.modal_stack.back(); @@ -2530,24 +2547,45 @@ void Viewport::_post_gui_grab_click_focus() { if (gui.mouse_focus == focus_grabber) return; - Ref<InputEventMouseButton> mb; - mb.instance(); - - //send unclic + int mask = gui.mouse_focus_mask; Point2 click = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos); - mb->set_position(click); - mb->set_button_index(gui.mouse_focus_button); - mb->set_pressed(false); - gui.mouse_focus->call_multilevel(SceneStringNames::get_singleton()->_gui_input, mb); + + for (int i = 0; i < 3; i++) { + + if (mask & (1 << i)) { + + Ref<InputEventMouseButton> mb; + mb.instance(); + + //send unclic + + mb->set_position(click); + mb->set_button_index(i + 1); + mb->set_pressed(false); + gui.mouse_focus->call_multilevel(SceneStringNames::get_singleton()->_gui_input, mb); + } + } gui.mouse_focus = focus_grabber; gui.focus_inv_xform = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse(); click = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos); - mb->set_position(click); - mb->set_button_index(gui.mouse_focus_button); - mb->set_pressed(true); - gui.mouse_focus->call_deferred(SceneStringNames::get_singleton()->_gui_input, mb); + + for (int i = 0; i < 3; i++) { + + if (mask & (1 << i)) { + + Ref<InputEventMouseButton> mb; + mb.instance(); + + //send clic + + mb->set_position(click); + mb->set_button_index(i + 1); + mb->set_pressed(true); + gui.mouse_focus->call_deferred(SceneStringNames::get_singleton()->_gui_input, mb); + } + } } } @@ -3068,7 +3106,8 @@ Viewport::Viewport() { physics_object_picking = false; physics_object_capture = 0; physics_object_over = 0; - physics_last_mousepos = Vector2(1e20, 1e20); + physics_has_last_mousepos = false; + physics_last_mousepos = Vector2(Math_INF, Math_INF); shadow_atlas_size = 0; for (int i = 0; i < 4; i++) { |