Browse Source

Use `Callable` in Area monitor callback

rafallus 3 years ago
parent
commit
770e3a8e51

+ 2 - 4
doc/classes/PhysicsServer2D.xml

@@ -123,8 +123,7 @@
 		<method name="area_set_area_monitor_callback">
 			<return type="void" />
 			<argument index="0" name="area" type="RID" />
-			<argument index="1" name="receiver" type="Object" />
-			<argument index="2" name="method" type="StringName" />
+			<argument index="1" name="callback" type="Callable" />
 			<description>
 			</description>
 		</method>
@@ -147,8 +146,7 @@
 		<method name="area_set_monitor_callback">
 			<return type="void" />
 			<argument index="0" name="area" type="RID" />
-			<argument index="1" name="receiver" type="Object" />
-			<argument index="2" name="method" type="StringName" />
+			<argument index="1" name="callback" type="Callable" />
 			<description>
 				Sets the function to call when any body/area enters or exits the area. This callback will be called for any object interacting with the area, and takes five parameters:
 				1: [constant AREA_BODY_ADDED] or [constant AREA_BODY_REMOVED], depending on whether the object entered or exited the area.

+ 2 - 4
doc/classes/PhysicsServer3D.xml

@@ -110,8 +110,7 @@
 		<method name="area_set_area_monitor_callback">
 			<return type="void" />
 			<argument index="0" name="area" type="RID" />
-			<argument index="1" name="receiver" type="Object" />
-			<argument index="2" name="method" type="StringName" />
+			<argument index="1" name="callback" type="Callable" />
 			<description>
 			</description>
 		</method>
@@ -134,8 +133,7 @@
 		<method name="area_set_monitor_callback">
 			<return type="void" />
 			<argument index="0" name="area" type="RID" />
-			<argument index="1" name="receiver" type="Object" />
-			<argument index="2" name="method" type="StringName" />
+			<argument index="1" name="callback" type="Callable" />
 			<description>
 				Sets the function to call when any body/area enters or exits the area. This callback will be called for any object interacting with the area, and takes five parameters:
 				1: [constant AREA_BODY_ADDED] or [constant AREA_BODY_REMOVED], depending on whether the object entered or exited the area.

+ 8 - 9
modules/bullet/area_bullet.cpp

@@ -94,10 +94,9 @@ void AreaBullet::dispatch_callbacks() {
 
 void AreaBullet::call_event(CollisionObjectBullet *p_otherObject, PhysicsServer3D::AreaBodyStatus p_status) {
 	InOutEventCallback &event = eventsCallbacks[static_cast<int>(p_otherObject->getType())];
-	Object *areaGodoObject = ObjectDB::get_instance(event.event_callback_id);
 
-	if (!areaGodoObject) {
-		event.event_callback_id = ObjectID();
+	if (!event.event_callback.is_valid()) {
+		event.event_callback = Callable();
 		return;
 	}
 
@@ -108,7 +107,8 @@ void AreaBullet::call_event(CollisionObjectBullet *p_otherObject, PhysicsServer3
 	call_event_res[4] = 0; // self_shape ID
 
 	Callable::CallError outResp;
-	areaGodoObject->call(event.event_callback_method, (const Variant **)call_event_res_ptr, 5, outResp);
+	Variant ret;
+	event.event_callback.call((const Variant **)call_event_res, 5, ret, outResp);
 }
 
 void AreaBullet::scratch() {
@@ -267,13 +267,12 @@ Variant AreaBullet::get_param(PhysicsServer3D::AreaParameter p_param) const {
 	}
 }
 
-void AreaBullet::set_event_callback(Type p_callbackObjectType, ObjectID p_id, const StringName &p_method) {
+void AreaBullet::set_event_callback(Type p_callbackObjectType, const Callable &p_callback) {
 	InOutEventCallback &ev = eventsCallbacks[static_cast<int>(p_callbackObjectType)];
-	ev.event_callback_id = p_id;
-	ev.event_callback_method = p_method;
+	ev.event_callback = p_callback;
 
 	/// Set if monitoring
-	if (eventsCallbacks[0].event_callback_id.is_valid() || eventsCallbacks[1].event_callback_id.is_valid()) {
+	if (!eventsCallbacks[0].event_callback.is_null() || !eventsCallbacks[1].event_callback.is_null()) {
 		set_godot_object_flags(get_godot_object_flags() | GOF_IS_MONITORING_AREA);
 	} else {
 		set_godot_object_flags(get_godot_object_flags() & (~GOF_IS_MONITORING_AREA));
@@ -281,7 +280,7 @@ void AreaBullet::set_event_callback(Type p_callbackObjectType, ObjectID p_id, co
 }
 
 bool AreaBullet::has_event_callback(Type p_callbackObjectType) {
-	return eventsCallbacks[static_cast<int>(p_callbackObjectType)].event_callback_id.is_valid();
+	return !eventsCallbacks[static_cast<int>(p_callbackObjectType)].event_callback.is_null();
 }
 
 void AreaBullet::on_enter_area(AreaBullet *p_area) {

+ 2 - 3
modules/bullet/area_bullet.h

@@ -47,8 +47,7 @@ class AreaBullet : public RigidCollisionObjectBullet {
 
 public:
 	struct InOutEventCallback {
-		ObjectID event_callback_id;
-		StringName event_callback_method;
+		Callable event_callback;
 
 		InOutEventCallback() {}
 	};
@@ -162,7 +161,7 @@ public:
 	void set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value);
 	Variant get_param(PhysicsServer3D::AreaParameter p_param) const;
 
-	void set_event_callback(Type p_callbackObjectType, ObjectID p_id, const StringName &p_method);
+	void set_event_callback(Type p_callbackObjectType, const Callable &p_callback);
 	bool has_event_callback(Type p_callbackObjectType);
 
 	virtual void on_enter_area(AreaBullet *p_area);

+ 4 - 4
modules/bullet/bullet_physics_server.cpp

@@ -413,18 +413,18 @@ void BulletPhysicsServer3D::area_set_monitorable(RID p_area, bool p_monitorable)
 	area->set_monitorable(p_monitorable);
 }
 
-void BulletPhysicsServer3D::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
+void BulletPhysicsServer3D::area_set_monitor_callback(RID p_area, const Callable &p_callback) {
 	AreaBullet *area = area_owner.get_or_null(p_area);
 	ERR_FAIL_COND(!area);
 
-	area->set_event_callback(CollisionObjectBullet::TYPE_RIGID_BODY, p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method);
+	area->set_event_callback(CollisionObjectBullet::TYPE_RIGID_BODY, p_callback.is_valid() ? p_callback : Callable());
 }
 
-void BulletPhysicsServer3D::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
+void BulletPhysicsServer3D::area_set_area_monitor_callback(RID p_area, const Callable &p_callback) {
 	AreaBullet *area = area_owner.get_or_null(p_area);
 	ERR_FAIL_COND(!area);
 
-	area->set_event_callback(CollisionObjectBullet::TYPE_AREA, p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method);
+	area->set_event_callback(CollisionObjectBullet::TYPE_AREA, p_callback.is_valid() ? p_callback : Callable());
 }
 
 void BulletPhysicsServer3D::area_set_ray_pickable(RID p_area, bool p_enable) {

+ 2 - 2
modules/bullet/bullet_physics_server.h

@@ -160,8 +160,8 @@ public:
 	virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) override;
 
 	virtual void area_set_monitorable(RID p_area, bool p_monitorable) override;
-	virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override;
-	virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override;
+	virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) override;
+	virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) override;
 	virtual void area_set_ray_pickable(RID p_area, bool p_enable) override;
 
 	/* RIGID BODY API */

+ 4 - 8
scene/2d/area_2d.cpp

@@ -369,12 +369,11 @@ void Area2D::set_monitoring(bool p_enable) {
 	monitoring = p_enable;
 
 	if (monitoring) {
-		PhysicsServer2D::get_singleton()->area_set_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_body_inout);
-		PhysicsServer2D::get_singleton()->area_set_area_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_area_inout);
-
+		PhysicsServer2D::get_singleton()->area_set_monitor_callback(get_rid(), callable_mp(this, &Area2D::_body_inout));
+		PhysicsServer2D::get_singleton()->area_set_area_monitor_callback(get_rid(), callable_mp(this, &Area2D::_area_inout));
 	} else {
-		PhysicsServer2D::get_singleton()->area_set_monitor_callback(get_rid(), nullptr, StringName());
-		PhysicsServer2D::get_singleton()->area_set_area_monitor_callback(get_rid(), nullptr, StringName());
+		PhysicsServer2D::get_singleton()->area_set_monitor_callback(get_rid(), Callable());
+		PhysicsServer2D::get_singleton()->area_set_area_monitor_callback(get_rid(), Callable());
 		_clear_monitoring();
 	}
 }
@@ -530,9 +529,6 @@ void Area2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_audio_bus_override", "enable"), &Area2D::set_audio_bus_override);
 	ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area2D::is_overriding_audio_bus);
 
-	ClassDB::bind_method(D_METHOD("_body_inout"), &Area2D::_body_inout);
-	ClassDB::bind_method(D_METHOD("_area_inout"), &Area2D::_area_inout);
-
 	ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
 	ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
 	ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D")));

+ 4 - 7
scene/3d/area_3d.cpp

@@ -334,11 +334,11 @@ void Area3D::set_monitoring(bool p_enable) {
 	monitoring = p_enable;
 
 	if (monitoring) {
-		PhysicsServer3D::get_singleton()->area_set_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_body_inout);
-		PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_area_inout);
+		PhysicsServer3D::get_singleton()->area_set_monitor_callback(get_rid(), callable_mp(this, &Area3D::_body_inout));
+		PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), callable_mp(this, &Area3D::_area_inout));
 	} else {
-		PhysicsServer3D::get_singleton()->area_set_monitor_callback(get_rid(), nullptr, StringName());
-		PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), nullptr, StringName());
+		PhysicsServer3D::get_singleton()->area_set_monitor_callback(get_rid(), Callable());
+		PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), Callable());
 		_clear_monitoring();
 	}
 }
@@ -630,9 +630,6 @@ void Area3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("overlaps_body", "body"), &Area3D::overlaps_body);
 	ClassDB::bind_method(D_METHOD("overlaps_area", "area"), &Area3D::overlaps_area);
 
-	ClassDB::bind_method(D_METHOD("_body_inout"), &Area3D::_body_inout);
-	ClassDB::bind_method(D_METHOD("_area_inout"), &Area3D::_area_inout);
-
 	ClassDB::bind_method(D_METHOD("set_audio_bus_override", "enable"), &Area3D::set_audio_bus_override);
 	ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area3D::is_overriding_audio_bus);
 

+ 66 - 66
servers/physics_2d/godot_area_2d.cpp

@@ -77,16 +77,17 @@ void GodotArea2D::set_space(GodotSpace2D *p_space) {
 	_set_space(p_space);
 }
 
-void GodotArea2D::set_monitor_callback(ObjectID p_id, const StringName &p_method) {
-	if (p_id == monitor_callback_id) {
-		monitor_callback_method = p_method;
+void GodotArea2D::set_monitor_callback(const Callable &p_callback) {
+	ObjectID id = p_callback.get_object_id();
+
+	if (id == monitor_callback.get_object_id()) {
+		monitor_callback = p_callback;
 		return;
 	}
 
 	_unregister_shapes();
 
-	monitor_callback_id = p_id;
-	monitor_callback_method = p_method;
+	monitor_callback = p_callback;
 
 	monitored_bodies.clear();
 	monitored_areas.clear();
@@ -98,16 +99,17 @@ void GodotArea2D::set_monitor_callback(ObjectID p_id, const StringName &p_method
 	}
 }
 
-void GodotArea2D::set_area_monitor_callback(ObjectID p_id, const StringName &p_method) {
-	if (p_id == area_monitor_callback_id) {
-		area_monitor_callback_method = p_method;
+void GodotArea2D::set_area_monitor_callback(const Callable &p_callback) {
+	ObjectID id = p_callback.get_object_id();
+
+	if (id == area_monitor_callback.get_object_id()) {
+		area_monitor_callback = p_callback;
 		return;
 	}
 
 	_unregister_shapes();
 
-	area_monitor_callback_id = p_id;
-	area_monitor_callback_method = p_method;
+	area_monitor_callback = p_callback;
 
 	monitored_bodies.clear();
 	monitored_areas.clear();
@@ -199,77 +201,75 @@ void GodotArea2D::set_monitorable(bool p_monitorable) {
 }
 
 void GodotArea2D::call_queries() {
-	if (monitor_callback_id.is_valid() && !monitored_bodies.is_empty()) {
-		Variant res[5];
-		Variant *resptr[5];
-		for (int i = 0; i < 5; i++) {
-			resptr[i] = &res[i];
-		}
+	if (!monitor_callback.is_null() && !monitored_bodies.is_empty()) {
+		if (monitor_callback.is_valid()) {
+			Variant res[5];
+			Variant *resptr[5];
+			for (int i = 0; i < 5; i++) {
+				resptr[i] = &res[i];
+			}
 
-		Object *obj = ObjectDB::get_instance(monitor_callback_id);
-		if (!obj) {
-			monitored_bodies.clear();
-			monitor_callback_id = ObjectID();
-			return;
-		}
+			for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) {
+				if (E->get().state == 0) { // Nothing happened
+					Map<BodyKey, BodyState>::Element *next = E->next();
+					monitored_bodies.erase(E);
+					E = next;
+					continue;
+				}
+
+				res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED;
+				res[1] = E->key().rid;
+				res[2] = E->key().instance_id;
+				res[3] = E->key().body_shape;
+				res[4] = E->key().area_shape;
 
-		for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) {
-			if (E->get().state == 0) { // Nothing happened
 				Map<BodyKey, BodyState>::Element *next = E->next();
 				monitored_bodies.erase(E);
 				E = next;
-				continue;
-			}
-
-			res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED;
-			res[1] = E->key().rid;
-			res[2] = E->key().instance_id;
-			res[3] = E->key().body_shape;
-			res[4] = E->key().area_shape;
 
-			Map<BodyKey, BodyState>::Element *next = E->next();
-			monitored_bodies.erase(E);
-			E = next;
-
-			Callable::CallError ce;
-			obj->call(monitor_callback_method, (const Variant **)resptr, 5, ce);
+				Callable::CallError ce;
+				Variant ret;
+				monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+			}
+		} else {
+			monitored_bodies.clear();
+			monitor_callback = Callable();
 		}
 	}
 
-	if (area_monitor_callback_id.is_valid() && !monitored_areas.is_empty()) {
-		Variant res[5];
-		Variant *resptr[5];
-		for (int i = 0; i < 5; i++) {
-			resptr[i] = &res[i];
-		}
+	if (!area_monitor_callback.is_null() && !monitored_areas.is_empty()) {
+		if (area_monitor_callback.is_valid()) {
+			Variant res[5];
+			Variant *resptr[5];
+			for (int i = 0; i < 5; i++) {
+				resptr[i] = &res[i];
+			}
 
-		Object *obj = ObjectDB::get_instance(area_monitor_callback_id);
-		if (!obj) {
-			monitored_areas.clear();
-			area_monitor_callback_id = ObjectID();
-			return;
-		}
+			for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) {
+				if (E->get().state == 0) { // Nothing happened
+					Map<BodyKey, BodyState>::Element *next = E->next();
+					monitored_areas.erase(E);
+					E = next;
+					continue;
+				}
+
+				res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED;
+				res[1] = E->key().rid;
+				res[2] = E->key().instance_id;
+				res[3] = E->key().body_shape;
+				res[4] = E->key().area_shape;
 
-		for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) {
-			if (E->get().state == 0) { // Nothing happened
 				Map<BodyKey, BodyState>::Element *next = E->next();
 				monitored_areas.erase(E);
 				E = next;
-				continue;
-			}
-
-			res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED;
-			res[1] = E->key().rid;
-			res[2] = E->key().instance_id;
-			res[3] = E->key().body_shape;
-			res[4] = E->key().area_shape;
-
-			Map<BodyKey, BodyState>::Element *next = E->next();
-			monitored_areas.erase(E);
-			E = next;
 
-			Callable::CallError ce;
-			obj->call(area_monitor_callback_method, (const Variant **)resptr, 5, ce);
+				Callable::CallError ce;
+				Variant ret;
+				area_monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+			}
+		} else {
+			monitored_areas.clear();
+			area_monitor_callback = Callable();
 		}
 	}
 }

+ 6 - 8
servers/physics_2d/godot_area_2d.h

@@ -52,11 +52,9 @@ class GodotArea2D : public GodotCollisionObject2D {
 	int priority = 0;
 	bool monitorable = false;
 
-	ObjectID monitor_callback_id;
-	StringName monitor_callback_method;
+	Callable monitor_callback;
 
-	ObjectID area_monitor_callback_id;
-	StringName area_monitor_callback_method;
+	Callable area_monitor_callback;
 
 	SelfList<GodotArea2D> monitor_query_list;
 	SelfList<GodotArea2D> moved_list;
@@ -99,11 +97,11 @@ class GodotArea2D : public GodotCollisionObject2D {
 	void _queue_monitor_update();
 
 public:
-	void set_monitor_callback(ObjectID p_id, const StringName &p_method);
-	_FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id.is_valid(); }
+	void set_monitor_callback(const Callable &p_callback);
+	_FORCE_INLINE_ bool has_monitor_callback() const { return !monitor_callback.is_null(); }
 
-	void set_area_monitor_callback(ObjectID p_id, const StringName &p_method);
-	_FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id.is_valid(); }
+	void set_area_monitor_callback(const Callable &p_callback);
+	_FORCE_INLINE_ bool has_area_monitor_callback() const { return !area_monitor_callback.is_null(); }
 
 	_FORCE_INLINE_ void add_body_to_query(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
 	_FORCE_INLINE_ void remove_body_from_query(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape);

+ 4 - 4
servers/physics_2d/godot_physics_server_2d.cpp

@@ -513,18 +513,18 @@ void GodotPhysicsServer2D::area_set_collision_layer(RID p_area, uint32_t p_layer
 	area->set_collision_layer(p_layer);
 }
 
-void GodotPhysicsServer2D::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
+void GodotPhysicsServer2D::area_set_monitor_callback(RID p_area, const Callable &p_callback) {
 	GodotArea2D *area = area_owner.get_or_null(p_area);
 	ERR_FAIL_COND(!area);
 
-	area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method);
+	area->set_monitor_callback(p_callback.is_valid() ? p_callback : Callable());
 }
 
-void GodotPhysicsServer2D::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
+void GodotPhysicsServer2D::area_set_area_monitor_callback(RID p_area, const Callable &p_callback) {
 	GodotArea2D *area = area_owner.get_or_null(p_area);
 	ERR_FAIL_COND(!area);
 
-	area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method);
+	area->set_area_monitor_callback(p_callback.is_valid() ? p_callback : Callable());
 }
 
 /* BODY API */

+ 2 - 2
servers/physics_2d/godot_physics_server_2d.h

@@ -158,8 +158,8 @@ public:
 	virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) override;
 	virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) override;
 
-	virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override;
-	virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override;
+	virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) override;
+	virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) override;
 
 	virtual void area_set_pickable(RID p_area, bool p_pickable) override;
 

+ 64 - 66
servers/physics_3d/godot_area_3d.cpp

@@ -86,16 +86,16 @@ void GodotArea3D::set_space(GodotSpace3D *p_space) {
 	_set_space(p_space);
 }
 
-void GodotArea3D::set_monitor_callback(ObjectID p_id, const StringName &p_method) {
-	if (p_id == monitor_callback_id) {
-		monitor_callback_method = p_method;
+void GodotArea3D::set_monitor_callback(const Callable &p_callback) {
+	ObjectID id = p_callback.get_object_id();
+	if (id == monitor_callback.get_object_id()) {
+		monitor_callback = p_callback;
 		return;
 	}
 
 	_unregister_shapes();
 
-	monitor_callback_id = p_id;
-	monitor_callback_method = p_method;
+	monitor_callback = p_callback;
 
 	monitored_bodies.clear();
 	monitored_areas.clear();
@@ -107,16 +107,16 @@ void GodotArea3D::set_monitor_callback(ObjectID p_id, const StringName &p_method
 	}
 }
 
-void GodotArea3D::set_area_monitor_callback(ObjectID p_id, const StringName &p_method) {
-	if (p_id == area_monitor_callback_id) {
-		area_monitor_callback_method = p_method;
+void GodotArea3D::set_area_monitor_callback(const Callable &p_callback) {
+	ObjectID id = p_callback.get_object_id();
+	if (id == area_monitor_callback.get_object_id()) {
+		area_monitor_callback = p_callback;
 		return;
 	}
 
 	_unregister_shapes();
 
-	area_monitor_callback_id = p_id;
-	area_monitor_callback_method = p_method;
+	area_monitor_callback = p_callback;
 
 	monitored_bodies.clear();
 	monitored_areas.clear();
@@ -230,77 +230,75 @@ void GodotArea3D::set_monitorable(bool p_monitorable) {
 }
 
 void GodotArea3D::call_queries() {
-	if (monitor_callback_id.is_valid() && !monitored_bodies.is_empty()) {
-		Variant res[5];
-		Variant *resptr[5];
-		for (int i = 0; i < 5; i++) {
-			resptr[i] = &res[i];
-		}
+	if (!monitor_callback.is_null() && !monitored_bodies.is_empty()) {
+		if (monitor_callback.is_valid()) {
+			Variant res[5];
+			Variant *resptr[5];
+			for (int i = 0; i < 5; i++) {
+				resptr[i] = &res[i];
+			}
 
-		Object *obj = ObjectDB::get_instance(monitor_callback_id);
-		if (!obj) {
-			monitored_bodies.clear();
-			monitor_callback_id = ObjectID();
-			return;
-		}
+			for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) {
+				if (E->get().state == 0) { // Nothing happened
+					Map<BodyKey, BodyState>::Element *next = E->next();
+					monitored_bodies.erase(E);
+					E = next;
+					continue;
+				}
+
+				res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED;
+				res[1] = E->key().rid;
+				res[2] = E->key().instance_id;
+				res[3] = E->key().body_shape;
+				res[4] = E->key().area_shape;
 
-		for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) {
-			if (E->get().state == 0) { // Nothing happened
 				Map<BodyKey, BodyState>::Element *next = E->next();
 				monitored_bodies.erase(E);
 				E = next;
-				continue;
-			}
 
-			res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED;
-			res[1] = E->key().rid;
-			res[2] = E->key().instance_id;
-			res[3] = E->key().body_shape;
-			res[4] = E->key().area_shape;
-
-			Map<BodyKey, BodyState>::Element *next = E->next();
-			monitored_bodies.erase(E);
-			E = next;
-
-			Callable::CallError ce;
-			obj->call(monitor_callback_method, (const Variant **)resptr, 5, ce);
+				Callable::CallError ce;
+				Variant ret;
+				monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+			}
+		} else {
+			monitored_bodies.clear();
+			monitor_callback = Callable();
 		}
 	}
 
-	if (area_monitor_callback_id.is_valid() && !monitored_areas.is_empty()) {
-		Variant res[5];
-		Variant *resptr[5];
-		for (int i = 0; i < 5; i++) {
-			resptr[i] = &res[i];
-		}
+	if (!area_monitor_callback.is_null() && !monitored_areas.is_empty()) {
+		if (area_monitor_callback.is_valid()) {
+			Variant res[5];
+			Variant *resptr[5];
+			for (int i = 0; i < 5; i++) {
+				resptr[i] = &res[i];
+			}
 
-		Object *obj = ObjectDB::get_instance(area_monitor_callback_id);
-		if (!obj) {
-			monitored_areas.clear();
-			area_monitor_callback_id = ObjectID();
-			return;
-		}
+			for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) {
+				if (E->get().state == 0) { // Nothing happened
+					Map<BodyKey, BodyState>::Element *next = E->next();
+					monitored_areas.erase(E);
+					E = next;
+					continue;
+				}
+
+				res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED;
+				res[1] = E->key().rid;
+				res[2] = E->key().instance_id;
+				res[3] = E->key().body_shape;
+				res[4] = E->key().area_shape;
 
-		for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) {
-			if (E->get().state == 0) { // Nothing happened
 				Map<BodyKey, BodyState>::Element *next = E->next();
 				monitored_areas.erase(E);
 				E = next;
-				continue;
-			}
 
-			res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED;
-			res[1] = E->key().rid;
-			res[2] = E->key().instance_id;
-			res[3] = E->key().body_shape;
-			res[4] = E->key().area_shape;
-
-			Map<BodyKey, BodyState>::Element *next = E->next();
-			monitored_areas.erase(E);
-			E = next;
-
-			Callable::CallError ce;
-			obj->call(area_monitor_callback_method, (const Variant **)resptr, 5, ce);
+				Callable::CallError ce;
+				Variant ret;
+				area_monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+			}
+		} else {
+			monitored_areas.clear();
+			area_monitor_callback = Callable();
 		}
 	}
 }

+ 6 - 9
servers/physics_3d/godot_area_3d.h

@@ -57,11 +57,8 @@ class GodotArea3D : public GodotCollisionObject3D {
 	int priority = 0;
 	bool monitorable = false;
 
-	ObjectID monitor_callback_id;
-	StringName monitor_callback_method;
-
-	ObjectID area_monitor_callback_id;
-	StringName area_monitor_callback_method;
+	Callable monitor_callback;
+	Callable area_monitor_callback;
 
 	SelfList<GodotArea3D> monitor_query_list;
 	SelfList<GodotArea3D> moved_list;
@@ -106,11 +103,11 @@ class GodotArea3D : public GodotCollisionObject3D {
 	void _queue_monitor_update();
 
 public:
-	void set_monitor_callback(ObjectID p_id, const StringName &p_method);
-	_FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id.is_valid(); }
+	void set_monitor_callback(const Callable &p_callback);
+	_FORCE_INLINE_ bool has_monitor_callback() const { return !monitor_callback.is_null(); }
 
-	void set_area_monitor_callback(ObjectID p_id, const StringName &p_method);
-	_FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id.is_valid(); }
+	void set_area_monitor_callback(const Callable &p_callback);
+	_FORCE_INLINE_ bool has_area_monitor_callback() const { return !area_monitor_callback.is_null(); }
 
 	_FORCE_INLINE_ void add_body_to_query(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape);
 	_FORCE_INLINE_ void remove_body_from_query(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape);

+ 4 - 4
servers/physics_3d/godot_physics_server_3d.cpp

@@ -416,11 +416,11 @@ void GodotPhysicsServer3D::area_set_monitorable(RID p_area, bool p_monitorable)
 	area->set_monitorable(p_monitorable);
 }
 
-void GodotPhysicsServer3D::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
+void GodotPhysicsServer3D::area_set_monitor_callback(RID p_area, const Callable &p_callback) {
 	GodotArea3D *area = area_owner.get_or_null(p_area);
 	ERR_FAIL_COND(!area);
 
-	area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method);
+	area->set_monitor_callback(p_callback.is_valid() ? p_callback : Callable());
 }
 
 void GodotPhysicsServer3D::area_set_ray_pickable(RID p_area, bool p_enable) {
@@ -430,11 +430,11 @@ void GodotPhysicsServer3D::area_set_ray_pickable(RID p_area, bool p_enable) {
 	area->set_ray_pickable(p_enable);
 }
 
-void GodotPhysicsServer3D::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
+void GodotPhysicsServer3D::area_set_area_monitor_callback(RID p_area, const Callable &p_callback) {
 	GodotArea3D *area = area_owner.get_or_null(p_area);
 	ERR_FAIL_COND(!area);
 
-	area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method);
+	area->set_area_monitor_callback(p_callback.is_valid() ? p_callback : Callable());
 }
 
 /* BODY API */

+ 2 - 2
servers/physics_3d/godot_physics_server_3d.h

@@ -157,8 +157,8 @@ public:
 
 	virtual void area_set_monitorable(RID p_area, bool p_monitorable) override;
 
-	virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override;
-	virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override;
+	virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) override;
+	virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) override;
 
 	/* BODY API */
 

+ 2 - 2
servers/physics_server_2d.cpp

@@ -616,8 +616,8 @@ void PhysicsServer2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("area_attach_canvas_instance_id", "area", "id"), &PhysicsServer2D::area_attach_canvas_instance_id);
 	ClassDB::bind_method(D_METHOD("area_get_canvas_instance_id", "area"), &PhysicsServer2D::area_get_canvas_instance_id);
 
-	ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &PhysicsServer2D::area_set_monitor_callback);
-	ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "receiver", "method"), &PhysicsServer2D::area_set_area_monitor_callback);
+	ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "callback"), &PhysicsServer2D::area_set_monitor_callback);
+	ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "callback"), &PhysicsServer2D::area_set_area_monitor_callback);
 	ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &PhysicsServer2D::area_set_monitorable);
 
 	ClassDB::bind_method(D_METHOD("body_create"), &PhysicsServer2D::body_create);

+ 2 - 2
servers/physics_server_2d.h

@@ -335,8 +335,8 @@ public:
 	virtual void area_set_monitorable(RID p_area, bool p_monitorable) = 0;
 	virtual void area_set_pickable(RID p_area, bool p_pickable) = 0;
 
-	virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0;
-	virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0;
+	virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) = 0;
+	virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) = 0;
 
 	/* BODY API */
 

+ 2 - 2
servers/physics_server_2d_wrap_mt.h

@@ -165,8 +165,8 @@ public:
 	FUNC2(area_set_monitorable, RID, bool);
 	FUNC2(area_set_pickable, RID, bool);
 
-	FUNC3(area_set_monitor_callback, RID, Object *, const StringName &);
-	FUNC3(area_set_area_monitor_callback, RID, Object *, const StringName &);
+	FUNC2(area_set_monitor_callback, RID, const Callable &);
+	FUNC2(area_set_area_monitor_callback, RID, const Callable &);
 
 	/* BODY API */
 

+ 2 - 2
servers/physics_server_3d.cpp

@@ -612,8 +612,8 @@ void PhysicsServer3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("area_attach_object_instance_id", "area", "id"), &PhysicsServer3D::area_attach_object_instance_id);
 	ClassDB::bind_method(D_METHOD("area_get_object_instance_id", "area"), &PhysicsServer3D::area_get_object_instance_id);
 
-	ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &PhysicsServer3D::area_set_monitor_callback);
-	ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "receiver", "method"), &PhysicsServer3D::area_set_area_monitor_callback);
+	ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "callback"), &PhysicsServer3D::area_set_monitor_callback);
+	ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "callback"), &PhysicsServer3D::area_set_area_monitor_callback);
 	ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &PhysicsServer3D::area_set_monitorable);
 
 	ClassDB::bind_method(D_METHOD("area_set_ray_pickable", "area", "enable"), &PhysicsServer3D::area_set_ray_pickable);

+ 2 - 2
servers/physics_server_3d.h

@@ -348,8 +348,8 @@ public:
 
 	virtual void area_set_monitorable(RID p_area, bool p_monitorable) = 0;
 
-	virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0;
-	virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0;
+	virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) = 0;
+	virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) = 0;
 
 	virtual void area_set_ray_pickable(RID p_area, bool p_enable) = 0;
 

+ 2 - 2
servers/physics_server_3d_wrap_mt.h

@@ -166,8 +166,8 @@ public:
 	FUNC2(area_set_monitorable, RID, bool);
 	FUNC2(area_set_ray_pickable, RID, bool);
 
-	FUNC3(area_set_monitor_callback, RID, Object *, const StringName &);
-	FUNC3(area_set_area_monitor_callback, RID, Object *, const StringName &);
+	FUNC2(area_set_monitor_callback, RID, const Callable &);
+	FUNC2(area_set_area_monitor_callback, RID, const Callable &);
 
 	/* BODY API */