diff options
Diffstat (limited to 'scene/main/viewport.cpp')
| -rw-r--r-- | scene/main/viewport.cpp | 75 |
1 files changed, 56 insertions, 19 deletions
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 28521c5bbe..a1e7555a5d 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -36,6 +36,7 @@ #include "core/object/message_queue.h" #include "core/string/translation.h" #include "core/templates/pair.h" +#include "core/templates/sort_array.h" #include "scene/2d/audio_listener_2d.h" #include "scene/2d/camera_2d.h" #include "scene/2d/collision_object_2d.h" @@ -379,7 +380,7 @@ void Viewport::_notification(int p_what) { if (get_tree()->is_debugging_collisions_hint()) { PhysicsServer2D::get_singleton()->space_set_debug_contacts(find_world_2d()->get_space(), get_tree()->get_collision_debug_contact_count()); contact_2d_debug = RenderingServer::get_singleton()->canvas_item_create(); - RenderingServer::get_singleton()->canvas_item_set_parent(contact_2d_debug, find_world_2d()->get_canvas()); + RenderingServer::get_singleton()->canvas_item_set_parent(contact_2d_debug, current_canvas); #ifndef _3D_DISABLED PhysicsServer3D::get_singleton()->space_set_debug_contacts(find_world_3d()->get_space(), get_tree()->get_collision_debug_contact_count()); contact_3d_debug_multimesh = RenderingServer::get_singleton()->multimesh_create(); @@ -613,7 +614,7 @@ void Viewport::_process_picking() { physics_last_mouse_state.mouse_mask.clear_flag(mouse_button_to_mask(mb->get_button_index())); // If touch mouse raised, assume we don't know last mouse pos until new events come - if (mb->get_device() == InputEvent::DEVICE_ID_TOUCH_MOUSE) { + if (mb->get_device() == InputEvent::DEVICE_ID_EMULATION) { physics_has_last_mousepos = false; } } @@ -669,6 +670,25 @@ void Viewport::_process_picking() { point_params.pick_point = true; int rc = ss2d->intersect_point(point_params, res, 64); + if (physics_object_picking_sort) { + struct ComparatorCollisionObjects { + bool operator()(const PhysicsDirectSpaceState2D::ShapeResult &p_a, const PhysicsDirectSpaceState2D::ShapeResult &p_b) const { + CollisionObject2D *a = Object::cast_to<CollisionObject2D>(p_a.collider); + CollisionObject2D *b = Object::cast_to<CollisionObject2D>(p_b.collider); + if (!a || !b) { + return false; + } + int za = a->get_effective_z_index(); + int zb = b->get_effective_z_index(); + if (za != zb) { + return zb < za; + } + return a->is_greater_than(b); + } + }; + SortArray<PhysicsDirectSpaceState2D::ShapeResult, ComparatorCollisionObjects> sorter; + sorter.sort(res, rc); + } for (int i = 0; i < rc; i++) { if (res[i].collider_id.is_valid() && res[i].collider) { CollisionObject2D *co = Object::cast_to<CollisionObject2D>(res[i].collider); @@ -1152,11 +1172,16 @@ Ref<InputEvent> Viewport::_make_input_local(const Ref<InputEvent> &ev) { } Vector2 Viewport::get_mouse_position() const { - return gui.last_mouse_pos; + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_MOUSE)) { + return get_screen_transform_internal(true).affine_inverse().xform(DisplayServer::get_singleton()->mouse_get_position()); + } else { + // Fallback to Input for getting mouse position in case of emulated mouse. + return get_screen_transform_internal().affine_inverse().xform(Input::get_singleton()->get_mouse_position()); + } } void Viewport::warp_mouse(const Vector2 &p_position) { - Transform2D xform = get_screen_transform(); + Transform2D xform = get_screen_transform_internal(); Vector2 gpos = xform.xform(p_position); Input::get_singleton()->warp_mouse(gpos); } @@ -1328,7 +1353,7 @@ bool Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu Ref<InputEvent> ev = p_input; // Returns true if an event should be impacted by a control's mouse filter. - bool is_mouse_event = Ref<InputEventMouse>(p_input).is_valid(); + bool is_pointer_event = Ref<InputEventMouse>(p_input).is_valid() || Ref<InputEventScreenDrag>(p_input).is_valid() || Ref<InputEventScreenTouch>(p_input).is_valid(); Ref<InputEventMouseButton> mb = p_input; bool is_scroll_event = mb.is_valid() && @@ -1352,8 +1377,8 @@ bool Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu stopped = true; break; } - if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP && is_mouse_event && !(is_scroll_event && control->data.force_pass_scroll_events)) { - // Mouse events are stopped by default with MOUSE_FILTER_STOP, unless we have a scroll event and force_pass_scroll_events set to true + if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP && is_pointer_event && !(is_scroll_event && control->data.force_pass_scroll_events)) { + // Mouse, ScreenDrag and ScreenTouch events are stopped by default with MOUSE_FILTER_STOP, unless we have a scroll event and force_pass_scroll_events set to true stopped = true; break; } @@ -2270,6 +2295,7 @@ void Viewport::_drop_mouse_focus() { mb->set_global_position(c->get_local_mouse_position()); mb->set_button_index(MouseButton(i + 1)); mb->set_pressed(false); + mb->set_device(InputEvent::DEVICE_ID_INTERNAL); c->_call_gui_input(mb); } } @@ -2381,6 +2407,7 @@ void Viewport::_post_gui_grab_click_focus() { mb->set_position(click); mb->set_button_index(MouseButton(i + 1)); mb->set_pressed(false); + mb->set_device(InputEvent::DEVICE_ID_INTERNAL); gui.mouse_focus->_call_gui_input(mb); } } @@ -2398,6 +2425,7 @@ void Viewport::_post_gui_grab_click_focus() { mb->set_position(click); mb->set_button_index(MouseButton(i + 1)); mb->set_pressed(true); + mb->set_device(InputEvent::DEVICE_ID_INTERNAL); MessageQueue::get_singleton()->push_callable(callable_mp(gui.mouse_focus, &Control::_call_gui_input), mb); } } @@ -2533,20 +2561,14 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) { if (gui.subwindow_drag == SUB_WINDOW_DRAG_RESIZE) { Vector2i diff = mm->get_position() - gui.subwindow_drag_from; Size2i min_size = gui.subwindow_focused->get_min_size(); + Size2i min_size_clamped = gui.subwindow_focused->get_clamped_minimum_size(); - Size2i min_size_adjusted = min_size; - if (gui.subwindow_focused->is_wrapping_controls()) { - Size2i cms = gui.subwindow_focused->get_contents_minimum_size(); - min_size_adjusted.x = MAX(cms.x, min_size.x); - min_size_adjusted.y = MAX(cms.y, min_size.y); - } - - min_size_adjusted.x = MAX(min_size_adjusted.x, 1); - min_size_adjusted.y = MAX(min_size_adjusted.y, 1); + min_size_clamped.x = MAX(min_size_clamped.x, 1); + min_size_clamped.y = MAX(min_size_clamped.y, 1); Rect2i r = gui.subwindow_resize_from_rect; - Size2i limit = r.size - min_size_adjusted; + Size2i limit = r.size - min_size_clamped; switch (gui.subwindow_resize_mode) { case SUB_WINDOW_RESIZE_TOP_LEFT: { @@ -2864,6 +2886,14 @@ bool Viewport::get_physics_object_picking() { return physics_object_picking; } +void Viewport::set_physics_object_picking_sort(bool p_enable) { + physics_object_picking_sort = p_enable; +} + +bool Viewport::get_physics_object_picking_sort() { + return physics_object_picking_sort; +} + Vector2 Viewport::get_camera_coords(const Vector2 &p_viewport_coords) const { Transform2D xf = stretch_transform * global_canvas_transform; return xf.xform(p_viewport_coords); @@ -3257,6 +3287,10 @@ Viewport::SDFScale Viewport::get_sdf_scale() const { } Transform2D Viewport::get_screen_transform() const { + return get_screen_transform_internal(); +} + +Transform2D Viewport::get_screen_transform_internal(bool p_absolute_position) const { return get_final_transform(); } @@ -3798,6 +3832,8 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_physics_object_picking", "enable"), &Viewport::set_physics_object_picking); ClassDB::bind_method(D_METHOD("get_physics_object_picking"), &Viewport::get_physics_object_picking); + ClassDB::bind_method(D_METHOD("set_physics_object_picking_sort", "enable"), &Viewport::set_physics_object_picking_sort); + ClassDB::bind_method(D_METHOD("get_physics_object_picking_sort"), &Viewport::get_physics_object_picking_sort); ClassDB::bind_method(D_METHOD("get_viewport_rid"), &Viewport::get_viewport_rid); ClassDB::bind_method(D_METHOD("push_text_input", "text"), &Viewport::push_text_input); @@ -3949,6 +3985,7 @@ void Viewport::_bind_methods() { #endif ADD_GROUP("Physics", "physics_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "physics_object_picking"), "set_physics_object_picking", "get_physics_object_picking"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "physics_object_picking_sort"), "set_physics_object_picking_sort", "get_physics_object_picking_sort"); ADD_GROUP("GUI", "gui_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_disable_input"), "set_disable_input", "is_input_disabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_snap_controls_to_pixels"), "set_snap_controls_to_pixels", "is_snap_controls_to_pixels_enabled"); @@ -4192,14 +4229,14 @@ DisplayServer::WindowID SubViewport::get_window_id() const { return DisplayServer::INVALID_WINDOW_ID; } -Transform2D SubViewport::get_screen_transform() const { +Transform2D SubViewport::get_screen_transform_internal(bool p_absolute_position) const { Transform2D container_transform; SubViewportContainer *c = Object::cast_to<SubViewportContainer>(get_parent()); if (c) { if (c->is_stretch_enabled()) { container_transform.scale(Vector2(c->get_stretch_shrink(), c->get_stretch_shrink())); } - container_transform = c->get_viewport()->get_screen_transform() * c->get_global_transform_with_canvas() * container_transform; + container_transform = c->get_viewport()->get_screen_transform_internal(p_absolute_position) * c->get_global_transform_with_canvas() * container_transform; } else { WARN_PRINT_ONCE("SubViewport is not a child of a SubViewportContainer. get_screen_transform doesn't return the actual screen position."); } |