PhysicsServer2D and PhysicsServer3D: make body_set_state_sync_callback take a Callable

Prefer Callable to a C-style callback. This is helpful for GDExtension.
This commit is contained in:
Ricardo Buring 2022-09-15 14:15:39 +02:00
parent 4ba934bf3d
commit ff4e72a0bc
21 changed files with 47 additions and 101 deletions

View File

@ -602,7 +602,7 @@
<method name="_body_set_state_sync_callback" qualifiers="virtual">
<return type="void" />
<param index="0" name="body" type="RID" />
<param index="1" name="callback" type="PhysicsServer2DExtensionStateCallback*" />
<param index="1" name="callable" type="Callable" />
<description>
</description>
</method>

View File

@ -575,7 +575,7 @@
<method name="_body_set_state_sync_callback" qualifiers="virtual">
<return type="void" />
<param index="0" name="body" type="RID" />
<param index="1" name="callback" type="PhysicsServer3DExtensionStateCallback*" />
<param index="1" name="callable" type="Callable" />
<description>
</description>
</method>

View File

@ -262,21 +262,16 @@ void AnimatableBody2D::_update_kinematic_motion() {
#endif
if (sync_to_physics) {
PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &AnimatableBody2D::_body_state_changed));
set_only_update_transform_changes(true);
set_notify_local_transform(true);
} else {
PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), nullptr, nullptr);
PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), Callable());
set_only_update_transform_changes(false);
set_notify_local_transform(false);
}
}
void AnimatableBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) {
AnimatableBody2D *body = static_cast<AnimatableBody2D *>(p_instance);
body->_body_state_changed(p_state);
}
void AnimatableBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
if (!sync_to_physics) {
return;
@ -438,11 +433,6 @@ struct _RigidBody2DInOut {
int local_shape = 0;
};
void RigidBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) {
RigidBody2D *body = static_cast<RigidBody2D *>(p_instance);
body->_body_state_changed(p_state);
}
void RigidBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
set_block_transform_notify(true); // don't want notify (would feedback loop)
if (!freeze || freeze_mode != FREEZE_MODE_KINEMATIC) {
@ -1079,7 +1069,7 @@ void RigidBody2D::_validate_property(PropertyInfo &p_property) const {
RigidBody2D::RigidBody2D() :
PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) {
PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &RigidBody2D::_body_state_changed));
}
RigidBody2D::~RigidBody2D() {

View File

@ -317,11 +317,6 @@ void AnimatableBody3D::_update_kinematic_motion() {
}
}
void AnimatableBody3D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state) {
AnimatableBody3D *body = (AnimatableBody3D *)p_instance;
body->_body_state_changed(p_state);
}
void AnimatableBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
linear_velocity = p_state->get_linear_velocity();
angular_velocity = p_state->get_angular_velocity();
@ -373,7 +368,7 @@ void AnimatableBody3D::_bind_methods() {
AnimatableBody3D::AnimatableBody3D() :
StaticBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) {
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &AnimatableBody3D::_body_state_changed));
}
void RigidBody3D::_body_enter_tree(ObjectID p_id) {
@ -488,11 +483,6 @@ struct _RigidBodyInOut {
int local_shape = 0;
};
void RigidBody3D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state) {
RigidBody3D *body = (RigidBody3D *)p_instance;
body->_body_state_changed(p_state);
}
void RigidBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
set_ignore_transform_notification(true);
set_global_transform(p_state->get_transform());
@ -1139,7 +1129,7 @@ void RigidBody3D::_validate_property(PropertyInfo &p_property) const {
RigidBody3D::RigidBody3D() :
PhysicsBody3D(PhysicsServer3D::BODY_MODE_RIGID) {
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &RigidBody3D::_body_state_changed));
}
RigidBody3D::~RigidBody3D() {
@ -2903,11 +2893,6 @@ void PhysicalBone3D::_notification(int p_what) {
}
}
void PhysicalBone3D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state) {
PhysicalBone3D *bone = (PhysicalBone3D *)p_instance;
bone->_body_state_changed(p_state);
}
void PhysicalBone3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
if (!simulate_physics || !_internal_simulate_physics) {
return;
@ -3425,7 +3410,7 @@ void PhysicalBone3D::_start_physics_simulation() {
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_priority(get_rid(), get_collision_priority());
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &PhysicalBone3D::_body_state_changed));
set_as_top_level(true);
_internal_simulate_physics = true;
}
@ -3446,7 +3431,7 @@ void PhysicalBone3D::_stop_physics_simulation() {
PhysicsServer3D::get_singleton()->body_set_collision_priority(get_rid(), 1.0);
}
if (_internal_simulate_physics) {
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), nullptr, nullptr);
PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), Callable());
parent_skeleton->set_bone_global_pose_override(bone_id, Transform3D(), 0.0, false);
set_as_top_level(false);
_internal_simulate_physics = false;

View File

@ -280,7 +280,7 @@ void PhysicsServer2DExtension::_bind_methods() {
GDVIRTUAL_BIND(_body_set_omit_force_integration, "body", "enable");
GDVIRTUAL_BIND(_body_is_omitting_force_integration, "body");
GDVIRTUAL_BIND(_body_set_state_sync_callback, "body", "callback");
GDVIRTUAL_BIND(_body_set_state_sync_callback, "body", "callable");
GDVIRTUAL_BIND(_body_set_force_integration_callback, "body", "callable", "userdata");
GDVIRTUAL_BIND(_body_collide_shape, "body", "body_shape", "shape", "shape_xform", "motion", "results", "result_max", "result_count");

View File

@ -94,7 +94,6 @@ public:
EXBIND1RC(Vector2, get_contact_local_position, int)
EXBIND1RC(Vector2, get_contact_local_normal, int)
EXBIND1RC(int, get_contact_local_shape, int)
EXBIND1RC(RID, get_contact_collider, int)
EXBIND1RC(Vector2, get_contact_collider_position, int)
EXBIND1RC(ObjectID, get_contact_collider_id, int)
@ -183,13 +182,7 @@ public:
typedef PhysicsServer2D::MotionResult PhysicsServer2DExtensionMotionResult;
struct PhysicsServer2DExtensionStateCallback {
void *instance = nullptr;
void (*callback)(void *p_instance, PhysicsDirectBodyState2D *p_state);
};
GDVIRTUAL_NATIVE_PTR(PhysicsServer2DExtensionMotionResult)
GDVIRTUAL_NATIVE_PTR(PhysicsServer2DExtensionStateCallback)
class PhysicsServer2DExtension : public PhysicsServer2D {
GDCLASS(PhysicsServer2DExtension, PhysicsServer2D);
@ -376,13 +369,7 @@ public:
EXBIND2(body_set_omit_force_integration, RID, bool)
EXBIND1RC(bool, body_is_omitting_force_integration, RID)
GDVIRTUAL2(_body_set_state_sync_callback, RID, GDNativePtr<PhysicsServer2DExtensionStateCallback>)
void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) override {
PhysicsServer2DExtensionStateCallback callback;
callback.callback = p_callback;
callback.instance = p_instance;
GDVIRTUAL_REQUIRED_CALL(_body_set_state_sync_callback, p_body, &callback);
}
EXBIND2(body_set_state_sync_callback, RID, const Callable &)
EXBIND3(body_set_force_integration_callback, RID, const Callable &, const Variant &)
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 {

View File

@ -284,7 +284,7 @@ void PhysicsServer3DExtension::_bind_methods() {
GDVIRTUAL_BIND(_body_set_omit_force_integration, "body", "enable");
GDVIRTUAL_BIND(_body_is_omitting_force_integration, "body");
GDVIRTUAL_BIND(_body_set_state_sync_callback, "body", "callback");
GDVIRTUAL_BIND(_body_set_state_sync_callback, "body", "callable");
GDVIRTUAL_BIND(_body_set_force_integration_callback, "body", "callable", "userdata");
GDVIRTUAL_BIND(_body_set_ray_pickable, "body", "enable");

View File

@ -192,14 +192,8 @@ public:
typedef PhysicsServer3D::MotionCollision PhysicsServer3DExtensionMotionCollision;
typedef PhysicsServer3D::MotionResult PhysicsServer3DExtensionMotionResult;
struct PhysicsServer3DExtensionStateCallback {
void *instance = nullptr;
void (*callback)(void *p_instance, PhysicsDirectBodyState3D *p_state);
};
GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionMotionCollision)
GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionMotionResult)
GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionStateCallback)
class PhysicsServer3DExtension : public PhysicsServer3D {
GDCLASS(PhysicsServer3DExtension, PhysicsServer3D);
@ -380,13 +374,7 @@ public:
EXBIND2(body_set_omit_force_integration, RID, bool)
EXBIND1RC(bool, body_is_omitting_force_integration, RID)
GDVIRTUAL2(_body_set_state_sync_callback, RID, GDNativePtr<PhysicsServer3DExtensionStateCallback>)
void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) override {
PhysicsServer3DExtensionStateCallback callback;
callback.callback = p_callback;
callback.instance = p_instance;
GDVIRTUAL_REQUIRED_CALL(_body_set_state_sync_callback, p_body, &callback);
}
EXBIND2(body_set_state_sync_callback, RID, const Callable &)
EXBIND3(body_set_force_integration_callback, RID, const Callable &, const Variant &)
EXBIND2(body_set_ray_pickable, RID, bool)

View File

@ -615,7 +615,7 @@ void GodotBody2D::integrate_velocities(real_t p_step) {
return;
}
if (fi_callback_data || body_state_callback) {
if (fi_callback_data || body_state_callback.get_object()) {
get_space()->body_add_to_state_query_list(&direct_state_query_list);
}
@ -673,11 +673,12 @@ void GodotBody2D::wakeup_neighbours() {
}
void GodotBody2D::call_queries() {
Variant direct_state_variant = get_direct_state();
if (fi_callback_data) {
if (!fi_callback_data->callable.get_object()) {
set_force_integration_callback(Callable());
} else {
Variant direct_state_variant = get_direct_state();
const Variant *vp[2] = { &direct_state_variant, &fi_callback_data->udata };
Callable::CallError ce;
@ -691,8 +692,11 @@ void GodotBody2D::call_queries() {
}
}
if (body_state_callback) {
(body_state_callback)(body_state_callback_instance, get_direct_state());
if (body_state_callback.get_object()) {
const Variant *vp[1] = { &direct_state_variant };
Callable::CallError ce;
Variant rv;
body_state_callback.callp(vp, 1, rv, ce);
}
}
@ -713,9 +717,8 @@ bool GodotBody2D::sleep_test(real_t p_step) {
}
}
void GodotBody2D::set_state_sync_callback(void *p_instance, PhysicsServer2D::BodyStateCallback p_callback) {
body_state_callback_instance = p_instance;
body_state_callback = p_callback;
void GodotBody2D::set_state_sync_callback(const Callable &p_callable) {
body_state_callback = p_callable;
}
void GodotBody2D::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {

View File

@ -137,8 +137,7 @@ class GodotBody2D : public GodotCollisionObject2D {
Vector<Contact> contacts; //no contacts by default
int contact_count = 0;
void *body_state_callback_instance = nullptr;
PhysicsServer2D::BodyStateCallback body_state_callback = nullptr;
Callable body_state_callback;
struct ForceIntegrationCallbackData {
Callable callable;
@ -156,7 +155,7 @@ class GodotBody2D : public GodotCollisionObject2D {
friend class GodotPhysicsDirectBodyState2D; // i give up, too many functions to expose
public:
void set_state_sync_callback(void *p_instance, PhysicsServer2D::BodyStateCallback p_callback);
void set_state_sync_callback(const Callable &p_callable);
void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant());
GodotPhysicsDirectBodyState2D *get_direct_state();

View File

@ -951,10 +951,10 @@ int GodotPhysicsServer2D::body_get_max_contacts_reported(RID p_body) const {
return body->get_max_contacts_reported();
}
void GodotPhysicsServer2D::body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) {
void GodotPhysicsServer2D::body_set_state_sync_callback(RID p_body, const Callable &p_callable) {
GodotBody2D *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_state_sync_callback(p_instance, p_callback);
body->set_state_sync_callback(p_callable);
}
void GodotPhysicsServer2D::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) {

View File

@ -243,7 +243,7 @@ public:
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 void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) override;
virtual void body_set_state_sync_callback(RID p_body, const Callable &p_callable) 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;

View File

@ -674,7 +674,7 @@ void GodotBody3D::integrate_velocities(real_t p_step) {
return;
}
if (fi_callback_data || body_state_callback) {
if (fi_callback_data || body_state_callback.get_object()) {
get_space()->body_add_to_state_query_list(&direct_state_query_list);
}
@ -756,11 +756,12 @@ void GodotBody3D::wakeup_neighbours() {
}
void GodotBody3D::call_queries() {
Variant direct_state_variant = get_direct_state();
if (fi_callback_data) {
if (!fi_callback_data->callable.get_object()) {
set_force_integration_callback(Callable());
} else {
Variant direct_state_variant = get_direct_state();
const Variant *vp[2] = { &direct_state_variant, &fi_callback_data->udata };
Callable::CallError ce;
@ -770,8 +771,11 @@ void GodotBody3D::call_queries() {
}
}
if (body_state_callback_instance) {
(body_state_callback)(body_state_callback_instance, get_direct_state());
if (body_state_callback.get_object()) {
const Variant *vp[1] = { &direct_state_variant };
Callable::CallError ce;
Variant rv;
body_state_callback.callp(vp, 1, rv, ce);
}
}
@ -792,9 +796,8 @@ bool GodotBody3D::sleep_test(real_t p_step) {
}
}
void GodotBody3D::set_state_sync_callback(void *p_instance, PhysicsServer3D::BodyStateCallback p_callback) {
body_state_callback_instance = p_instance;
body_state_callback = p_callback;
void GodotBody3D::set_state_sync_callback(const Callable &p_callable) {
body_state_callback = p_callable;
}
void GodotBody3D::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {

View File

@ -131,8 +131,7 @@ class GodotBody3D : public GodotCollisionObject3D {
Vector<Contact> contacts; //no contacts by default
int contact_count = 0;
void *body_state_callback_instance = nullptr;
PhysicsServer3D::BodyStateCallback body_state_callback = nullptr;
Callable body_state_callback;
struct ForceIntegrationCallbackData {
Callable callable;
@ -150,7 +149,7 @@ class GodotBody3D : public GodotCollisionObject3D {
friend class GodotPhysicsDirectBodyState3D; // i give up, too many functions to expose
public:
void set_state_sync_callback(void *p_instance, PhysicsServer3D::BodyStateCallback p_callback);
void set_state_sync_callback(const Callable &p_callable);
void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant());
GodotPhysicsDirectBodyState3D *get_direct_state();

View File

@ -877,10 +877,10 @@ int GodotPhysicsServer3D::body_get_max_contacts_reported(RID p_body) const {
return body->get_max_contacts_reported();
}
void GodotPhysicsServer3D::body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) {
void GodotPhysicsServer3D::body_set_state_sync_callback(RID p_body, const Callable &p_callable) {
GodotBody3D *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
body->set_state_sync_callback(p_instance, p_callback);
body->set_state_sync_callback(p_callable);
}
void GodotPhysicsServer3D::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) {

View File

@ -242,7 +242,7 @@ public:
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 void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) override;
virtual void body_set_state_sync_callback(RID p_body, const Callable &p_callable) 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;

View File

@ -470,10 +470,7 @@ public:
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;
// Callback for C++ use only.
typedef void (*BodyStateCallback)(void *p_instance, PhysicsDirectBodyState2D *p_state);
virtual void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) = 0;
virtual void body_set_state_sync_callback(RID p_body, const Callable &p_callable) = 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;

View File

@ -249,7 +249,7 @@ public:
FUNC2(body_set_omit_force_integration, RID, bool);
FUNC1RC(bool, body_is_omitting_force_integration, RID);
FUNC3(body_set_state_sync_callback, RID, void *, BodyStateCallback);
FUNC2(body_set_state_sync_callback, RID, const Callable &);
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 {

View File

@ -508,10 +508,7 @@ public:
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;
// Callback for C++ use only.
typedef void (*BodyStateCallback)(void *p_instance, PhysicsDirectBodyState3D *p_state);
virtual void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) = 0;
virtual void body_set_state_sync_callback(RID p_body, const Callable &p_callable) = 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;

View File

@ -252,7 +252,7 @@ public:
FUNC2(body_set_omit_force_integration, RID, bool);
FUNC1RC(bool, body_is_omitting_force_integration, RID);
FUNC3(body_set_state_sync_callback, RID, void *, BodyStateCallback);
FUNC2(body_set_state_sync_callback, RID, const Callable &);
FUNC3(body_set_force_integration_callback, RID, const Callable &, const Variant &);
FUNC2(body_set_ray_pickable, RID, bool);

View File

@ -145,7 +145,6 @@ void register_server_types() {
GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionShapeResult, "RID rid;ObjectID collider_id;Object *collider;int shape");
GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionShapeRestInfo, "Vector2 point;Vector2 normal;RID rid;ObjectID collider_id;int shape;Vector2 linear_velocity");
GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionMotionResult, "Vector2 travel;Vector2 remainder;Vector2 collision_point;Vector2 collision_normal;Vector2 collider_velocity;real_t collision_depth;real_t collision_safe_fraction;real_t collision_unsafe_fraction;int collision_local_shape;ObjectID collider_id;RID collider;int collider_shape");
GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionStateCallback, "void *instance;void (*callback)(void *p_instance, PhysicsDirectBodyState2D *p_state)");
GDREGISTER_CLASS(PhysicsServer3DManager);
Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3DManager", PhysicsServer3DManager::get_singleton(), "PhysicsServer3DManager"));
@ -161,7 +160,6 @@ void register_server_types() {
GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionShapeRestInfo, "Vector3 point;Vector3 normal;RID rid;ObjectID collider_id;int shape;Vector3 linear_velocity");
GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionMotionCollision, "Vector3 position;Vector3 normal;Vector3 collider_velocity;real_t depth;int local_shape;ObjectID collider_id;RID collider;int collider_shape");
GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionMotionResult, "Vector3 travel;Vector3 remainder;real_t collision_safe_fraction;real_t collision_unsafe_fraction;PhysicsServer3DExtensionMotionCollision collisions[32];int collision_count");
GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionStateCallback, "void *instance;void (*callback)(void *p_instance, PhysicsDirectBodyState3D *p_state)");
GDREGISTER_ABSTRACT_CLASS(NavigationServer2D);
GDREGISTER_ABSTRACT_CLASS(NavigationServer3D);