Browse Source

Unexpose _direct_state_changed in PhysicsBody
Removed _direct_state_changed bindings
Affects 2D and 3D nodes
Callbacks now use Callable
Tests were changed accordingly

rafallus 4 years ago
parent
commit
cfa06f0f76

+ 2 - 4
doc/classes/PhysicsServer2D.xml

@@ -659,11 +659,9 @@
 			</return>
 			</return>
 			<argument index="0" name="body" type="RID">
 			<argument index="0" name="body" type="RID">
 			</argument>
 			</argument>
-			<argument index="1" name="receiver" type="Object">
-			</argument>
-			<argument index="2" name="method" type="StringName">
+			<argument index="1" name="callable" type="Callable">
 			</argument>
 			</argument>
-			<argument index="3" name="userdata" type="Variant" default="null">
+			<argument index="2" name="userdata" type="Variant" default="null">
 			</argument>
 			</argument>
 			<description>
 			<description>
 				Sets the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force_integration]).
 				Sets the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force_integration]).

+ 2 - 4
doc/classes/PhysicsServer3D.xml

@@ -653,11 +653,9 @@
 			</return>
 			</return>
 			<argument index="0" name="body" type="RID">
 			<argument index="0" name="body" type="RID">
 			</argument>
 			</argument>
-			<argument index="1" name="receiver" type="Object">
-			</argument>
-			<argument index="2" name="method" type="StringName">
+			<argument index="1" name="callable" type="Callable">
 			</argument>
 			</argument>
-			<argument index="3" name="userdata" type="Variant" default="null">
+			<argument index="2" name="userdata" type="Variant" default="null">
 			</argument>
 			</argument>
 			<description>
 			<description>
 				Sets the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force_integration]).
 				Sets the function used to calculate physics for an object, if that object allows it (see [method body_set_omit_force_integration]).

+ 2 - 2
modules/bullet/bullet_physics_server.cpp

@@ -824,10 +824,10 @@ bool BulletPhysicsServer3D::body_is_omitting_force_integration(RID p_body) const
 	return body->get_omit_forces_integration();
 	return body->get_omit_forces_integration();
 }
 }
 
 
-void BulletPhysicsServer3D::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) {
+void BulletPhysicsServer3D::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) {
 	RigidBodyBullet *body = rigid_body_owner.getornull(p_body);
 	RigidBodyBullet *body = rigid_body_owner.getornull(p_body);
 	ERR_FAIL_COND(!body);
 	ERR_FAIL_COND(!body);
-	body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata);
+	body->set_force_integration_callback(p_callable, p_udata);
 }
 }
 
 
 void BulletPhysicsServer3D::body_set_ray_pickable(RID p_body, bool p_enable) {
 void BulletPhysicsServer3D::body_set_ray_pickable(RID p_body, bool p_enable) {

+ 1 - 1
modules/bullet/bullet_physics_server.h

@@ -246,7 +246,7 @@ public:
 	virtual void body_set_omit_force_integration(RID p_body, bool p_omit) override;
 	virtual void body_set_omit_force_integration(RID p_body, bool p_omit) override;
 	virtual bool body_is_omitting_force_integration(RID p_body) const override;
 	virtual bool body_is_omitting_force_integration(RID p_body) const override;
 
 
-	virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) override;
+	virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) override;
 
 
 	virtual void body_set_ray_pickable(RID p_body, bool p_enable) override;
 	virtual void body_set_ray_pickable(RID p_body, bool p_enable) override;
 
 

+ 7 - 7
modules/bullet/rigid_body_bullet.cpp

@@ -346,16 +346,17 @@ void RigidBodyBullet::dispatch_callbacks() {
 
 
 		Variant variantBodyDirect = bodyDirect;
 		Variant variantBodyDirect = bodyDirect;
 
 
-		Object *obj = ObjectDB::get_instance(force_integration_callback->id);
+		Object *obj = force_integration_callback->callable.get_object();
 		if (!obj) {
 		if (!obj) {
 			// Remove integration callback
 			// Remove integration callback
-			set_force_integration_callback(ObjectID(), StringName());
+			set_force_integration_callback(Callable());
 		} else {
 		} else {
 			const Variant *vp[2] = { &variantBodyDirect, &force_integration_callback->udata };
 			const Variant *vp[2] = { &variantBodyDirect, &force_integration_callback->udata };
 
 
 			Callable::CallError responseCallError;
 			Callable::CallError responseCallError;
 			int argc = (force_integration_callback->udata.get_type() == Variant::NIL) ? 1 : 2;
 			int argc = (force_integration_callback->udata.get_type() == Variant::NIL) ? 1 : 2;
-			obj->call(force_integration_callback->method, vp, argc, responseCallError);
+			Variant rv;
+			force_integration_callback->callable.call(vp, argc, rv, responseCallError);
 		}
 		}
 	}
 	}
 
 
@@ -371,16 +372,15 @@ void RigidBodyBullet::dispatch_callbacks() {
 	previousActiveState = btBody->isActive();
 	previousActiveState = btBody->isActive();
 }
 }
 
 
-void RigidBodyBullet::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) {
+void RigidBodyBullet::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {
 	if (force_integration_callback) {
 	if (force_integration_callback) {
 		memdelete(force_integration_callback);
 		memdelete(force_integration_callback);
 		force_integration_callback = nullptr;
 		force_integration_callback = nullptr;
 	}
 	}
 
 
-	if (p_id.is_valid()) {
+	if (p_callable.get_object()) {
 		force_integration_callback = memnew(ForceIntegrationCallback);
 		force_integration_callback = memnew(ForceIntegrationCallback);
-		force_integration_callback->id = p_id;
-		force_integration_callback->method = p_method;
+		force_integration_callback->callable = p_callable;
 		force_integration_callback->udata = p_udata;
 		force_integration_callback->udata = p_udata;
 	}
 	}
 }
 }

+ 2 - 3
modules/bullet/rigid_body_bullet.h

@@ -154,8 +154,7 @@ public:
 	};
 	};
 
 
 	struct ForceIntegrationCallback {
 	struct ForceIntegrationCallback {
-		ObjectID id;
-		StringName method;
+		Callable callable;
 		Variant udata;
 		Variant udata;
 	};
 	};
 
 
@@ -240,7 +239,7 @@ public:
 	virtual void set_space(SpaceBullet *p_space);
 	virtual void set_space(SpaceBullet *p_space);
 
 
 	virtual void dispatch_callbacks();
 	virtual void dispatch_callbacks();
-	void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant());
+	void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant());
 	void scratch_space_override_modificator();
 	void scratch_space_override_modificator();
 
 
 	virtual void on_collision_filters_change();
 	virtual void on_collision_filters_change();

+ 5 - 7
scene/2d/physics_body_2d.cpp

@@ -271,6 +271,7 @@ bool RigidBody2D::_test_motion(const Vector2 &p_motion, bool p_infinite_inertia,
 void RigidBody2D::_direct_state_changed(Object *p_state) {
 void RigidBody2D::_direct_state_changed(Object *p_state) {
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	state = Object::cast_to<PhysicsDirectBodyState2D>(p_state);
 	state = Object::cast_to<PhysicsDirectBodyState2D>(p_state);
+	ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState2D object as argument");
 #else
 #else
 	state = (PhysicsDirectBodyState2D *)p_state; //trust it
 	state = (PhysicsDirectBodyState2D *)p_state; //trust it
 #endif
 #endif
@@ -729,8 +730,6 @@ void RigidBody2D::_bind_methods() {
 
 
 	ClassDB::bind_method(D_METHOD("test_motion", "motion", "infinite_inertia", "margin", "result"), &RigidBody2D::_test_motion, DEFVAL(true), DEFVAL(0.08), DEFVAL(Variant()));
 	ClassDB::bind_method(D_METHOD("test_motion", "motion", "infinite_inertia", "margin", "result"), &RigidBody2D::_test_motion, DEFVAL(true), DEFVAL(0.08), DEFVAL(Variant()));
 
 
-	ClassDB::bind_method(D_METHOD("_direct_state_changed"), &RigidBody2D::_direct_state_changed);
-
 	ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody2D::get_colliding_bodies);
 	ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody2D::get_colliding_bodies);
 
 
 	BIND_VMETHOD(MethodInfo("_integrate_forces", PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectBodyState2D")));
 	BIND_VMETHOD(MethodInfo("_integrate_forces", PropertyInfo(Variant::OBJECT, "state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectBodyState2D")));
@@ -774,7 +773,7 @@ void RigidBody2D::_bind_methods() {
 
 
 RigidBody2D::RigidBody2D() :
 RigidBody2D::RigidBody2D() :
 		PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) {
 		PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) {
-	PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
+	PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &RigidBody2D::_direct_state_changed));
 }
 }
 
 
 RigidBody2D::~RigidBody2D() {
 RigidBody2D::~RigidBody2D() {
@@ -1080,11 +1079,11 @@ void KinematicBody2D::set_sync_to_physics(bool p_enable) {
 	}
 	}
 
 
 	if (p_enable) {
 	if (p_enable) {
-		PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
+		PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &KinematicBody2D::_direct_state_changed));
 		set_only_update_transform_changes(true);
 		set_only_update_transform_changes(true);
 		set_notify_local_transform(true);
 		set_notify_local_transform(true);
 	} else {
 	} else {
-		PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), nullptr, "");
+		PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), Callable());
 		set_only_update_transform_changes(false);
 		set_only_update_transform_changes(false);
 		set_notify_local_transform(false);
 		set_notify_local_transform(false);
 	}
 	}
@@ -1100,6 +1099,7 @@ void KinematicBody2D::_direct_state_changed(Object *p_state) {
 	}
 	}
 
 
 	PhysicsDirectBodyState2D *state = Object::cast_to<PhysicsDirectBodyState2D>(p_state);
 	PhysicsDirectBodyState2D *state = Object::cast_to<PhysicsDirectBodyState2D>(p_state);
+	ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState2D object as argument");
 
 
 	last_valid_transform = state->get_transform();
 	last_valid_transform = state->get_transform();
 	set_notify_local_transform(false);
 	set_notify_local_transform(false);
@@ -1153,8 +1153,6 @@ void KinematicBody2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &KinematicBody2D::set_sync_to_physics);
 	ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &KinematicBody2D::set_sync_to_physics);
 	ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &KinematicBody2D::is_sync_to_physics_enabled);
 	ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &KinematicBody2D::is_sync_to_physics_enabled);
 
 
-	ClassDB::bind_method(D_METHOD("_direct_state_changed"), &KinematicBody2D::_direct_state_changed);
-
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "motion/sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "motion/sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
 }
 }

+ 7 - 10
scene/3d/physics_body_3d.cpp

@@ -274,6 +274,7 @@ struct _RigidBodyInOut {
 void RigidBody3D::_direct_state_changed(Object *p_state) {
 void RigidBody3D::_direct_state_changed(Object *p_state) {
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	state = Object::cast_to<PhysicsDirectBodyState3D>(p_state);
 	state = Object::cast_to<PhysicsDirectBodyState3D>(p_state);
+	ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState3D object as argument");
 #else
 #else
 	state = (PhysicsDirectBodyState3D *)p_state; //trust it
 	state = (PhysicsDirectBodyState3D *)p_state; //trust it
 #endif
 #endif
@@ -712,8 +713,6 @@ void RigidBody3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody3D::set_can_sleep);
 	ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody3D::set_can_sleep);
 	ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody3D::is_able_to_sleep);
 	ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody3D::is_able_to_sleep);
 
 
-	ClassDB::bind_method(D_METHOD("_direct_state_changed"), &RigidBody3D::_direct_state_changed);
-
 	ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &RigidBody3D::set_axis_lock);
 	ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &RigidBody3D::set_axis_lock);
 	ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &RigidBody3D::get_axis_lock);
 	ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &RigidBody3D::get_axis_lock);
 
 
@@ -759,7 +758,7 @@ void RigidBody3D::_bind_methods() {
 
 
 RigidBody3D::RigidBody3D() :
 RigidBody3D::RigidBody3D() :
 		PhysicsBody3D(PhysicsServer3D::BODY_MODE_RIGID) {
 		PhysicsBody3D(PhysicsServer3D::BODY_MODE_RIGID) {
-	PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
+	PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &RigidBody3D::_direct_state_changed));
 }
 }
 
 
 RigidBody3D::~RigidBody3D() {
 RigidBody3D::~RigidBody3D() {
@@ -1093,8 +1092,6 @@ void KinematicBody3D::_notification(int p_what) {
 }
 }
 
 
 void KinematicBody3D::_bind_methods() {
 void KinematicBody3D::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("_direct_state_changed"), &KinematicBody3D::_direct_state_changed);
-
 	ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody3D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false));
 	ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody3D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false));
 	ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody3D::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((real_t)45.0)), DEFVAL(true));
 	ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody3D::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((real_t)45.0)), DEFVAL(true));
 	ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody3D::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((real_t)45.0)), DEFVAL(true));
 	ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "up_direction", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody3D::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((real_t)45.0)), DEFVAL(true));
@@ -1127,6 +1124,7 @@ void KinematicBody3D::_bind_methods() {
 void KinematicBody3D::_direct_state_changed(Object *p_state) {
 void KinematicBody3D::_direct_state_changed(Object *p_state) {
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	PhysicsDirectBodyState3D *state = Object::cast_to<PhysicsDirectBodyState3D>(p_state);
 	PhysicsDirectBodyState3D *state = Object::cast_to<PhysicsDirectBodyState3D>(p_state);
+	ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState3D object as argument");
 #else
 #else
 	PhysicsDirectBodyState3D *state = (PhysicsDirectBodyState3D *)p_state; //trust it
 	PhysicsDirectBodyState3D *state = (PhysicsDirectBodyState3D *)p_state; //trust it
 #endif
 #endif
@@ -1138,7 +1136,7 @@ void KinematicBody3D::_direct_state_changed(Object *p_state) {
 KinematicBody3D::KinematicBody3D() :
 KinematicBody3D::KinematicBody3D() :
 		PhysicsBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) {
 		PhysicsBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) {
 	set_safe_margin(0.001);
 	set_safe_margin(0.001);
-	PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
+	PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &KinematicBody3D::_direct_state_changed));
 }
 }
 
 
 KinematicBody3D::~KinematicBody3D() {
 KinematicBody3D::~KinematicBody3D() {
@@ -1977,6 +1975,7 @@ void PhysicalBone3D::_direct_state_changed(Object *p_state) {
 
 
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	state = Object::cast_to<PhysicsDirectBodyState3D>(p_state);
 	state = Object::cast_to<PhysicsDirectBodyState3D>(p_state);
+	ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState3D object as argument");
 #else
 #else
 	state = (PhysicsDirectBodyState3D *)p_state; //trust it
 	state = (PhysicsDirectBodyState3D *)p_state; //trust it
 #endif
 #endif
@@ -1999,8 +1998,6 @@ void PhysicalBone3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicalBone3D::apply_central_impulse);
 	ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicalBone3D::apply_central_impulse);
 	ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &PhysicalBone3D::apply_impulse, Vector3());
 	ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &PhysicalBone3D::apply_impulse, Vector3());
 
 
-	ClassDB::bind_method(D_METHOD("_direct_state_changed"), &PhysicalBone3D::_direct_state_changed);
-
 	ClassDB::bind_method(D_METHOD("set_joint_type", "joint_type"), &PhysicalBone3D::set_joint_type);
 	ClassDB::bind_method(D_METHOD("set_joint_type", "joint_type"), &PhysicalBone3D::set_joint_type);
 	ClassDB::bind_method(D_METHOD("get_joint_type"), &PhysicalBone3D::get_joint_type);
 	ClassDB::bind_method(D_METHOD("get_joint_type"), &PhysicalBone3D::get_joint_type);
 
 
@@ -2479,7 +2476,7 @@ void PhysicalBone3D::_start_physics_simulation() {
 	PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_RIGID);
 	PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_RIGID);
 	PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
 	PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
 	PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
 	PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
-	PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
+	PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &PhysicalBone3D::_direct_state_changed));
 	set_as_top_level(true);
 	set_as_top_level(true);
 	_internal_simulate_physics = true;
 	_internal_simulate_physics = true;
 }
 }
@@ -2498,7 +2495,7 @@ void PhysicalBone3D::_stop_physics_simulation() {
 		PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), 0);
 		PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), 0);
 	}
 	}
 	if (_internal_simulate_physics) {
 	if (_internal_simulate_physics) {
-		PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), nullptr, "");
+		PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), Callable());
 		parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false);
 		parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false);
 		set_as_top_level(false);
 		set_as_top_level(false);
 		_internal_simulate_physics = false;
 		_internal_simulate_physics = false;

+ 2 - 1
scene/3d/vehicle_body_3d.cpp

@@ -803,6 +803,7 @@ void VehicleBody3D::_direct_state_changed(Object *p_state) {
 	RigidBody3D::_direct_state_changed(p_state);
 	RigidBody3D::_direct_state_changed(p_state);
 
 
 	state = Object::cast_to<PhysicsDirectBodyState3D>(p_state);
 	state = Object::cast_to<PhysicsDirectBodyState3D>(p_state);
+	ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState3D object as argument");
 
 
 	real_t step = state->get_step();
 	real_t step = state->get_step();
 
 
@@ -922,7 +923,7 @@ void VehicleBody3D::_bind_methods() {
 
 
 VehicleBody3D::VehicleBody3D() {
 VehicleBody3D::VehicleBody3D() {
 	exclude.insert(get_rid());
 	exclude.insert(get_rid());
-	//PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");
+	//PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &VehicleBody3D::_direct_state_changed));
 
 
 	set_mass(40);
 	set_mass(40);
 }
 }

+ 8 - 8
servers/physics_2d/body_2d_sw.cpp

@@ -591,16 +591,17 @@ void Body2DSW::call_queries() {
 		Variant v = dbs;
 		Variant v = dbs;
 		const Variant *vp[2] = { &v, &fi_callback->callback_udata };
 		const Variant *vp[2] = { &v, &fi_callback->callback_udata };
 
 
-		Object *obj = ObjectDB::get_instance(fi_callback->id);
+		Object *obj = fi_callback->callable.get_object();
 		if (!obj) {
 		if (!obj) {
-			set_force_integration_callback(ObjectID(), StringName());
+			set_force_integration_callback(Callable());
 		} else {
 		} else {
 			Callable::CallError ce;
 			Callable::CallError ce;
+			Variant rv;
 			if (fi_callback->callback_udata.get_type() != Variant::NIL) {
 			if (fi_callback->callback_udata.get_type() != Variant::NIL) {
-				obj->call(fi_callback->method, vp, 2, ce);
+				fi_callback->callable.call(vp, 2, rv, ce);
 
 
 			} else {
 			} else {
-				obj->call(fi_callback->method, vp, 1, ce);
+				fi_callback->callable.call(vp, 1, rv, ce);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -625,16 +626,15 @@ bool Body2DSW::sleep_test(real_t p_step) {
 	}
 	}
 }
 }
 
 
-void Body2DSW::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) {
+void Body2DSW::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {
 	if (fi_callback) {
 	if (fi_callback) {
 		memdelete(fi_callback);
 		memdelete(fi_callback);
 		fi_callback = nullptr;
 		fi_callback = nullptr;
 	}
 	}
 
 
-	if (p_id.is_valid()) {
+	if (p_callable.get_object()) {
 		fi_callback = memnew(ForceIntegrationCallback);
 		fi_callback = memnew(ForceIntegrationCallback);
-		fi_callback->id = p_id;
-		fi_callback->method = p_method;
+		fi_callback->callable = p_callable;
 		fi_callback->callback_udata = p_udata;
 		fi_callback->callback_udata = p_udata;
 	}
 	}
 }
 }

+ 2 - 3
servers/physics_2d/body_2d_sw.h

@@ -117,8 +117,7 @@ class Body2DSW : public CollisionObject2DSW {
 	int contact_count;
 	int contact_count;
 
 
 	struct ForceIntegrationCallback {
 	struct ForceIntegrationCallback {
-		ObjectID id;
-		StringName method;
+		Callable callable;
 		Variant callback_udata;
 		Variant callback_udata;
 	};
 	};
 
 
@@ -131,7 +130,7 @@ class Body2DSW : public CollisionObject2DSW {
 	friend class PhysicsDirectBodyState2DSW; // i give up, too many functions to expose
 	friend class PhysicsDirectBodyState2DSW; // i give up, too many functions to expose
 
 
 public:
 public:
-	void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant());
+	void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant());
 
 
 	_FORCE_INLINE_ void add_area(Area2DSW *p_area) {
 	_FORCE_INLINE_ void add_area(Area2DSW *p_area) {
 		int index = areas.find(AreaCMP(p_area));
 		int index = areas.find(AreaCMP(p_area));

+ 2 - 2
servers/physics_2d/physics_server_2d_sw.cpp

@@ -927,10 +927,10 @@ int PhysicsServer2DSW::body_get_max_contacts_reported(RID p_body) const {
 	return body->get_max_contacts_reported();
 	return body->get_max_contacts_reported();
 }
 }
 
 
-void PhysicsServer2DSW::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) {
+void PhysicsServer2DSW::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) {
 	Body2DSW *body = body_owner.getornull(p_body);
 	Body2DSW *body = body_owner.getornull(p_body);
 	ERR_FAIL_COND(!body);
 	ERR_FAIL_COND(!body);
-	body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata);
+	body->set_force_integration_callback(p_callable, p_udata);
 }
 }
 
 
 bool PhysicsServer2DSW::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) {
 bool PhysicsServer2DSW::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) {

+ 1 - 1
servers/physics_2d/physics_server_2d_sw.h

@@ -242,7 +242,7 @@ public:
 	virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) override;
 	virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) override;
 	virtual int body_get_max_contacts_reported(RID p_body) const override;
 	virtual int body_get_max_contacts_reported(RID p_body) const override;
 
 
-	virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) override;
+	virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) override;
 	virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override;
 	virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override;
 
 
 	virtual void body_set_pickable(RID p_body, bool p_pickable) override;
 	virtual void body_set_pickable(RID p_body, bool p_pickable) override;

+ 1 - 1
servers/physics_2d/physics_server_2d_wrap_mt.h

@@ -245,7 +245,7 @@ public:
 	FUNC2(body_set_omit_force_integration, RID, bool);
 	FUNC2(body_set_omit_force_integration, RID, bool);
 	FUNC1RC(bool, body_is_omitting_force_integration, RID);
 	FUNC1RC(bool, body_is_omitting_force_integration, RID);
 
 
-	FUNC4(body_set_force_integration_callback, RID, Object *, const StringName &, const Variant &);
+	FUNC3(body_set_force_integration_callback, RID, const Callable &, const Variant &);
 
 
 	bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override {
 	bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override {
 		return physics_2d_server->body_collide_shape(p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count);
 		return physics_2d_server->body_collide_shape(p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count);

+ 7 - 7
servers/physics_3d/body_3d_sw.cpp

@@ -693,15 +693,16 @@ void Body3DSW::call_queries() {
 
 
 		Variant v = dbs;
 		Variant v = dbs;
 
 
-		Object *obj = ObjectDB::get_instance(fi_callback->id);
+		Object *obj = fi_callback->callable.get_object();
 		if (!obj) {
 		if (!obj) {
-			set_force_integration_callback(ObjectID(), StringName());
+			set_force_integration_callback(Callable());
 		} else {
 		} else {
 			const Variant *vp[2] = { &v, &fi_callback->udata };
 			const Variant *vp[2] = { &v, &fi_callback->udata };
 
 
 			Callable::CallError ce;
 			Callable::CallError ce;
 			int argc = (fi_callback->udata.get_type() == Variant::NIL) ? 1 : 2;
 			int argc = (fi_callback->udata.get_type() == Variant::NIL) ? 1 : 2;
-			obj->call(fi_callback->method, vp, argc, ce);
+			Variant rv;
+			fi_callback->callable.call(vp, argc, rv, ce);
 		}
 		}
 	}
 	}
 }
 }
@@ -725,16 +726,15 @@ bool Body3DSW::sleep_test(real_t p_step) {
 	}
 	}
 }
 }
 
 
-void Body3DSW::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) {
+void Body3DSW::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {
 	if (fi_callback) {
 	if (fi_callback) {
 		memdelete(fi_callback);
 		memdelete(fi_callback);
 		fi_callback = nullptr;
 		fi_callback = nullptr;
 	}
 	}
 
 
-	if (p_id.is_valid()) {
+	if (p_callable.get_object()) {
 		fi_callback = memnew(ForceIntegrationCallback);
 		fi_callback = memnew(ForceIntegrationCallback);
-		fi_callback->id = p_id;
-		fi_callback->method = p_method;
+		fi_callback->callable = p_callable;
 		fi_callback->udata = p_udata;
 		fi_callback->udata = p_udata;
 	}
 	}
 }
 }

+ 2 - 3
servers/physics_3d/body_3d_sw.h

@@ -127,8 +127,7 @@ class Body3DSW : public CollisionObject3DSW {
 	int contact_count;
 	int contact_count;
 
 
 	struct ForceIntegrationCallback {
 	struct ForceIntegrationCallback {
-		ObjectID id;
-		StringName method;
+		Callable callable;
 		Variant udata;
 		Variant udata;
 	};
 	};
 
 
@@ -143,7 +142,7 @@ class Body3DSW : public CollisionObject3DSW {
 	friend class PhysicsDirectBodyState3DSW; // i give up, too many functions to expose
 	friend class PhysicsDirectBodyState3DSW; // i give up, too many functions to expose
 
 
 public:
 public:
-	void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant());
+	void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant());
 
 
 	void set_kinematic_margin(real_t p_margin);
 	void set_kinematic_margin(real_t p_margin);
 	_FORCE_INLINE_ real_t get_kinematic_margin() { return kinematic_safe_margin; }
 	_FORCE_INLINE_ real_t get_kinematic_margin() { return kinematic_safe_margin; }

+ 2 - 2
servers/physics_3d/physics_server_3d_sw.cpp

@@ -857,10 +857,10 @@ int PhysicsServer3DSW::body_get_max_contacts_reported(RID p_body) const {
 	return body->get_max_contacts_reported();
 	return body->get_max_contacts_reported();
 }
 }
 
 
-void PhysicsServer3DSW::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) {
+void PhysicsServer3DSW::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) {
 	Body3DSW *body = body_owner.getornull(p_body);
 	Body3DSW *body = body_owner.getornull(p_body);
 	ERR_FAIL_COND(!body);
 	ERR_FAIL_COND(!body);
-	body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata);
+	body->set_force_integration_callback(p_callable, p_udata);
 }
 }
 
 
 void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) {
 void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) {

+ 1 - 1
servers/physics_3d/physics_server_3d_sw.h

@@ -241,7 +241,7 @@ public:
 	virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) override;
 	virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) override;
 	virtual int body_get_max_contacts_reported(RID p_body) const override;
 	virtual int body_get_max_contacts_reported(RID p_body) const override;
 
 
-	virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) override;
+	virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) override;
 
 
 	virtual void body_set_ray_pickable(RID p_body, bool p_enable) override;
 	virtual void body_set_ray_pickable(RID p_body, bool p_enable) override;
 
 

+ 1 - 1
servers/physics_3d/physics_server_3d_wrap_mt.h

@@ -249,7 +249,7 @@ public:
 	FUNC2(body_set_omit_force_integration, RID, bool);
 	FUNC2(body_set_omit_force_integration, RID, bool);
 	FUNC1RC(bool, body_is_omitting_force_integration, RID);
 	FUNC1RC(bool, body_is_omitting_force_integration, RID);
 
 
-	FUNC4(body_set_force_integration_callback, RID, Object *, const StringName &, const Variant &);
+	FUNC3(body_set_force_integration_callback, RID, const Callable &, const Variant &);
 
 
 	FUNC2(body_set_ray_pickable, RID, bool);
 	FUNC2(body_set_ray_pickable, RID, bool);
 
 

+ 1 - 1
servers/physics_server_2d.cpp

@@ -647,7 +647,7 @@ void PhysicsServer2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("body_set_omit_force_integration", "body", "enable"), &PhysicsServer2D::body_set_omit_force_integration);
 	ClassDB::bind_method(D_METHOD("body_set_omit_force_integration", "body", "enable"), &PhysicsServer2D::body_set_omit_force_integration);
 	ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration", "body"), &PhysicsServer2D::body_is_omitting_force_integration);
 	ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration", "body"), &PhysicsServer2D::body_is_omitting_force_integration);
 
 
-	ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "receiver", "method", "userdata"), &PhysicsServer2D::body_set_force_integration_callback, DEFVAL(Variant()));
+	ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "callable", "userdata"), &PhysicsServer2D::body_set_force_integration_callback, DEFVAL(Variant()));
 
 
 	ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "margin", "result"), &PhysicsServer2D::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant()));
 	ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "margin", "result"), &PhysicsServer2D::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant()));
 
 

+ 1 - 1
servers/physics_server_2d.h

@@ -477,7 +477,7 @@ public:
 	virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0;
 	virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0;
 	virtual bool body_is_omitting_force_integration(RID p_body) const = 0;
 	virtual bool body_is_omitting_force_integration(RID p_body) const = 0;
 
 
-	virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) = 0;
+	virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) = 0;
 
 
 	virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) = 0;
 	virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) = 0;
 
 

+ 1 - 1
servers/physics_server_3d.cpp

@@ -550,7 +550,7 @@ void PhysicsServer3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("body_set_omit_force_integration", "body", "enable"), &PhysicsServer3D::body_set_omit_force_integration);
 	ClassDB::bind_method(D_METHOD("body_set_omit_force_integration", "body", "enable"), &PhysicsServer3D::body_set_omit_force_integration);
 	ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration", "body"), &PhysicsServer3D::body_is_omitting_force_integration);
 	ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration", "body"), &PhysicsServer3D::body_is_omitting_force_integration);
 
 
-	ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "receiver", "method", "userdata"), &PhysicsServer3D::body_set_force_integration_callback, DEFVAL(Variant()));
+	ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "callable", "userdata"), &PhysicsServer3D::body_set_force_integration_callback, DEFVAL(Variant()));
 
 
 	ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer3D::body_set_ray_pickable);
 	ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer3D::body_set_ray_pickable);
 
 

+ 1 - 1
servers/physics_server_3d.h

@@ -486,7 +486,7 @@ public:
 	virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0;
 	virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0;
 	virtual bool body_is_omitting_force_integration(RID p_body) const = 0;
 	virtual bool body_is_omitting_force_integration(RID p_body) const = 0;
 
 
-	virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) = 0;
+	virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) = 0;
 
 
 	virtual void body_set_ray_pickable(RID p_body, bool p_enable) = 0;
 	virtual void body_set_ray_pickable(RID p_body, bool p_enable) = 0;
 
 

+ 1 - 4
tests/test_physics_2d.cpp

@@ -243,9 +243,7 @@ protected:
 		Size2 imgsize(5, 5); //vs->texture_get_width(body_shape_data[p_shape].image), vs->texture_get_height(body_shape_data[p_shape].image));
 		Size2 imgsize(5, 5); //vs->texture_get_width(body_shape_data[p_shape].image), vs->texture_get_height(body_shape_data[p_shape].image));
 		vs->canvas_item_add_texture_rect(sprite, Rect2(-imgsize / 2.0, imgsize), body_shape_data[p_shape].image);
 		vs->canvas_item_add_texture_rect(sprite, Rect2(-imgsize / 2.0, imgsize), body_shape_data[p_shape].image);
 
 
-		ps->body_set_force_integration_callback(body, this, "_body_moved", sprite);
-		//RID q = ps->query_create(this,"_body_moved",sprite);
-		//ps->query_body_state(q,body);
+		ps->body_set_force_integration_callback(body, callable_mp(this, &TestPhysics2DMainLoop::_body_moved), sprite);
 
 
 		return body;
 		return body;
 	}
 	}
@@ -310,7 +308,6 @@ protected:
 	}
 	}
 
 
 	static void _bind_methods() {
 	static void _bind_methods() {
-		ClassDB::bind_method(D_METHOD("_body_moved"), &TestPhysics2DMainLoop::_body_moved);
 		ClassDB::bind_method(D_METHOD("_ray_query_callback"), &TestPhysics2DMainLoop::_ray_query_callback);
 		ClassDB::bind_method(D_METHOD("_ray_query_callback"), &TestPhysics2DMainLoop::_ray_query_callback);
 	}
 	}
 
 

+ 2 - 7
tests/test_physics_3d.cpp

@@ -77,10 +77,6 @@ class TestPhysics3DMainLoop : public MainLoop {
 	bool quit;
 	bool quit;
 
 
 protected:
 protected:
-	static void _bind_methods() {
-		ClassDB::bind_method("body_changed_transform", &TestPhysics3DMainLoop::body_changed_transform);
-	}
-
 	RID create_body(PhysicsServer3D::ShapeType p_shape, PhysicsServer3D::BodyMode p_body, const Transform p_location, bool p_active_default = true, const Transform &p_shape_xform = Transform()) {
 	RID create_body(PhysicsServer3D::ShapeType p_shape, PhysicsServer3D::BodyMode p_body, const Transform p_location, bool p_active_default = true, const Transform &p_shape_xform = Transform()) {
 		RenderingServer *vs = RenderingServer::get_singleton();
 		RenderingServer *vs = RenderingServer::get_singleton();
 		PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
 		PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
@@ -93,7 +89,7 @@ protected:
 		ps->body_set_param(body, PhysicsServer3D::BODY_PARAM_BOUNCE, 0.0);
 		ps->body_set_param(body, PhysicsServer3D::BODY_PARAM_BOUNCE, 0.0);
 		//todo set space
 		//todo set space
 		ps->body_add_shape(body, type_shape_map[p_shape]);
 		ps->body_add_shape(body, type_shape_map[p_shape]);
-		ps->body_set_force_integration_callback(body, this, "body_changed_transform", mesh_instance);
+		ps->body_set_force_integration_callback(body, callable_mp(this, &TestPhysics3DMainLoop::body_changed_transform), mesh_instance);
 
 
 		ps->body_set_state(body, PhysicsServer3D::BODY_STATE_TRANSFORM, p_location);
 		ps->body_set_state(body, PhysicsServer3D::BODY_STATE_TRANSFORM, p_location);
 		bodies.push_back(body);
 		bodies.push_back(body);
@@ -370,8 +366,7 @@ public:
 		ps->body_set_space(character, space);
 		ps->body_set_space(character, space);
 		//todo add space
 		//todo add space
 		ps->body_add_shape(character, capsule_shape);
 		ps->body_add_shape(character, capsule_shape);
-
-		ps->body_set_force_integration_callback(character, this, "body_changed_transform", mesh_instance);
+		ps->body_set_force_integration_callback(character, callable_mp(this, &TestPhysics3DMainLoop::body_changed_transform), mesh_instance);
 
 
 		ps->body_set_state(character, PhysicsServer3D::BODY_STATE_TRANSFORM, Transform(Basis(), Vector3(-2, 5, -2)));
 		ps->body_set_state(character, PhysicsServer3D::BODY_STATE_TRANSFORM, Transform(Basis(), Vector3(-2, 5, -2)));
 		bodies.push_back(character);
 		bodies.push_back(character);