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"> <method name="area_set_area_monitor_callback">
<return type="void" /> <return type="void" />
<argument index="0" name="area" type="RID" /> <argument index="0" name="area" type="RID" />
<argument index="1" name="receiver" type="Object" /> <argument index="1" name="callback" type="Callable" />
<argument index="2" name="method" type="StringName" />
<description> <description>
</description> </description>
</method> </method>
@ -147,8 +146,7 @@
<method name="area_set_monitor_callback"> <method name="area_set_monitor_callback">
<return type="void" /> <return type="void" />
<argument index="0" name="area" type="RID" /> <argument index="0" name="area" type="RID" />
<argument index="1" name="receiver" type="Object" /> <argument index="1" name="callback" type="Callable" />
<argument index="2" name="method" type="StringName" />
<description> <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: 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. 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"> <method name="area_set_area_monitor_callback">
<return type="void" /> <return type="void" />
<argument index="0" name="area" type="RID" /> <argument index="0" name="area" type="RID" />
<argument index="1" name="receiver" type="Object" /> <argument index="1" name="callback" type="Callable" />
<argument index="2" name="method" type="StringName" />
<description> <description>
</description> </description>
</method> </method>
@ -134,8 +133,7 @@
<method name="area_set_monitor_callback"> <method name="area_set_monitor_callback">
<return type="void" /> <return type="void" />
<argument index="0" name="area" type="RID" /> <argument index="0" name="area" type="RID" />
<argument index="1" name="receiver" type="Object" /> <argument index="1" name="callback" type="Callable" />
<argument index="2" name="method" type="StringName" />
<description> <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: 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. 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) { void AreaBullet::call_event(CollisionObjectBullet *p_otherObject, PhysicsServer3D::AreaBodyStatus p_status) {
InOutEventCallback &event = eventsCallbacks[static_cast<int>(p_otherObject->getType())]; InOutEventCallback &event = eventsCallbacks[static_cast<int>(p_otherObject->getType())];
Object *areaGodoObject = ObjectDB::get_instance(event.event_callback_id);
if (!areaGodoObject) { if (!event.event_callback.is_valid()) {
event.event_callback_id = ObjectID(); event.event_callback = Callable();
return; return;
} }
@ -108,7 +107,8 @@ void AreaBullet::call_event(CollisionObjectBullet *p_otherObject, PhysicsServer3
call_event_res[4] = 0; // self_shape ID call_event_res[4] = 0; // self_shape ID
Callable::CallError outResp; 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() { 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)]; InOutEventCallback &ev = eventsCallbacks[static_cast<int>(p_callbackObjectType)];
ev.event_callback_id = p_id; ev.event_callback = p_callback;
ev.event_callback_method = p_method;
/// Set if monitoring /// 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); set_godot_object_flags(get_godot_object_flags() | GOF_IS_MONITORING_AREA);
} else { } else {
set_godot_object_flags(get_godot_object_flags() & (~GOF_IS_MONITORING_AREA)); 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) { 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) { void AreaBullet::on_enter_area(AreaBullet *p_area) {

View file

@ -47,8 +47,7 @@ class AreaBullet : public RigidCollisionObjectBullet {
public: public:
struct InOutEventCallback { struct InOutEventCallback {
ObjectID event_callback_id; Callable event_callback;
StringName event_callback_method;
InOutEventCallback() {} InOutEventCallback() {}
}; };
@ -162,7 +161,7 @@ public:
void set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value); void set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value);
Variant get_param(PhysicsServer3D::AreaParameter p_param) const; 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); bool has_event_callback(Type p_callbackObjectType);
virtual void on_enter_area(AreaBullet *p_area); 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); 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); AreaBullet *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!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); AreaBullet *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!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) { 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_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_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_monitor_callback(RID p_area, const Callable &p_callback) override;
virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) 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; virtual void area_set_ray_pickable(RID p_area, bool p_enable) override;
/* RIGID BODY API */ /* RIGID BODY API */

View file

@ -369,12 +369,11 @@ void Area2D::set_monitoring(bool p_enable) {
monitoring = p_enable; monitoring = p_enable;
if (monitoring) { if (monitoring) {
PhysicsServer2D::get_singleton()->area_set_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_body_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(), this, SceneStringNames::get_singleton()->_area_inout); PhysicsServer2D::get_singleton()->area_set_area_monitor_callback(get_rid(), callable_mp(this, &Area2D::_area_inout));
} else { } else {
PhysicsServer2D::get_singleton()->area_set_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(), nullptr, StringName()); PhysicsServer2D::get_singleton()->area_set_area_monitor_callback(get_rid(), Callable());
_clear_monitoring(); _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("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("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_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_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"))); 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; monitoring = p_enable;
if (monitoring) { if (monitoring) {
PhysicsServer3D::get_singleton()->area_set_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_body_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(), this, SceneStringNames::get_singleton()->_area_inout); PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), callable_mp(this, &Area3D::_area_inout));
} else { } else {
PhysicsServer3D::get_singleton()->area_set_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(), nullptr, StringName()); PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), Callable());
_clear_monitoring(); _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_body", "body"), &Area3D::overlaps_body);
ClassDB::bind_method(D_METHOD("overlaps_area", "area"), &Area3D::overlaps_area); 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("set_audio_bus_override", "enable"), &Area3D::set_audio_bus_override);
ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area3D::is_overriding_audio_bus); 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); _set_space(p_space);
} }
void GodotArea2D::set_monitor_callback(ObjectID p_id, const StringName &p_method) { void GodotArea2D::set_monitor_callback(const Callable &p_callback) {
if (p_id == monitor_callback_id) { ObjectID id = p_callback.get_object_id();
monitor_callback_method = p_method;
if (id == monitor_callback.get_object_id()) {
monitor_callback = p_callback;
return; return;
} }
_unregister_shapes(); _unregister_shapes();
monitor_callback_id = p_id; monitor_callback = p_callback;
monitor_callback_method = p_method;
monitored_bodies.clear(); monitored_bodies.clear();
monitored_areas.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) { void GodotArea2D::set_area_monitor_callback(const Callable &p_callback) {
if (p_id == area_monitor_callback_id) { ObjectID id = p_callback.get_object_id();
area_monitor_callback_method = p_method;
if (id == area_monitor_callback.get_object_id()) {
area_monitor_callback = p_callback;
return; return;
} }
_unregister_shapes(); _unregister_shapes();
area_monitor_callback_id = p_id; area_monitor_callback = p_callback;
area_monitor_callback_method = p_method;
monitored_bodies.clear(); monitored_bodies.clear();
monitored_areas.clear(); monitored_areas.clear();
@ -199,77 +201,75 @@ void GodotArea2D::set_monitorable(bool p_monitorable) {
} }
void GodotArea2D::call_queries() { void GodotArea2D::call_queries() {
if (monitor_callback_id.is_valid() && !monitored_bodies.is_empty()) { if (!monitor_callback.is_null() && !monitored_bodies.is_empty()) {
Variant res[5]; if (monitor_callback.is_valid()) {
Variant *resptr[5]; Variant res[5];
for (int i = 0; i < 5; i++) { Variant *resptr[5];
resptr[i] = &res[i]; for (int i = 0; i < 5; i++) {
} resptr[i] = &res[i];
}
Object *obj = ObjectDB::get_instance(monitor_callback_id); for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) {
if (!obj) { if (E->get().state == 0) { // Nothing happened
monitored_bodies.clear(); Map<BodyKey, BodyState>::Element *next = E->next();
monitor_callback_id = ObjectID(); monitored_bodies.erase(E);
return; 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(); Map<BodyKey, BodyState>::Element *next = E->next();
monitored_bodies.erase(E); monitored_bodies.erase(E);
E = next; E = next;
continue;
Callable::CallError ce;
Variant ret;
monitor_callback.call((const Variant **)resptr, 5, ret, ce);
} }
} else {
res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED; monitored_bodies.clear();
res[1] = E->key().rid; monitor_callback = Callable();
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);
} }
} }
if (area_monitor_callback_id.is_valid() && !monitored_areas.is_empty()) { if (!area_monitor_callback.is_null() && !monitored_areas.is_empty()) {
Variant res[5]; if (area_monitor_callback.is_valid()) {
Variant *resptr[5]; Variant res[5];
for (int i = 0; i < 5; i++) { Variant *resptr[5];
resptr[i] = &res[i]; for (int i = 0; i < 5; i++) {
} resptr[i] = &res[i];
}
Object *obj = ObjectDB::get_instance(area_monitor_callback_id); for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) {
if (!obj) { if (E->get().state == 0) { // Nothing happened
monitored_areas.clear(); Map<BodyKey, BodyState>::Element *next = E->next();
area_monitor_callback_id = ObjectID(); monitored_areas.erase(E);
return; 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(); Map<BodyKey, BodyState>::Element *next = E->next();
monitored_areas.erase(E); monitored_areas.erase(E);
E = next; E = next;
continue;
Callable::CallError ce;
Variant ret;
area_monitor_callback.call((const Variant **)resptr, 5, ret, ce);
} }
} else {
res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED; monitored_areas.clear();
res[1] = E->key().rid; area_monitor_callback = Callable();
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);
} }
} }
} }

View file

@ -52,11 +52,9 @@ class GodotArea2D : public GodotCollisionObject2D {
int priority = 0; int priority = 0;
bool monitorable = false; bool monitorable = false;
ObjectID monitor_callback_id; Callable monitor_callback;
StringName monitor_callback_method;
ObjectID area_monitor_callback_id; Callable area_monitor_callback;
StringName area_monitor_callback_method;
SelfList<GodotArea2D> monitor_query_list; SelfList<GodotArea2D> monitor_query_list;
SelfList<GodotArea2D> moved_list; SelfList<GodotArea2D> moved_list;
@ -99,11 +97,11 @@ class GodotArea2D : public GodotCollisionObject2D {
void _queue_monitor_update(); void _queue_monitor_update();
public: public:
void set_monitor_callback(ObjectID p_id, const StringName &p_method); void set_monitor_callback(const Callable &p_callback);
_FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id.is_valid(); } _FORCE_INLINE_ bool has_monitor_callback() const { return !monitor_callback.is_null(); }
void set_area_monitor_callback(ObjectID p_id, const StringName &p_method); void set_area_monitor_callback(const Callable &p_callback);
_FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id.is_valid(); } _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 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); _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); 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); GodotArea2D *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!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); GodotArea2D *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!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 */ /* 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_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_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_monitor_callback(RID p_area, const Callable &p_callback) override;
virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) 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; 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); _set_space(p_space);
} }
void GodotArea3D::set_monitor_callback(ObjectID p_id, const StringName &p_method) { void GodotArea3D::set_monitor_callback(const Callable &p_callback) {
if (p_id == monitor_callback_id) { ObjectID id = p_callback.get_object_id();
monitor_callback_method = p_method; if (id == monitor_callback.get_object_id()) {
monitor_callback = p_callback;
return; return;
} }
_unregister_shapes(); _unregister_shapes();
monitor_callback_id = p_id; monitor_callback = p_callback;
monitor_callback_method = p_method;
monitored_bodies.clear(); monitored_bodies.clear();
monitored_areas.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) { void GodotArea3D::set_area_monitor_callback(const Callable &p_callback) {
if (p_id == area_monitor_callback_id) { ObjectID id = p_callback.get_object_id();
area_monitor_callback_method = p_method; if (id == area_monitor_callback.get_object_id()) {
area_monitor_callback = p_callback;
return; return;
} }
_unregister_shapes(); _unregister_shapes();
area_monitor_callback_id = p_id; area_monitor_callback = p_callback;
area_monitor_callback_method = p_method;
monitored_bodies.clear(); monitored_bodies.clear();
monitored_areas.clear(); monitored_areas.clear();
@ -230,77 +230,75 @@ void GodotArea3D::set_monitorable(bool p_monitorable) {
} }
void GodotArea3D::call_queries() { void GodotArea3D::call_queries() {
if (monitor_callback_id.is_valid() && !monitored_bodies.is_empty()) { if (!monitor_callback.is_null() && !monitored_bodies.is_empty()) {
Variant res[5]; if (monitor_callback.is_valid()) {
Variant *resptr[5]; Variant res[5];
for (int i = 0; i < 5; i++) { Variant *resptr[5];
resptr[i] = &res[i]; for (int i = 0; i < 5; i++) {
} resptr[i] = &res[i];
}
Object *obj = ObjectDB::get_instance(monitor_callback_id); for (Map<BodyKey, BodyState>::Element *E = monitored_bodies.front(); E;) {
if (!obj) { if (E->get().state == 0) { // Nothing happened
monitored_bodies.clear(); Map<BodyKey, BodyState>::Element *next = E->next();
monitor_callback_id = ObjectID(); monitored_bodies.erase(E);
return; 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(); Map<BodyKey, BodyState>::Element *next = E->next();
monitored_bodies.erase(E); monitored_bodies.erase(E);
E = next; E = next;
continue;
Callable::CallError ce;
Variant ret;
monitor_callback.call((const Variant **)resptr, 5, ret, ce);
} }
} else {
res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED; monitored_bodies.clear();
res[1] = E->key().rid; monitor_callback = Callable();
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);
} }
} }
if (area_monitor_callback_id.is_valid() && !monitored_areas.is_empty()) { if (!area_monitor_callback.is_null() && !monitored_areas.is_empty()) {
Variant res[5]; if (area_monitor_callback.is_valid()) {
Variant *resptr[5]; Variant res[5];
for (int i = 0; i < 5; i++) { Variant *resptr[5];
resptr[i] = &res[i]; for (int i = 0; i < 5; i++) {
} resptr[i] = &res[i];
}
Object *obj = ObjectDB::get_instance(area_monitor_callback_id); for (Map<BodyKey, BodyState>::Element *E = monitored_areas.front(); E;) {
if (!obj) { if (E->get().state == 0) { // Nothing happened
monitored_areas.clear(); Map<BodyKey, BodyState>::Element *next = E->next();
area_monitor_callback_id = ObjectID(); monitored_areas.erase(E);
return; 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(); Map<BodyKey, BodyState>::Element *next = E->next();
monitored_areas.erase(E); monitored_areas.erase(E);
E = next; E = next;
continue;
Callable::CallError ce;
Variant ret;
area_monitor_callback.call((const Variant **)resptr, 5, ret, ce);
} }
} else {
res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED; monitored_areas.clear();
res[1] = E->key().rid; area_monitor_callback = Callable();
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);
} }
} }
} }

View file

@ -57,11 +57,8 @@ class GodotArea3D : public GodotCollisionObject3D {
int priority = 0; int priority = 0;
bool monitorable = false; bool monitorable = false;
ObjectID monitor_callback_id; Callable monitor_callback;
StringName monitor_callback_method; Callable area_monitor_callback;
ObjectID area_monitor_callback_id;
StringName area_monitor_callback_method;
SelfList<GodotArea3D> monitor_query_list; SelfList<GodotArea3D> monitor_query_list;
SelfList<GodotArea3D> moved_list; SelfList<GodotArea3D> moved_list;
@ -106,11 +103,11 @@ class GodotArea3D : public GodotCollisionObject3D {
void _queue_monitor_update(); void _queue_monitor_update();
public: public:
void set_monitor_callback(ObjectID p_id, const StringName &p_method); void set_monitor_callback(const Callable &p_callback);
_FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id.is_valid(); } _FORCE_INLINE_ bool has_monitor_callback() const { return !monitor_callback.is_null(); }
void set_area_monitor_callback(ObjectID p_id, const StringName &p_method); void set_area_monitor_callback(const Callable &p_callback);
_FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id.is_valid(); } _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 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); _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); 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); GodotArea3D *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!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) { 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); 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); GodotArea3D *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!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 */ /* 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_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_monitor_callback(RID p_area, const Callable &p_callback) override;
virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) override; virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) override;
/* BODY API */ /* 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_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_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_monitor_callback", "area", "callback"), &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_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("area_set_monitorable", "area", "monitorable"), &PhysicsServer2D::area_set_monitorable);
ClassDB::bind_method(D_METHOD("body_create"), &PhysicsServer2D::body_create); 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_monitorable(RID p_area, bool p_monitorable) = 0;
virtual void area_set_pickable(RID p_area, bool p_pickable) = 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_monitor_callback(RID p_area, const Callable &p_callback) = 0;
virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0; virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) = 0;
/* BODY API */ /* BODY API */

View file

@ -165,8 +165,8 @@ public:
FUNC2(area_set_monitorable, RID, bool); FUNC2(area_set_monitorable, RID, bool);
FUNC2(area_set_pickable, RID, bool); FUNC2(area_set_pickable, RID, bool);
FUNC3(area_set_monitor_callback, RID, Object *, const StringName &); FUNC2(area_set_monitor_callback, RID, const Callable &);
FUNC3(area_set_area_monitor_callback, RID, Object *, const StringName &); FUNC2(area_set_area_monitor_callback, RID, const Callable &);
/* BODY API */ /* 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_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_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_monitor_callback", "area", "callback"), &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_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_monitorable", "area", "monitorable"), &PhysicsServer3D::area_set_monitorable);
ClassDB::bind_method(D_METHOD("area_set_ray_pickable", "area", "enable"), &PhysicsServer3D::area_set_ray_pickable); 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_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_monitor_callback(RID p_area, const Callable &p_callback) = 0;
virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 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; 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_monitorable, RID, bool);
FUNC2(area_set_ray_pickable, RID, bool); FUNC2(area_set_ray_pickable, RID, bool);
FUNC3(area_set_monitor_callback, RID, Object *, const StringName &); FUNC2(area_set_monitor_callback, RID, const Callable &);
FUNC3(area_set_area_monitor_callback, RID, Object *, const StringName &); FUNC2(area_set_area_monitor_callback, RID, const Callable &);
/* BODY API */ /* BODY API */