Browse Source

Merge pull request #21386 from RandomShaper/fix-picking-in-canvas-layers

Fix picking in CanvasLayer
Juan Linietsky 6 years ago
parent
commit
daa1686772

+ 9 - 0
scene/2d/canvas_item.cpp

@@ -965,6 +965,15 @@ RID CanvasItem::get_canvas() const {
 		return get_viewport()->find_world_2d()->get_canvas();
 		return get_viewport()->find_world_2d()->get_canvas();
 }
 }
 
 
+ObjectID CanvasItem::get_canvas_layer_instance_id() const {
+
+	if (canvas_layer) {
+		return canvas_layer->get_instance_id();
+	} else {
+		return 0;
+	}
+}
+
 CanvasItem *CanvasItem::get_toplevel() const {
 CanvasItem *CanvasItem::get_toplevel() const {
 
 
 	CanvasItem *ci = const_cast<CanvasItem *>(this);
 	CanvasItem *ci = const_cast<CanvasItem *>(this);

+ 1 - 0
scene/2d/canvas_item.h

@@ -352,6 +352,7 @@ public:
 	Rect2 get_viewport_rect() const;
 	Rect2 get_viewport_rect() const;
 	RID get_viewport_rid() const;
 	RID get_viewport_rid() const;
 	RID get_canvas() const;
 	RID get_canvas() const;
+	ObjectID get_canvas_layer_instance_id() const;
 	Ref<World2D> get_world_2d() const;
 	Ref<World2D> get_world_2d() const;
 
 
 	virtual void set_material(const Ref<Material> &p_material);
 	virtual void set_material(const Ref<Material> &p_material);

+ 16 - 0
scene/2d/collision_object_2d.cpp

@@ -58,6 +58,14 @@ void CollisionObject2D::_notification(int p_what) {
 			//get space
 			//get space
 		}
 		}
 
 
+		case NOTIFICATION_ENTER_CANVAS: {
+
+			if (area)
+				Physics2DServer::get_singleton()->area_attach_canvas_instance_id(rid, get_canvas_layer_instance_id());
+			else
+				Physics2DServer::get_singleton()->body_attach_canvas_instance_id(rid, get_canvas_layer_instance_id());
+		}
+
 		case NOTIFICATION_VISIBILITY_CHANGED: {
 		case NOTIFICATION_VISIBILITY_CHANGED: {
 
 
 			_update_pickable();
 			_update_pickable();
@@ -86,6 +94,14 @@ void CollisionObject2D::_notification(int p_what) {
 				Physics2DServer::get_singleton()->body_set_space(rid, RID());
 				Physics2DServer::get_singleton()->body_set_space(rid, RID());
 
 
 		} break;
 		} break;
+
+		case NOTIFICATION_EXIT_CANVAS: {
+
+			if (area)
+				Physics2DServer::get_singleton()->area_attach_canvas_instance_id(rid, 0);
+			else
+				Physics2DServer::get_singleton()->body_attach_canvas_instance_id(rid, 0);
+		}
 	}
 	}
 }
 }
 
 

+ 5 - 0
scene/main/canvas_layer.cpp

@@ -146,6 +146,8 @@ void CanvasLayer::_notification(int p_what) {
 				vp = Node::get_viewport();
 				vp = Node::get_viewport();
 			}
 			}
 			ERR_FAIL_COND(!vp);
 			ERR_FAIL_COND(!vp);
+
+			vp->_canvas_layer_add(this);
 			viewport = vp->get_viewport_rid();
 			viewport = vp->get_viewport_rid();
 
 
 			VisualServer::get_singleton()->viewport_attach_canvas(viewport, canvas);
 			VisualServer::get_singleton()->viewport_attach_canvas(viewport, canvas);
@@ -155,6 +157,7 @@ void CanvasLayer::_notification(int p_what) {
 		} break;
 		} break;
 		case NOTIFICATION_EXIT_TREE: {
 		case NOTIFICATION_EXIT_TREE: {
 
 
+			vp->_canvas_layer_remove(this);
 			VisualServer::get_singleton()->viewport_remove_canvas(viewport, canvas);
 			VisualServer::get_singleton()->viewport_remove_canvas(viewport, canvas);
 			viewport = RID();
 			viewport = RID();
 
 
@@ -183,6 +186,7 @@ RID CanvasLayer::get_viewport() const {
 void CanvasLayer::set_custom_viewport(Node *p_viewport) {
 void CanvasLayer::set_custom_viewport(Node *p_viewport) {
 	ERR_FAIL_NULL(p_viewport);
 	ERR_FAIL_NULL(p_viewport);
 	if (is_inside_tree()) {
 	if (is_inside_tree()) {
+		vp->_canvas_layer_remove(this);
 		VisualServer::get_singleton()->viewport_remove_canvas(viewport, canvas);
 		VisualServer::get_singleton()->viewport_remove_canvas(viewport, canvas);
 		viewport = RID();
 		viewport = RID();
 	}
 	}
@@ -202,6 +206,7 @@ void CanvasLayer::set_custom_viewport(Node *p_viewport) {
 		else
 		else
 			vp = Node::get_viewport();
 			vp = Node::get_viewport();
 
 
+		vp->_canvas_layer_add(this);
 		viewport = vp->get_viewport_rid();
 		viewport = vp->get_viewport_rid();
 
 
 		VisualServer::get_singleton()->viewport_attach_canvas(viewport, canvas);
 		VisualServer::get_singleton()->viewport_attach_canvas(viewport, canvas);

+ 43 - 16
scene/main/viewport.cpp

@@ -45,6 +45,7 @@
 #include "scene/gui/panel.h"
 #include "scene/gui/panel.h"
 #include "scene/gui/panel_container.h"
 #include "scene/gui/panel_container.h"
 #include "scene/gui/popup_menu.h"
 #include "scene/gui/popup_menu.h"
+#include "scene/main/canvas_layer.h"
 #include "scene/main/timer.h"
 #include "scene/main/timer.h"
 #include "scene/resources/mesh.h"
 #include "scene/resources/mesh.h"
 #include "scene/scene_string_names.h"
 #include "scene/scene_string_names.h"
@@ -443,24 +444,39 @@ void Viewport::_notification(int p_what) {
 
 
 						uint64_t frame = get_tree()->get_frame();
 						uint64_t frame = get_tree()->get_frame();
 
 
-						Vector2 point = get_canvas_transform().affine_inverse().xform(pos);
 						Physics2DDirectSpaceState::ShapeResult res[64];
 						Physics2DDirectSpaceState::ShapeResult res[64];
-						int rc = ss2d->intersect_point(point, res, 64, Set<RID>(), 0xFFFFFFFF, true, true, true);
-						for (int i = 0; i < rc; i++) {
-
-							if (res[i].collider_id && res[i].collider) {
-								CollisionObject2D *co = Object::cast_to<CollisionObject2D>(res[i].collider);
-								if (co) {
-
-									Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.find(res[i].collider_id);
-									if (!E) {
-										E = physics_2d_mouseover.insert(res[i].collider_id, frame);
-										co->_mouse_enter();
-									} else {
-										E->get() = frame;
-									}
+						for (Set<CanvasLayer *>::Element *E = canvas_layers.front(); E; E = E->next()) {
+							Transform2D canvas_transform;
+							ObjectID canvas_layer_id;
+							if (E->get()) {
+								// A descendant CanvasLayer
+								canvas_transform = E->get()->get_transform();
+								canvas_layer_id = E->get()->get_instance_id();
+							} else {
+								// This Viewport's builtin canvas
+								canvas_transform = get_canvas_transform();
+								canvas_layer_id = 0;
+							}
+
+							Vector2 point = canvas_transform.affine_inverse().xform(pos);
+
+							int rc = ss2d->intersect_point_on_canvas(point, canvas_layer_id, res, 64, Set<RID>(), 0xFFFFFFFF, true, true, true);
+							for (int i = 0; i < rc; i++) {
+
+								if (res[i].collider_id && res[i].collider) {
+									CollisionObject2D *co = Object::cast_to<CollisionObject2D>(res[i].collider);
+									if (co) {
+
+										Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.find(res[i].collider_id);
+										if (!E) {
+											E = physics_2d_mouseover.insert(res[i].collider_id, frame);
+											co->_mouse_enter();
+										} else {
+											E->get() = frame;
+										}
 
 
-									co->_input_event(this, ev, res[i].shape);
+										co->_input_event(this, ev, res[i].shape);
+									}
 								}
 								}
 							}
 							}
 						}
 						}
@@ -854,6 +870,16 @@ void Viewport::_camera_make_next_current(Camera *p_exclude) {
 }
 }
 #endif
 #endif
 
 
+void Viewport::_canvas_layer_add(CanvasLayer *p_canvas_layer) {
+
+	canvas_layers.insert(p_canvas_layer);
+}
+
+void Viewport::_canvas_layer_remove(CanvasLayer *p_canvas_layer) {
+
+	canvas_layers.erase(p_canvas_layer);
+}
+
 void Viewport::set_transparent_background(bool p_enable) {
 void Viewport::set_transparent_background(bool p_enable) {
 
 
 	transparent_bg = p_enable;
 	transparent_bg = p_enable;
@@ -2911,6 +2937,7 @@ Viewport::Viewport() {
 	parent = NULL;
 	parent = NULL;
 	listener = NULL;
 	listener = NULL;
 	camera = NULL;
 	camera = NULL;
+	canvas_layers.insert(NULL); // This eases picking code (interpreted as the canvas of the Viewport)
 	arvr = false;
 	arvr = false;
 	size_override = false;
 	size_override = false;
 	size_override_stretch = false;
 	size_override_stretch = false;

+ 6 - 0
scene/main/viewport.h

@@ -45,6 +45,7 @@ class Camera2D;
 class Listener;
 class Listener;
 class Control;
 class Control;
 class CanvasItem;
 class CanvasItem;
+class CanvasLayer;
 class Panel;
 class Panel;
 class Label;
 class Label;
 class Timer;
 class Timer;
@@ -163,6 +164,7 @@ private:
 
 
 	Camera *camera;
 	Camera *camera;
 	Set<Camera *> cameras;
 	Set<Camera *> cameras;
+	Set<CanvasLayer *> canvas_layers;
 
 
 	RID viewport;
 	RID viewport;
 	RID current_canvas;
 	RID current_canvas;
@@ -354,6 +356,10 @@ private:
 	void _camera_remove(Camera *p_camera);
 	void _camera_remove(Camera *p_camera);
 	void _camera_make_next_current(Camera *p_exclude);
 	void _camera_make_next_current(Camera *p_exclude);
 
 
+	friend class CanvasLayer;
+	void _canvas_layer_add(CanvasLayer *p_canvas_layer);
+	void _canvas_layer_remove(CanvasLayer *p_canvas_layer);
+
 protected:
 protected:
 	void _notification(int p_what);
 	void _notification(int p_what);
 	static void _bind_methods();
 	static void _bind_methods();

+ 1 - 0
servers/physics_2d/collision_object_2d_sw.cpp

@@ -244,6 +244,7 @@ CollisionObject2DSW::CollisionObject2DSW(Type p_type) {
 	type = p_type;
 	type = p_type;
 	space = NULL;
 	space = NULL;
 	instance_id = 0;
 	instance_id = 0;
+	canvas_instance_id = 0;
 	collision_mask = 1;
 	collision_mask = 1;
 	collision_layer = 1;
 	collision_layer = 1;
 	pickable = true;
 	pickable = true;

+ 4 - 0
servers/physics_2d/collision_object_2d_sw.h

@@ -49,6 +49,7 @@ private:
 	Type type;
 	Type type;
 	RID self;
 	RID self;
 	ObjectID instance_id;
 	ObjectID instance_id;
+	ObjectID canvas_instance_id;
 	bool pickable;
 	bool pickable;
 
 
 	struct Shape {
 	struct Shape {
@@ -102,6 +103,9 @@ public:
 	_FORCE_INLINE_ void set_instance_id(const ObjectID &p_instance_id) { instance_id = p_instance_id; }
 	_FORCE_INLINE_ void set_instance_id(const ObjectID &p_instance_id) { instance_id = p_instance_id; }
 	_FORCE_INLINE_ ObjectID get_instance_id() const { return instance_id; }
 	_FORCE_INLINE_ ObjectID get_instance_id() const { return instance_id; }
 
 
+	_FORCE_INLINE_ void set_canvas_instance_id(const ObjectID &p_canvas_instance_id) { canvas_instance_id = p_canvas_instance_id; }
+	_FORCE_INLINE_ ObjectID get_canvas_instance_id() const { return canvas_instance_id; }
+
 	void _shape_changed();
 	void _shape_changed();
 
 
 	_FORCE_INLINE_ Type get_type() const { return type; }
 	_FORCE_INLINE_ Type get_type() const { return type; }

+ 37 - 0
servers/physics_2d/physics_2d_server_sw.cpp

@@ -469,6 +469,27 @@ ObjectID Physics2DServerSW::area_get_object_instance_id(RID p_area) const {
 	return area->get_instance_id();
 	return area->get_instance_id();
 }
 }
 
 
+void Physics2DServerSW::area_attach_canvas_instance_id(RID p_area, ObjectID p_ID) {
+
+	if (space_owner.owns(p_area)) {
+		Space2DSW *space = space_owner.get(p_area);
+		p_area = space->get_default_area()->get_self();
+	}
+	Area2DSW *area = area_owner.get(p_area);
+	ERR_FAIL_COND(!area);
+	area->set_canvas_instance_id(p_ID);
+}
+ObjectID Physics2DServerSW::area_get_canvas_instance_id(RID p_area) const {
+
+	if (space_owner.owns(p_area)) {
+		Space2DSW *space = space_owner.get(p_area);
+		p_area = space->get_default_area()->get_self();
+	}
+	Area2DSW *area = area_owner.get(p_area);
+	ERR_FAIL_COND_V(!area, 0);
+	return area->get_canvas_instance_id();
+}
+
 void Physics2DServerSW::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) {
 void Physics2DServerSW::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) {
 
 
 	if (space_owner.owns(p_area)) {
 	if (space_owner.owns(p_area)) {
@@ -744,6 +765,22 @@ uint32_t Physics2DServerSW::body_get_object_instance_id(RID p_body) const {
 	return body->get_instance_id();
 	return body->get_instance_id();
 };
 };
 
 
+void Physics2DServerSW::body_attach_canvas_instance_id(RID p_body, uint32_t p_ID) {
+
+	Body2DSW *body = body_owner.get(p_body);
+	ERR_FAIL_COND(!body);
+
+	body->set_canvas_instance_id(p_ID);
+};
+
+uint32_t Physics2DServerSW::body_get_canvas_instance_id(RID p_body) const {
+
+	Body2DSW *body = body_owner.get(p_body);
+	ERR_FAIL_COND_V(!body, 0);
+
+	return body->get_canvas_instance_id();
+};
+
 void Physics2DServerSW::body_set_collision_layer(RID p_body, uint32_t p_layer) {
 void Physics2DServerSW::body_set_collision_layer(RID p_body, uint32_t p_layer) {
 
 
 	Body2DSW *body = body_owner.get(p_body);
 	Body2DSW *body = body_owner.get(p_body);

+ 6 - 0
servers/physics_2d/physics_2d_server_sw.h

@@ -144,6 +144,9 @@ public:
 	virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID);
 	virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID);
 	virtual ObjectID area_get_object_instance_id(RID p_area) const;
 	virtual ObjectID area_get_object_instance_id(RID p_area) const;
 
 
+	virtual void area_attach_canvas_instance_id(RID p_area, ObjectID p_ID);
+	virtual ObjectID area_get_canvas_instance_id(RID p_area) const;
+
 	virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value);
 	virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value);
 	virtual void area_set_transform(RID p_area, const Transform2D &p_transform);
 	virtual void area_set_transform(RID p_area, const Transform2D &p_transform);
 
 
@@ -188,6 +191,9 @@ public:
 	virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID);
 	virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID);
 	virtual uint32_t body_get_object_instance_id(RID p_body) const;
 	virtual uint32_t body_get_object_instance_id(RID p_body) const;
 
 
+	virtual void body_attach_canvas_instance_id(RID p_body, uint32_t p_ID);
+	virtual uint32_t body_get_canvas_instance_id(RID p_body) const;
+
 	virtual void body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode);
 	virtual void body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode);
 	virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const;
 	virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const;
 
 

+ 6 - 0
servers/physics_2d/physics_2d_server_wrap_mt.h

@@ -154,6 +154,9 @@ public:
 	FUNC2(area_attach_object_instance_id, RID, ObjectID);
 	FUNC2(area_attach_object_instance_id, RID, ObjectID);
 	FUNC1RC(ObjectID, area_get_object_instance_id, RID);
 	FUNC1RC(ObjectID, area_get_object_instance_id, RID);
 
 
+	FUNC2(area_attach_canvas_instance_id, RID, ObjectID);
+	FUNC1RC(ObjectID, area_get_canvas_instance_id, RID);
+
 	FUNC3(area_set_param, RID, AreaParameter, const Variant &);
 	FUNC3(area_set_param, RID, AreaParameter, const Variant &);
 	FUNC2(area_set_transform, RID, const Transform2D &);
 	FUNC2(area_set_transform, RID, const Transform2D &);
 
 
@@ -199,6 +202,9 @@ public:
 	FUNC2(body_attach_object_instance_id, RID, uint32_t);
 	FUNC2(body_attach_object_instance_id, RID, uint32_t);
 	FUNC1RC(uint32_t, body_get_object_instance_id, RID);
 	FUNC1RC(uint32_t, body_get_object_instance_id, RID);
 
 
+	FUNC2(body_attach_canvas_instance_id, RID, uint32_t);
+	FUNC1RC(uint32_t, body_get_canvas_instance_id, RID);
+
 	FUNC2(body_set_continuous_collision_detection_mode, RID, CCDMode);
 	FUNC2(body_set_continuous_collision_detection_mode, RID, CCDMode);
 	FUNC1RC(CCDMode, body_get_continuous_collision_detection_mode, RID);
 	FUNC1RC(CCDMode, body_get_continuous_collision_detection_mode, RID);
 
 

+ 14 - 1
servers/physics_2d/space_2d_sw.cpp

@@ -49,7 +49,7 @@ _FORCE_INLINE_ static bool _can_collide_with(CollisionObject2DSW *p_object, uint
 	return true;
 	return true;
 }
 }
 
 
-int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) {
+int Physics2DDirectSpaceStateSW::_intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) {
 
 
 	if (p_result_max <= 0)
 	if (p_result_max <= 0)
 		return 0;
 		return 0;
@@ -75,6 +75,9 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeRe
 		if (p_pick_point && !col_obj->is_pickable())
 		if (p_pick_point && !col_obj->is_pickable())
 			continue;
 			continue;
 
 
+		if (p_filter_by_canvas && col_obj->get_canvas_instance_id() != p_canvas_instance_id)
+			continue;
+
 		int shape_idx = space->intersection_query_subindex_results[i];
 		int shape_idx = space->intersection_query_subindex_results[i];
 
 
 		Shape2DSW *shape = col_obj->get_shape(shape_idx);
 		Shape2DSW *shape = col_obj->get_shape(shape_idx);
@@ -100,6 +103,16 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeRe
 	return cc;
 	return cc;
 }
 }
 
 
+int Physics2DDirectSpaceStateSW::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) {
+
+	return _intersect_point_impl(p_point, r_results, p_result_max, p_exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas, p_pick_point);
+}
+
+int Physics2DDirectSpaceStateSW::intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) {
+
+	return _intersect_point_impl(p_point, r_results, p_result_max, p_exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas, p_pick_point, true, p_canvas_instance_id);
+}
+
 bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
 bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
 
 
 	ERR_FAIL_COND_V(space->locked, false);
 	ERR_FAIL_COND_V(space->locked, false);

+ 3 - 0
servers/physics_2d/space_2d_sw.h

@@ -45,10 +45,13 @@ class Physics2DDirectSpaceStateSW : public Physics2DDirectSpaceState {
 
 
 	GDCLASS(Physics2DDirectSpaceStateSW, Physics2DDirectSpaceState);
 	GDCLASS(Physics2DDirectSpaceStateSW, Physics2DDirectSpaceState);
 
 
+	int _intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = 0);
+
 public:
 public:
 	Space2DSW *space;
 	Space2DSW *space;
 
 
 	virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false);
 	virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false);
+	virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false);
 	virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
 	virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
 	virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
 	virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
 	virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
 	virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);

+ 24 - 2
servers/physics_2d_server.cpp

@@ -328,7 +328,7 @@ Array Physics2DDirectSpaceState::_cast_motion(const Ref<Physics2DShapeQueryParam
 	return ret;
 	return ret;
 }
 }
 
 
-Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) {
+Array Physics2DDirectSpaceState::_intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) {
 
 
 	Set<RID> exclude;
 	Set<RID> exclude;
 	for (int i = 0; i < p_exclude.size(); i++)
 	for (int i = 0; i < p_exclude.size(); i++)
@@ -337,7 +337,12 @@ Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_
 	Vector<ShapeResult> ret;
 	Vector<ShapeResult> ret;
 	ret.resize(p_max_results);
 	ret.resize(p_max_results);
 
 
-	int rc = intersect_point(p_point, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
+	int rc;
+	if (p_filter_by_canvas)
+		rc = intersect_point(p_point, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
+	else
+		rc = intersect_point_on_canvas(p_point, p_canvas_instance_id, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
+
 	if (rc == 0)
 	if (rc == 0)
 		return Array();
 		return Array();
 
 
@@ -356,6 +361,16 @@ Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_
 	return r;
 	return r;
 }
 }
 
 
+Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) {
+
+	return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas);
+}
+
+Array Physics2DDirectSpaceState::_intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) {
+
+	return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas, true, p_canvas_intance_id);
+}
+
 Array Physics2DDirectSpaceState::_collide_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results) {
 Array Physics2DDirectSpaceState::_collide_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results) {
 
 
 	ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
 	ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
@@ -400,6 +415,7 @@ Physics2DDirectSpaceState::Physics2DDirectSpaceState() {
 void Physics2DDirectSpaceState::_bind_methods() {
 void Physics2DDirectSpaceState::_bind_methods() {
 
 
 	ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
 	ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
+	ClassDB::bind_method(D_METHOD("intersect_point_on_canvas", "point", "canvas_instance_id", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_point_on_canvas, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
 	ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
 	ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false));
 	ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &Physics2DDirectSpaceState::_intersect_shape, DEFVAL(32));
 	ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &Physics2DDirectSpaceState::_intersect_shape, DEFVAL(32));
 	ClassDB::bind_method(D_METHOD("cast_motion", "shape"), &Physics2DDirectSpaceState::_cast_motion);
 	ClassDB::bind_method(D_METHOD("cast_motion", "shape"), &Physics2DDirectSpaceState::_cast_motion);
@@ -575,6 +591,9 @@ void Physics2DServer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("area_attach_object_instance_id", "area", "id"), &Physics2DServer::area_attach_object_instance_id);
 	ClassDB::bind_method(D_METHOD("area_attach_object_instance_id", "area", "id"), &Physics2DServer::area_attach_object_instance_id);
 	ClassDB::bind_method(D_METHOD("area_get_object_instance_id", "area"), &Physics2DServer::area_get_object_instance_id);
 	ClassDB::bind_method(D_METHOD("area_get_object_instance_id", "area"), &Physics2DServer::area_get_object_instance_id);
 
 
+	ClassDB::bind_method(D_METHOD("area_attach_canvas_instance_id", "area", "id"), &Physics2DServer::area_attach_canvas_instance_id);
+	ClassDB::bind_method(D_METHOD("area_get_canvas_instance_id", "area"), &Physics2DServer::area_get_canvas_instance_id);
+
 	ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &Physics2DServer::area_set_monitor_callback);
 	ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &Physics2DServer::area_set_monitor_callback);
 	ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "receiver", "method"), &Physics2DServer::area_set_area_monitor_callback);
 	ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "receiver", "method"), &Physics2DServer::area_set_area_monitor_callback);
 	ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &Physics2DServer::area_set_monitorable);
 	ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &Physics2DServer::area_set_monitorable);
@@ -606,6 +625,9 @@ void Physics2DServer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("body_attach_object_instance_id", "body", "id"), &Physics2DServer::body_attach_object_instance_id);
 	ClassDB::bind_method(D_METHOD("body_attach_object_instance_id", "body", "id"), &Physics2DServer::body_attach_object_instance_id);
 	ClassDB::bind_method(D_METHOD("body_get_object_instance_id", "body"), &Physics2DServer::body_get_object_instance_id);
 	ClassDB::bind_method(D_METHOD("body_get_object_instance_id", "body"), &Physics2DServer::body_get_object_instance_id);
 
 
+	ClassDB::bind_method(D_METHOD("body_attach_canvas_instance_id", "body", "id"), &Physics2DServer::body_attach_canvas_instance_id);
+	ClassDB::bind_method(D_METHOD("body_get_canvas_instance_id", "body"), &Physics2DServer::body_get_canvas_instance_id);
+
 	ClassDB::bind_method(D_METHOD("body_set_continuous_collision_detection_mode", "body", "mode"), &Physics2DServer::body_set_continuous_collision_detection_mode);
 	ClassDB::bind_method(D_METHOD("body_set_continuous_collision_detection_mode", "body", "mode"), &Physics2DServer::body_set_continuous_collision_detection_mode);
 	ClassDB::bind_method(D_METHOD("body_get_continuous_collision_detection_mode", "body"), &Physics2DServer::body_get_continuous_collision_detection_mode);
 	ClassDB::bind_method(D_METHOD("body_get_continuous_collision_detection_mode", "body"), &Physics2DServer::body_get_continuous_collision_detection_mode);
 
 

+ 9 - 1
servers/physics_2d_server.h

@@ -147,8 +147,9 @@ class Physics2DDirectSpaceState : public Object {
 	GDCLASS(Physics2DDirectSpaceState, Object);
 	GDCLASS(Physics2DDirectSpaceState, Object);
 
 
 	Dictionary _intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
 	Dictionary _intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
-
 	Array _intersect_point(const Vector2 &p_point, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
 	Array _intersect_point(const Vector2 &p_point, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
+	Array _intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false);
+	Array _intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclud, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = 0);
 	Array _intersect_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results = 32);
 	Array _intersect_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results = 32);
 	Array _cast_motion(const Ref<Physics2DShapeQueryParameters> &p_shape_query);
 	Array _cast_motion(const Ref<Physics2DShapeQueryParameters> &p_shape_query);
 	Array _collide_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results = 32);
 	Array _collide_shape(const Ref<Physics2DShapeQueryParameters> &p_shape_query, int p_max_results = 32);
@@ -181,6 +182,7 @@ public:
 	};
 	};
 
 
 	virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
 	virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
+	virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
 
 
 	virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
 	virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
 
 
@@ -348,6 +350,9 @@ public:
 	virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID) = 0;
 	virtual void area_attach_object_instance_id(RID p_area, ObjectID p_ID) = 0;
 	virtual ObjectID area_get_object_instance_id(RID p_area) const = 0;
 	virtual ObjectID area_get_object_instance_id(RID p_area) const = 0;
 
 
+	virtual void area_attach_canvas_instance_id(RID p_area, ObjectID p_ID) = 0;
+	virtual ObjectID area_get_canvas_instance_id(RID p_area) const = 0;
+
 	virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) = 0;
 	virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) = 0;
 	virtual void area_set_transform(RID p_area, const Transform2D &p_transform) = 0;
 	virtual void area_set_transform(RID p_area, const Transform2D &p_transform) = 0;
 
 
@@ -401,6 +406,9 @@ public:
 	virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID) = 0;
 	virtual void body_attach_object_instance_id(RID p_body, uint32_t p_ID) = 0;
 	virtual uint32_t body_get_object_instance_id(RID p_body) const = 0;
 	virtual uint32_t body_get_object_instance_id(RID p_body) const = 0;
 
 
+	virtual void body_attach_canvas_instance_id(RID p_body, uint32_t p_ID) = 0;
+	virtual uint32_t body_get_canvas_instance_id(RID p_body) const = 0;
+
 	enum CCDMode {
 	enum CCDMode {
 		CCD_MODE_DISABLED,
 		CCD_MODE_DISABLED,
 		CCD_MODE_CAST_RAY,
 		CCD_MODE_CAST_RAY,