added ability for Area (3D) to detect other areas
This commit is contained in:
parent
8945670bc0
commit
89300b70e7
10 changed files with 500 additions and 22 deletions
|
@ -225,6 +225,7 @@ void Area::_clear_monitoring() {
|
|||
}
|
||||
ERR_FAIL_COND(locked);
|
||||
|
||||
{
|
||||
Map<ObjectID,BodyState> bmcopy = body_map;
|
||||
body_map.clear();
|
||||
//disconnect all monitored stuff
|
||||
|
@ -248,6 +249,34 @@ void Area::_clear_monitoring() {
|
|||
node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_body_exit_tree);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
Map<ObjectID,AreaState> bmcopy = area_map;
|
||||
area_map.clear();
|
||||
//disconnect all monitored stuff
|
||||
|
||||
for (Map<ObjectID,AreaState>::Element *E=bmcopy.front();E;E=E->next()) {
|
||||
|
||||
Object *obj = ObjectDB::get_instance(E->key());
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
ERR_CONTINUE(!node);
|
||||
if (!E->get().in_tree)
|
||||
continue;
|
||||
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->area_exit_shape,E->key(),node,E->get().shapes[i].area_shape,E->get().shapes[i].self_shape);
|
||||
}
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->area_exit,obj);
|
||||
|
||||
node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_area_enter_tree);
|
||||
node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_area_exit_tree);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
void Area::_notification(int p_what) {
|
||||
|
||||
|
@ -271,12 +300,129 @@ void Area::set_enable_monitoring(bool p_enable) {
|
|||
if (monitoring) {
|
||||
|
||||
PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(),this,"_body_inout");
|
||||
PhysicsServer::get_singleton()->area_set_area_monitor_callback(get_rid(),this,"_area_inout");
|
||||
} else {
|
||||
PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(),NULL,StringName());
|
||||
PhysicsServer::get_singleton()->area_set_area_monitor_callback(get_rid(),NULL,StringName());
|
||||
_clear_monitoring();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Area::_area_enter_tree(ObjectID p_id) {
|
||||
|
||||
Object *obj = ObjectDB::get_instance(p_id);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
ERR_FAIL_COND(!node);
|
||||
|
||||
Map<ObjectID,AreaState>::Element *E=area_map.find(p_id);
|
||||
ERR_FAIL_COND(!E);
|
||||
ERR_FAIL_COND(E->get().in_tree);
|
||||
|
||||
E->get().in_tree=true;
|
||||
emit_signal(SceneStringNames::get_singleton()->area_enter,node);
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->area_enter_shape,p_id,node,E->get().shapes[i].area_shape,E->get().shapes[i].self_shape);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Area::_area_exit_tree(ObjectID p_id) {
|
||||
|
||||
Object *obj = ObjectDB::get_instance(p_id);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
ERR_FAIL_COND(!node);
|
||||
Map<ObjectID,AreaState>::Element *E=area_map.find(p_id);
|
||||
ERR_FAIL_COND(!E);
|
||||
ERR_FAIL_COND(!E->get().in_tree);
|
||||
E->get().in_tree=false;
|
||||
emit_signal(SceneStringNames::get_singleton()->area_exit,node);
|
||||
for(int i=0;i<E->get().shapes.size();i++) {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->area_exit_shape,p_id,node,E->get().shapes[i].area_shape,E->get().shapes[i].self_shape);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Area::_area_inout(int p_status,const RID& p_area, int p_instance, int p_area_shape,int p_self_shape) {
|
||||
|
||||
|
||||
bool area_in = p_status==PhysicsServer::AREA_BODY_ADDED;
|
||||
ObjectID objid=p_instance;
|
||||
|
||||
Object *obj = ObjectDB::get_instance(objid);
|
||||
Node *node = obj ? obj->cast_to<Node>() : NULL;
|
||||
|
||||
Map<ObjectID,AreaState>::Element *E=area_map.find(objid);
|
||||
|
||||
ERR_FAIL_COND(!area_in && !E);
|
||||
|
||||
locked=true;
|
||||
|
||||
if (area_in) {
|
||||
if (!E) {
|
||||
|
||||
E = area_map.insert(objid,AreaState());
|
||||
E->get().rc=0;
|
||||
E->get().in_tree=node && node->is_inside_tree();
|
||||
if (node) {
|
||||
node->connect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_area_enter_tree,make_binds(objid));
|
||||
node->connect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_area_exit_tree,make_binds(objid));
|
||||
if (E->get().in_tree) {
|
||||
emit_signal(SceneStringNames::get_singleton()->area_enter,node);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
E->get().rc++;
|
||||
if (node)
|
||||
E->get().shapes.insert(AreaShapePair(p_area_shape,p_self_shape));
|
||||
|
||||
|
||||
if (!node || E->get().in_tree) {
|
||||
emit_signal(SceneStringNames::get_singleton()->area_enter_shape,objid,node,p_area_shape,p_self_shape);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
E->get().rc--;
|
||||
|
||||
if (node)
|
||||
E->get().shapes.erase(AreaShapePair(p_area_shape,p_self_shape));
|
||||
|
||||
bool eraseit=false;
|
||||
|
||||
if (E->get().rc==0) {
|
||||
|
||||
if (node) {
|
||||
node->disconnect(SceneStringNames::get_singleton()->enter_tree,this,SceneStringNames::get_singleton()->_area_enter_tree);
|
||||
node->disconnect(SceneStringNames::get_singleton()->exit_tree,this,SceneStringNames::get_singleton()->_area_exit_tree);
|
||||
if (E->get().in_tree) {
|
||||
emit_signal(SceneStringNames::get_singleton()->area_exit,obj);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
eraseit=true;
|
||||
|
||||
}
|
||||
if (!node || E->get().in_tree) {
|
||||
emit_signal(SceneStringNames::get_singleton()->area_exit_shape,objid,obj,p_area_shape,p_self_shape);
|
||||
}
|
||||
|
||||
if (eraseit)
|
||||
area_map.erase(E);
|
||||
|
||||
}
|
||||
|
||||
locked=false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool Area::is_monitoring_enabled() const {
|
||||
|
||||
return monitoring;
|
||||
|
@ -302,11 +448,76 @@ Array Area::get_overlapping_bodies() const {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void Area::set_monitorable(bool p_enable) {
|
||||
|
||||
if (locked) {
|
||||
ERR_EXPLAIN("This function can't be used during the in/out signal.");
|
||||
}
|
||||
ERR_FAIL_COND(locked);
|
||||
|
||||
if (p_enable==monitorable)
|
||||
return;
|
||||
|
||||
monitorable=p_enable;
|
||||
|
||||
PhysicsServer::get_singleton()->area_set_monitorable(get_rid(),monitorable);
|
||||
}
|
||||
|
||||
bool Area::is_monitorable() const {
|
||||
|
||||
return monitorable;
|
||||
}
|
||||
|
||||
|
||||
Array Area::get_overlapping_areas() const {
|
||||
|
||||
ERR_FAIL_COND_V(!monitoring,Array());
|
||||
Array ret;
|
||||
ret.resize(area_map.size());
|
||||
int idx=0;
|
||||
for (const Map<ObjectID,AreaState>::Element *E=area_map.front();E;E=E->next()) {
|
||||
Object *obj = ObjectDB::get_instance(E->key());
|
||||
if (!obj) {
|
||||
ret.resize( ret.size() -1 ); //ops
|
||||
} else {
|
||||
ret[idx++]=obj;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Area::overlaps_area(Node* p_area) const {
|
||||
|
||||
ERR_FAIL_NULL_V(p_area,false);
|
||||
const Map<ObjectID,AreaState>::Element *E=area_map.find(p_area->get_instance_ID());
|
||||
if (!E)
|
||||
return false;
|
||||
return E->get().in_tree;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool Area::overlaps_body(Node* p_body) const{
|
||||
|
||||
ERR_FAIL_NULL_V(p_body,false);
|
||||
const Map<ObjectID,BodyState>::Element *E=body_map.find(p_body->get_instance_ID());
|
||||
if (!E)
|
||||
return false;
|
||||
return E->get().in_tree;
|
||||
|
||||
}
|
||||
|
||||
void Area::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_body_enter_tree","id"),&Area::_body_enter_tree);
|
||||
ObjectTypeDB::bind_method(_MD("_body_exit_tree","id"),&Area::_body_exit_tree);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_area_enter_tree","id"),&Area::_area_enter_tree);
|
||||
ObjectTypeDB::bind_method(_MD("_area_exit_tree","id"),&Area::_area_exit_tree);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_space_override_mode","enable"),&Area::set_space_override_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_space_override_mode"),&Area::get_space_override_mode);
|
||||
|
||||
|
@ -328,13 +539,21 @@ void Area::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("set_priority","priority"),&Area::set_priority);
|
||||
ObjectTypeDB::bind_method(_MD("get_priority"),&Area::get_priority);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_monitorable","enable"),&Area::set_monitorable);
|
||||
ObjectTypeDB::bind_method(_MD("is_monitorable"),&Area::is_monitorable);
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_enable_monitoring","enable"),&Area::set_enable_monitoring);
|
||||
ObjectTypeDB::bind_method(_MD("is_monitoring_enabled"),&Area::is_monitoring_enabled);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_overlapping_bodies"),&Area::get_overlapping_bodies);
|
||||
ObjectTypeDB::bind_method(_MD("get_overlapping_areas"),&Area::get_overlapping_areas);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("overlaps_body:PhysicsBody","body"),&Area::overlaps_body);
|
||||
ObjectTypeDB::bind_method(_MD("overlaps_area:Area","area"),&Area::overlaps_area);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_body_inout"),&Area::_body_inout);
|
||||
ObjectTypeDB::bind_method(_MD("_area_inout"),&Area::_area_inout);
|
||||
|
||||
|
||||
ADD_SIGNAL( MethodInfo("body_enter_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape")));
|
||||
|
@ -342,6 +561,11 @@ void Area::_bind_methods() {
|
|||
ADD_SIGNAL( MethodInfo("body_enter",PropertyInfo(Variant::OBJECT,"body")));
|
||||
ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body")));
|
||||
|
||||
ADD_SIGNAL( MethodInfo("area_enter_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"area_shape")));
|
||||
ADD_SIGNAL( MethodInfo("area_exit_shape",PropertyInfo(Variant::INT,"area_id"),PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area"),PropertyInfo(Variant::INT,"area_shape"),PropertyInfo(Variant::INT,"area_shape")));
|
||||
ADD_SIGNAL( MethodInfo("area_enter",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area")));
|
||||
ADD_SIGNAL( MethodInfo("area_exit",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area")));
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"space_override",PROPERTY_HINT_ENUM,"Disabled,Combine,Replace"),_SCS("set_space_override_mode"),_SCS("get_space_override_mode"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gravity_point"),_SCS("set_gravity_is_point"),_SCS("is_gravity_a_point"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_distance_scale", PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_gravity_distance_scale"),_SCS("get_gravity_distance_scale"));
|
||||
|
@ -350,6 +574,7 @@ void Area::_bind_methods() {
|
|||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"density",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_density"),_SCS("get_density"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitorable"),_SCS("set_monitorable"),_SCS("is_monitorable"));
|
||||
|
||||
}
|
||||
|
||||
|
@ -366,6 +591,7 @@ Area::Area() : CollisionObject(PhysicsServer::get_singleton()->area_create(),tru
|
|||
monitoring=false;
|
||||
set_ray_pickable(false);
|
||||
set_enable_monitoring(true);
|
||||
set_monitorable(true);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ private:
|
|||
real_t density;
|
||||
int priority;
|
||||
bool monitoring;
|
||||
bool monitorable;
|
||||
bool locked;
|
||||
|
||||
|
||||
|
@ -84,6 +85,36 @@ private:
|
|||
};
|
||||
|
||||
Map<ObjectID,BodyState> body_map;
|
||||
|
||||
|
||||
void _area_inout(int p_status,const RID& p_area, int p_instance, int p_area_shape,int p_self_shape);
|
||||
|
||||
void _area_enter_tree(ObjectID p_id);
|
||||
void _area_exit_tree(ObjectID p_id);
|
||||
|
||||
struct AreaShapePair {
|
||||
|
||||
int area_shape;
|
||||
int self_shape;
|
||||
bool operator<(const AreaShapePair& p_sp) const {
|
||||
if (area_shape==p_sp.area_shape)
|
||||
return self_shape < p_sp.self_shape;
|
||||
else
|
||||
return area_shape < p_sp.area_shape;
|
||||
}
|
||||
|
||||
AreaShapePair() {}
|
||||
AreaShapePair(int p_bs, int p_as) { area_shape=p_bs; self_shape=p_as; }
|
||||
};
|
||||
|
||||
struct AreaState {
|
||||
|
||||
int rc;
|
||||
bool in_tree;
|
||||
VSet<AreaShapePair> shapes;
|
||||
};
|
||||
|
||||
Map<ObjectID,AreaState> area_map;
|
||||
void _clear_monitoring();
|
||||
|
||||
|
||||
|
@ -117,7 +148,14 @@ public:
|
|||
void set_enable_monitoring(bool p_enable);
|
||||
bool is_monitoring_enabled() const;
|
||||
|
||||
void set_monitorable(bool p_enable);
|
||||
bool is_monitorable() const;
|
||||
|
||||
Array get_overlapping_bodies() const;
|
||||
Array get_overlapping_areas() const; //function for script
|
||||
|
||||
bool overlaps_area(Node* p_area) const;
|
||||
bool overlaps_body(Node* p_body) const;
|
||||
|
||||
|
||||
Area();
|
||||
|
|
|
@ -93,3 +93,72 @@ AreaPairSW::~AreaPairSW() {
|
|||
body->remove_constraint(this);
|
||||
area->remove_constraint(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
bool Area2PairSW::setup(float p_step) {
|
||||
|
||||
// bool result = area_a->test_collision_mask(area_b) && CollisionSolverSW::solve(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),Vector2(),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),Vector2(),NULL,this);
|
||||
bool result = CollisionSolverSW::solve_static(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),NULL,this);
|
||||
|
||||
if (result!=colliding) {
|
||||
|
||||
if (result) {
|
||||
|
||||
if (area_b->has_area_monitor_callback() && area_a->is_monitorable())
|
||||
area_b->add_area_to_query(area_a,shape_a,shape_b);
|
||||
|
||||
if (area_a->has_area_monitor_callback() && area_b->is_monitorable())
|
||||
area_a->add_area_to_query(area_b,shape_b,shape_a);
|
||||
|
||||
} else {
|
||||
|
||||
if (area_b->has_area_monitor_callback() && area_a->is_monitorable())
|
||||
area_b->remove_area_from_query(area_a,shape_a,shape_b);
|
||||
|
||||
if (area_a->has_area_monitor_callback() && area_b->is_monitorable())
|
||||
area_a->remove_area_from_query(area_b,shape_b,shape_a);
|
||||
}
|
||||
|
||||
colliding=result;
|
||||
|
||||
}
|
||||
|
||||
return false; //never do any post solving
|
||||
}
|
||||
|
||||
void Area2PairSW::solve(float p_step) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
Area2PairSW::Area2PairSW(AreaSW *p_area_a,int p_shape_a, AreaSW *p_area_b,int p_shape_b) {
|
||||
|
||||
|
||||
area_a=p_area_a;
|
||||
area_b=p_area_b;
|
||||
shape_a=p_shape_a;
|
||||
shape_b=p_shape_b;
|
||||
colliding=false;
|
||||
area_a->add_constraint(this);
|
||||
area_b->add_constraint(this);
|
||||
|
||||
}
|
||||
|
||||
Area2PairSW::~Area2PairSW() {
|
||||
|
||||
if (colliding) {
|
||||
|
||||
if (area_b->has_area_monitor_callback() && area_a->is_monitorable())
|
||||
area_b->remove_area_from_query(area_a,shape_a,shape_b);
|
||||
|
||||
if (area_a->has_area_monitor_callback() && area_b->is_monitorable())
|
||||
area_a->remove_area_from_query(area_b,shape_b,shape_a);
|
||||
}
|
||||
|
||||
area_a->remove_constraint(this);
|
||||
area_b->remove_constraint(this);
|
||||
}
|
||||
|
|
|
@ -49,5 +49,23 @@ public:
|
|||
~AreaPairSW();
|
||||
};
|
||||
|
||||
|
||||
class Area2PairSW : public ConstraintSW {
|
||||
|
||||
AreaSW *area_a;
|
||||
AreaSW *area_b;
|
||||
int shape_a;
|
||||
int shape_b;
|
||||
bool colliding;
|
||||
public:
|
||||
|
||||
bool setup(float p_step);
|
||||
void solve(float p_step);
|
||||
|
||||
Area2PairSW(AreaSW *p_area_a,int p_shape_a, AreaSW *p_area_b,int p_shape_b);
|
||||
~Area2PairSW();
|
||||
};
|
||||
|
||||
|
||||
#endif // AREA_PAIR__SW_H
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "body_sw.h"
|
||||
|
||||
AreaSW::BodyKey::BodyKey(BodySW *p_body, uint32_t p_body_shape,uint32_t p_area_shape) { rid=p_body->get_self(); instance_id=p_body->get_instance_id(); body_shape=p_body_shape; area_shape=p_area_shape; }
|
||||
AreaSW::BodyKey::BodyKey(AreaSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape) { rid=p_body->get_self(); instance_id=p_body->get_instance_id(); body_shape=p_body_shape; area_shape=p_area_shape; }
|
||||
|
||||
void AreaSW::_shapes_changed() {
|
||||
|
||||
|
@ -57,6 +58,7 @@ void AreaSW::set_space(SpaceSW *p_space) {
|
|||
}
|
||||
|
||||
monitored_bodies.clear();
|
||||
monitored_areas.clear();
|
||||
|
||||
_set_space(p_space);
|
||||
}
|
||||
|
@ -76,11 +78,32 @@ void AreaSW::set_monitor_callback(ObjectID p_id, const StringName& p_method) {
|
|||
monitor_callback_method=p_method;
|
||||
|
||||
monitored_bodies.clear();
|
||||
monitored_areas.clear();
|
||||
|
||||
|
||||
_shape_changed();
|
||||
|
||||
}
|
||||
|
||||
void AreaSW::set_area_monitor_callback(ObjectID p_id, const StringName& p_method) {
|
||||
|
||||
|
||||
if (p_id==area_monitor_callback_id) {
|
||||
area_monitor_callback_method=p_method;
|
||||
return;
|
||||
}
|
||||
|
||||
_unregister_shapes();
|
||||
|
||||
area_monitor_callback_id=p_id;
|
||||
area_monitor_callback_method=p_method;
|
||||
|
||||
monitored_bodies.clear();
|
||||
monitored_areas.clear();
|
||||
|
||||
_shape_changed();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void AreaSW::set_space_override_mode(PhysicsServer::AreaSpaceOverrideMode p_mode) {
|
||||
|
@ -134,6 +157,15 @@ void AreaSW::_queue_monitor_update() {
|
|||
|
||||
}
|
||||
|
||||
void AreaSW::set_monitorable(bool p_monitorable) {
|
||||
|
||||
if (monitorable==p_monitorable)
|
||||
return;
|
||||
|
||||
monitorable=p_monitorable;
|
||||
_set_static(!monitorable);
|
||||
}
|
||||
|
||||
void AreaSW::call_queries() {
|
||||
|
||||
if (monitor_callback_id && !monitored_bodies.empty()) {
|
||||
|
@ -168,6 +200,41 @@ void AreaSW::call_queries() {
|
|||
|
||||
monitored_bodies.clear();
|
||||
|
||||
if (area_monitor_callback_id && !monitored_areas.empty()) {
|
||||
|
||||
|
||||
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=0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (Map<BodyKey,BodyState>::Element *E=monitored_areas.front();E;E=E->next()) {
|
||||
|
||||
if (E->get().state==0)
|
||||
continue; //nothing happened
|
||||
|
||||
res[0]=E->get().state>0 ? PhysicsServer::AREA_BODY_ADDED : PhysicsServer::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;
|
||||
|
||||
|
||||
Variant::CallError ce;
|
||||
obj->call(area_monitor_callback_method,(const Variant**)resptr,5,ce);
|
||||
}
|
||||
}
|
||||
|
||||
monitored_areas.clear();
|
||||
//get_space()->area_remove_from_monitor_query_list(&monitor_query_list);
|
||||
|
||||
}
|
||||
|
@ -185,6 +252,8 @@ AreaSW::AreaSW() : CollisionObjectSW(TYPE_AREA), monitor_query_list(this), move
|
|||
priority=0;
|
||||
set_ray_pickable(false);
|
||||
monitor_callback_id=0;
|
||||
area_monitor_callback_id=0;
|
||||
monitorable=false;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -49,10 +49,14 @@ class AreaSW : public CollisionObjectSW{
|
|||
float point_attenuation;
|
||||
float density;
|
||||
int priority;
|
||||
bool monitorable;
|
||||
|
||||
ObjectID monitor_callback_id;
|
||||
StringName monitor_callback_method;
|
||||
|
||||
ObjectID area_monitor_callback_id;
|
||||
StringName area_monitor_callback_method;
|
||||
|
||||
SelfList<AreaSW> monitor_query_list;
|
||||
SelfList<AreaSW> moved_list;
|
||||
|
||||
|
@ -79,6 +83,8 @@ class AreaSW : public CollisionObjectSW{
|
|||
|
||||
_FORCE_INLINE_ BodyKey() {}
|
||||
BodyKey(BodySW *p_body, uint32_t p_body_shape,uint32_t p_area_shape);
|
||||
BodyKey(AreaSW *p_body, uint32_t p_body_shape,uint32_t p_area_shape);
|
||||
|
||||
};
|
||||
|
||||
struct BodyState {
|
||||
|
@ -90,6 +96,7 @@ class AreaSW : public CollisionObjectSW{
|
|||
};
|
||||
|
||||
Map<BodyKey,BodyState> monitored_bodies;
|
||||
Map<BodyKey,BodyState> monitored_areas;
|
||||
|
||||
//virtual void shape_changed_notify(ShapeSW *p_shape);
|
||||
//virtual void shape_deleted_notify(ShapeSW *p_shape);
|
||||
|
@ -108,9 +115,15 @@ public:
|
|||
void set_monitor_callback(ObjectID p_id, const StringName& p_method);
|
||||
_FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id; }
|
||||
|
||||
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; }
|
||||
|
||||
_FORCE_INLINE_ void add_body_to_query(BodySW *p_body, uint32_t p_body_shape,uint32_t p_area_shape);
|
||||
_FORCE_INLINE_ void remove_body_from_query(BodySW *p_body, uint32_t p_body_shape,uint32_t p_area_shape);
|
||||
|
||||
_FORCE_INLINE_ void add_area_to_query(AreaSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape);
|
||||
_FORCE_INLINE_ void remove_area_from_query(AreaSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape);
|
||||
|
||||
void set_param(PhysicsServer::AreaParameter p_param, const Variant& p_value);
|
||||
Variant get_param(PhysicsServer::AreaParameter p_param) const;
|
||||
|
||||
|
@ -142,8 +155,8 @@ public:
|
|||
_FORCE_INLINE_ void remove_constraint( ConstraintSW* p_constraint) { constraints.erase(p_constraint); }
|
||||
_FORCE_INLINE_ const Set<ConstraintSW*>& get_constraints() const { return constraints; }
|
||||
|
||||
|
||||
|
||||
void set_monitorable(bool p_monitorable);
|
||||
_FORCE_INLINE_ bool is_monitorable() const { return monitorable; }
|
||||
|
||||
void set_transform(const Transform& p_transform);
|
||||
|
||||
|
@ -172,6 +185,26 @@ void AreaSW::remove_body_from_query(BodySW *p_body, uint32_t p_body_shape,uint32
|
|||
}
|
||||
|
||||
|
||||
void AreaSW::add_area_to_query(AreaSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape) {
|
||||
|
||||
|
||||
BodyKey bk(p_area,p_area_shape,p_self_shape);
|
||||
monitored_areas[bk].inc();
|
||||
if (!monitor_query_list.in_list())
|
||||
_queue_monitor_update();
|
||||
|
||||
|
||||
}
|
||||
void AreaSW::remove_area_from_query(AreaSW *p_area, uint32_t p_area_shape,uint32_t p_self_shape) {
|
||||
|
||||
|
||||
BodyKey bk(p_area,p_area_shape,p_self_shape);
|
||||
monitored_areas[bk].dec();
|
||||
if (!monitor_query_list.in_list())
|
||||
_queue_monitor_update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -394,6 +394,14 @@ Transform PhysicsServerSW::area_get_transform(RID p_area) const {
|
|||
return area->get_transform();
|
||||
};
|
||||
|
||||
void PhysicsServerSW::area_set_monitorable(RID p_area,bool p_monitorable) {
|
||||
|
||||
AreaSW *area = area_owner.get(p_area);
|
||||
ERR_FAIL_COND(!area);
|
||||
|
||||
area->set_monitorable(p_monitorable);
|
||||
}
|
||||
|
||||
void PhysicsServerSW::area_set_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method) {
|
||||
|
||||
AreaSW *area = area_owner.get(p_area);
|
||||
|
@ -423,6 +431,14 @@ bool PhysicsServerSW::area_is_ray_pickable(RID p_area) const{
|
|||
}
|
||||
|
||||
|
||||
void PhysicsServerSW::area_set_area_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method) {
|
||||
|
||||
|
||||
AreaSW *area = area_owner.get(p_area);
|
||||
ERR_FAIL_COND(!area);
|
||||
|
||||
area->set_area_monitor_callback(p_receiver?p_receiver->get_instance_ID():0,p_method);
|
||||
}
|
||||
|
||||
/* BODY API */
|
||||
|
||||
|
|
|
@ -128,7 +128,10 @@ public:
|
|||
virtual void area_set_ray_pickable(RID p_area,bool p_enable);
|
||||
virtual bool area_is_ray_pickable(RID p_area) const;
|
||||
|
||||
virtual void area_set_monitorable(RID p_area,bool p_monitorable);
|
||||
|
||||
virtual void area_set_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method);
|
||||
virtual void area_set_area_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method);
|
||||
|
||||
|
||||
/* BODY API */
|
||||
|
|
|
@ -503,15 +503,18 @@ void* SpaceSW::_broadphase_pair(CollisionObjectSW *A,int p_subindex_A,CollisionO
|
|||
|
||||
if (type_A==CollisionObjectSW::TYPE_AREA) {
|
||||
|
||||
|
||||
ERR_FAIL_COND_V(type_B!=CollisionObjectSW::TYPE_BODY,NULL);
|
||||
AreaSW *area=static_cast<AreaSW*>(A);
|
||||
if (type_B==CollisionObjectSW::TYPE_AREA) {
|
||||
|
||||
AreaSW *area_b=static_cast<AreaSW*>(B);
|
||||
Area2PairSW *area2_pair = memnew(Area2PairSW(area_b,p_subindex_B,area,p_subindex_A) );
|
||||
return area2_pair;
|
||||
} else {
|
||||
|
||||
BodySW *body=static_cast<BodySW*>(B);
|
||||
|
||||
|
||||
AreaPairSW *area_pair = memnew(AreaPairSW(body,p_subindex_B,area,p_subindex_A) );
|
||||
|
||||
return area_pair;
|
||||
}
|
||||
} else {
|
||||
|
||||
|
||||
|
|
|
@ -339,7 +339,10 @@ public:
|
|||
virtual Variant area_get_param(RID p_parea,AreaParameter p_param) const=0;
|
||||
virtual Transform area_get_transform(RID p_area) const=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_area_monitor_callback(RID p_area,Object *p_receiver,const StringName& p_method)=0;
|
||||
|
||||
virtual void area_set_ray_pickable(RID p_area,bool p_enable)=0;
|
||||
virtual bool area_is_ray_pickable(RID p_area) const=0;
|
||||
|
|
Loading…
Reference in a new issue