Use Callable in Area monitor callback

This commit is contained in:
rafallus 2021-10-31 15:45:58 -06:00
parent 455e027725
commit 770e3a8e51
22 changed files with 194 additions and 214 deletions

View file

@ -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.

View file

@ -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.

View file

@ -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) {

View file

@ -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);

View file

@ -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) {

View file

@ -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 */

View file

@ -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")));

View file

@ -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);

View file

@ -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;
Callable::CallError ce;
Variant ret;
monitor_callback.call((const Variant **)resptr, 5, ret, ce);
}
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);
} 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;
Callable::CallError ce;
Variant ret;
area_monitor_callback.call((const Variant **)resptr, 5, ret, ce);
}
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);
} else {
monitored_areas.clear();
area_monitor_callback = Callable();
}
}
}

View file

@ -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);

View file

@ -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 */

View file

@ -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;

View file

@ -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;
Callable::CallError ce;
Variant ret;
monitor_callback.call((const Variant **)resptr, 5, ret, ce);
}
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);
} 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;
Callable::CallError ce;
Variant ret;
area_monitor_callback.call((const Variant **)resptr, 5, ret, ce);
}
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);
} else {
monitored_areas.clear();
area_monitor_callback = Callable();
}
}
}

View file

@ -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);

View file

@ -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 */

View file

@ -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 */

View file

@ -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);

View file

@ -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 */

View file

@ -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 */

View file

@ -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);

View file

@ -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;

View file

@ -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 */