Fix propagation order for 2D physics picking events
This patch adds a viewport-configuration-option for sorting physics-picking events by the Z-Index and the scene tree position of the collision objects.
This commit is contained in:
parent
0810ecaafd
commit
6e855e3820
|
@ -277,6 +277,10 @@
|
|||
<member name="physics_object_picking" type="bool" setter="set_physics_object_picking" getter="get_physics_object_picking" default="false">
|
||||
If [code]true[/code], the objects rendered by viewport become subjects of mouse picking process.
|
||||
</member>
|
||||
<member name="physics_object_picking_sort" type="bool" setter="set_physics_object_picking_sort" getter="get_physics_object_picking_sort" default="false">
|
||||
If [code]true[/code], objects receive mouse picking events sorted primarily by their [member CanvasItem.z_index] and secondarily by their position in the scene tree. If [code]false[/code], the order is undetermined.
|
||||
[b]Note:[/b] This setting is disabled by default because of its potential expensive computational cost.
|
||||
</member>
|
||||
<member name="positional_shadow_atlas_16_bits" type="bool" setter="set_positional_shadow_atlas_16_bits" getter="get_positional_shadow_atlas_16_bits" default="true">
|
||||
</member>
|
||||
<member name="positional_shadow_atlas_quad_0" type="int" setter="set_positional_shadow_atlas_quadrant_subdiv" getter="get_positional_shadow_atlas_quadrant_subdiv" enum="Viewport.PositionalShadowAtlasQuadrantSubdiv" default="2">
|
||||
|
|
|
@ -491,6 +491,17 @@ int CanvasItem::get_z_index() const {
|
|||
return z_index;
|
||||
}
|
||||
|
||||
int CanvasItem::get_effective_z_index() const {
|
||||
int effective_z_index = z_index;
|
||||
if (is_z_relative()) {
|
||||
CanvasItem *p = get_parent_item();
|
||||
if (p) {
|
||||
effective_z_index += p->get_effective_z_index();
|
||||
}
|
||||
}
|
||||
return effective_z_index;
|
||||
}
|
||||
|
||||
void CanvasItem::set_y_sort_enabled(bool p_enabled) {
|
||||
y_sort_enabled = p_enabled;
|
||||
RS::get_singleton()->canvas_item_set_sort_children_by_y(canvas_item, y_sort_enabled);
|
||||
|
|
|
@ -246,6 +246,7 @@ public:
|
|||
|
||||
void set_z_index(int p_z);
|
||||
int get_z_index() const;
|
||||
int get_effective_z_index() const;
|
||||
|
||||
void set_z_as_relative(bool p_enabled);
|
||||
bool is_z_relative() const;
|
||||
|
|
|
@ -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"
|
||||
|
@ -664,6 +665,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);
|
||||
|
@ -2858,6 +2878,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);
|
||||
|
@ -3792,6 +3820,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);
|
||||
|
@ -3943,6 +3973,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");
|
||||
|
|
|
@ -246,6 +246,7 @@ private:
|
|||
bool snap_2d_vertices_to_pixel = false;
|
||||
|
||||
bool physics_object_picking = false;
|
||||
bool physics_object_picking_sort = false;
|
||||
List<Ref<InputEvent>> physics_picking_events;
|
||||
ObjectID physics_object_capture;
|
||||
ObjectID physics_object_over;
|
||||
|
@ -577,6 +578,8 @@ public:
|
|||
|
||||
void set_physics_object_picking(bool p_enable);
|
||||
bool get_physics_object_picking();
|
||||
void set_physics_object_picking_sort(bool p_enable);
|
||||
bool get_physics_object_picking_sort();
|
||||
|
||||
Variant gui_get_drag_data() const;
|
||||
|
||||
|
|
Loading…
Reference in New Issue