diff options
Diffstat (limited to 'scene')
-rw-r--r-- | scene/2d/physics_body_2d.cpp | 274 | ||||
-rw-r--r-- | scene/2d/physics_body_2d.h | 7 | ||||
-rw-r--r-- | scene/main/node.cpp | 113 | ||||
-rw-r--r-- | scene/main/node.h | 3 | ||||
-rw-r--r-- | scene/register_scene_types.cpp | 3 |
5 files changed, 210 insertions, 190 deletions
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 166ee4daa8..afdca4a3be 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -744,192 +744,149 @@ bool KinematicBody2D::_ignores_mode(Physics2DServer::BodyMode p_mode) const { return true; } -bool KinematicBody2D::is_trapped() const { - - ERR_FAIL_COND_V(!is_inside_scene(),false); - - Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(get_world_2d()->get_space()); - ERR_FAIL_COND_V(!dss,false); - - const int max_shapes=32; - Physics2DDirectSpaceState::ShapeResult sr[max_shapes]; - - Set<RID> exclude; - exclude.insert(get_rid()); - - - for(int i=0;i<get_shape_count();i++) { - - - int res = dss->intersect_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),Vector2(),sr,max_shapes,exclude); - - for(int j=0;j<res;j++) { - - Physics2DServer::BodyMode bm = Physics2DServer::get_singleton()->body_get_mode(sr[j].rid); - if (!_ignores_mode(bm)) { - return true; //it's indeed trapped - } - - } - - } - - return false; +Vector2 KinematicBody2D::move(const Vector2& p_motion) { -} -void KinematicBody2D::untrap() { + //give me back regular physics engine logic + //this is madness + //and most people using this function will think + //what it does is simpler than using physics + //this took about a week to get right.. + //but is it right? who knows at this point.. - //this is reaaaaaaaaally wild, will probably only work for simple cases - ERR_FAIL_COND(!is_inside_scene()); + colliding=false; + ERR_FAIL_COND_V(!is_inside_scene(),Vector2()); Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(get_world_2d()->get_space()); - ERR_FAIL_COND(!dss); - + ERR_FAIL_COND_V(!dss,Vector2()); const int max_shapes=32; - Physics2DDirectSpaceState::ShapeResult sr[max_shapes]; - const int max_contacts=8; - Vector2 pairs[max_contacts*2]; + Vector2 sr[max_shapes*2]; + int res_shapes; Set<RID> exclude; exclude.insert(get_rid()); - Vector2 untrap_vec; - - for(int i=0;i<get_shape_count();i++) { - Matrix32 shape_xform = get_global_transform() * get_shape_transform(i); - int res = dss->intersect_shape(get_shape(i)->get_rid(), shape_xform,Vector2(),sr,max_shapes,exclude); + //recover first + int recover_attempts=4; - for(int j=0;j<res;j++) { + bool collided=false; + uint32_t mask=0; + if (collide_static) + mask|=Physics2DDirectSpaceState::TYPE_MASK_STATIC_BODY; + if (collide_kinematic) + mask|=Physics2DDirectSpaceState::TYPE_MASK_KINEMATIC_BODY; + if (collide_rigid) + mask|=Physics2DDirectSpaceState::TYPE_MASK_RIGID_BODY; + if (collide_character) + mask|=Physics2DDirectSpaceState::TYPE_MASK_CHARACTER_BODY; - Physics2DServer::BodyMode bm = Physics2DServer::get_singleton()->body_get_mode(sr[j].rid); - if (_ignores_mode(bm)) { - exclude.insert(sr[j].rid); - } else { +// print_line("motion: "+p_motion+" margin: "+rtos(margin)); - int rc; - bool c = Physics2DServer::get_singleton()->body_collide_shape(sr[j].rid,sr[j].shape,get_shape(i)->get_rid(),shape_xform,Vector2(),pairs,max_contacts,rc); + //print_line("margin: "+rtos(margin)); + do { - if (c) { - - for(int k=0;k<rc;k++) { + //fill exclude list.. + for(int i=0;i<get_shape_count();i++) { - untrap_vec+=pairs[k*2+0]-pairs[k*2+1]; - } - } - } + if (dss->collide_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),Vector2(),margin,sr,max_shapes,res_shapes,exclude,0,mask)) + collided=true; } - } - - untrap_vec += untrap_vec.normalized()*margin; + if (!collided) + break; + Vector2 recover_motion; - Matrix32 gt = get_global_transform(); - gt.elements[2]+=untrap_vec; - set_global_transform(gt); + for(int i=0;i<res_shapes;i++) { -} + Vector2 a = sr[i*2+0]; + Vector2 b = sr[i*2+1]; -Vector2 KinematicBody2D::move(const Vector2& p_motion) { + float d = a.distance_to(b); - colliding=false; - ERR_FAIL_COND_V(!is_inside_scene(),Vector2()); - Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(get_world_2d()->get_space()); - ERR_FAIL_COND_V(!dss,Vector2()); - const int max_shapes=32; - Physics2DDirectSpaceState::ShapeResult sr[max_shapes]; + //if (d<margin) + /// continue; + recover_motion+=(b-a)*0.2; + } - float best_travel = 1e20; - Physics2DDirectSpaceState::MotionCastCollision mcc_final; - Set<RID> exclude; - exclude.insert(get_rid()); + if (recover_motion==Vector2()) { + collided=false; + break; + } - print_line("pos: "+get_global_pos()); - print_line("mlen: "+p_motion); + Matrix32 gt = get_global_transform(); + gt.elements[2]+=recover_motion; + set_global_transform(gt); - if (!collide_static || ! collide_rigid || !collide_character || !collide_kinematic) { - //fill exclude list.. - for(int i=0;i<get_shape_count();i++) { + recover_attempts--; + } while (recover_attempts); - int res = dss->intersect_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),p_motion,sr,max_shapes,exclude); - for(int j=0;j<res;j++) { - - Physics2DServer::BodyMode bm = Physics2DServer::get_singleton()->body_get_mode(sr[j].rid); - if (_ignores_mode(bm)) { - exclude.insert(sr[j].rid); - } else { - // print_line("DANGER???"); - } - } - } - } + //move second + float safe = 1.0; + float unsafe = 1.0; + int best_shape=-1; for(int i=0;i<get_shape_count();i++) { - Physics2DDirectSpaceState::MotionCastCollision mcc; - bool res = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, mcc,exclude,0); - if (res==false) + float lsafe,lunsafe; + bool valid = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, 0,lsafe,lunsafe,exclude,0,mask); + //print_line("shape: "+itos(i)+" travel:"+rtos(ltravel)); + if (!valid) { + safe=0; + unsafe=0; + best_shape=i; //sadly it's the best + break; + } + if (lsafe==1.0) { continue; - if (mcc.travel<=0) { - //uh it's trapped - colliding=false; - return p_motion; } - if (mcc.travel < best_travel) { + if (lsafe < safe) { - mcc_final=mcc; - best_travel=mcc.travel; + safe=lsafe; + unsafe=lunsafe; + best_shape=i; } } - float motion; - Vector2 motion_ret; - Vector2 push; - if (best_travel>1) { + + //print_line("best shape: "+itos(best_shape)+" motion "+p_motion); + + if (safe>=1) { //not collided colliding=false; - motion=p_motion.length(); //no stopped } else { - colliding=true; - collision=mcc_final.point; - normal=mcc_final.normal; - collider=mcc_final.collider_id; - Vector2 mnormal=p_motion.normalized(); - - float sine = Math::abs(mnormal.dot(normal)); - float retreat=0; - motion = p_motion.length()*mcc_final.travel; - - if (sine==0) { - //something odd going on, do not allow motion? - - retreat=motion; - + //it collided, let's get the rest info in unsafe advance + Matrix32 ugt = get_global_transform(); + ugt.elements[2]+=p_motion*unsafe; + Physics2DDirectSpaceState::ShapeRestInfo rest_info; + bool c2 = dss->rest_info(get_shape(best_shape)->get_rid(), ugt*get_shape_transform(best_shape), Vector2(), margin,&rest_info,exclude,0,mask); + if (!c2) { + //should not happen, but floating point precision is so weird.. + colliding=false; } else { - retreat = margin/sine; - if (retreat>motion) - retreat=motion; + //print_line("Travel: "+rtos(travel)); + colliding=true; + collision=rest_info.point; + normal=rest_info.normal; + collider=rest_info.collider_id; + collider_vel=rest_info.linear_velocity; } - motion_ret=p_motion.normalized() * ( p_motion.length() - motion); - motion-=retreat; - - } + Vector2 motion=p_motion*safe; Matrix32 gt = get_global_transform(); - gt.elements[2]+=p_motion.normalized()*motion; + gt.elements[2]+=motion; set_global_transform(gt); - return motion_ret; + return p_motion-motion; } @@ -938,18 +895,31 @@ Vector2 KinematicBody2D::move_to(const Vector2& p_position) { return move(p_position-get_global_pos()); } -bool KinematicBody2D::can_move_to(const Vector2& p_position) { +bool KinematicBody2D::can_move_to(const Vector2& p_position, bool p_discrete) { ERR_FAIL_COND_V(!is_inside_scene(),false); Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(get_world_2d()->get_space()); ERR_FAIL_COND_V(!dss,false); - const int max_shapes=32; - Physics2DDirectSpaceState::ShapeResult sr[max_shapes]; + uint32_t mask=0; + if (collide_static) + mask|=Physics2DDirectSpaceState::TYPE_MASK_STATIC_BODY; + if (collide_kinematic) + mask|=Physics2DDirectSpaceState::TYPE_MASK_KINEMATIC_BODY; + if (collide_rigid) + mask|=Physics2DDirectSpaceState::TYPE_MASK_RIGID_BODY; + if (collide_character) + mask|=Physics2DDirectSpaceState::TYPE_MASK_CHARACTER_BODY; Vector2 motion = p_position-get_global_pos(); + Matrix32 xform=get_global_transform(); + + if (p_discrete) { + + xform.elements[2]+=motion; + motion=Vector2(); + } - Physics2DDirectSpaceState::MotionCastCollision mcc_final; Set<RID> exclude; exclude.insert(get_rid()); @@ -957,19 +927,9 @@ bool KinematicBody2D::can_move_to(const Vector2& p_position) { for(int i=0;i<get_shape_count();i++) { - int res = dss->intersect_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),motion,sr,max_shapes,exclude); - - for(int j=0;j<res;j++) { - - Physics2DServer::BodyMode bm = Physics2DServer::get_singleton()->body_get_mode(sr[j].rid); - if (_ignores_mode(bm)) { - exclude.insert(sr[j].rid); - continue; - } - - return false; //omg collided - - } + bool col = dss->intersect_shape(get_shape(i)->get_rid(), xform * get_shape_transform(i),motion,0,NULL,0,exclude,0,mask); + if (col) + return false; } return true; @@ -993,6 +953,12 @@ Vector2 KinematicBody2D::get_collision_normal() const { return normal; } + +Vector2 KinematicBody2D::get_collider_velocity() const { + + return collider_vel; +} + ObjectID KinematicBody2D::get_collider() const { ERR_FAIL_COND_V(!colliding,0); @@ -1051,9 +1017,6 @@ float KinematicBody2D::get_collision_margin() const{ void KinematicBody2D::_bind_methods() { - ObjectTypeDB::bind_method(_MD("is_trapped"),&KinematicBody2D::is_trapped); - ObjectTypeDB::bind_method(_MD("untrap"),&KinematicBody2D::untrap); - ObjectTypeDB::bind_method(_MD("move","rel_vec"),&KinematicBody2D::move); ObjectTypeDB::bind_method(_MD("move_to","position"),&KinematicBody2D::move_to); @@ -1063,6 +1026,7 @@ void KinematicBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_collision_pos"),&KinematicBody2D::get_collision_pos); ObjectTypeDB::bind_method(_MD("get_collision_normal"),&KinematicBody2D::get_collision_normal); + ObjectTypeDB::bind_method(_MD("get_collider_velocity"),&KinematicBody2D::get_collider_velocity); ObjectTypeDB::bind_method(_MD("get_collider:Object"),&KinematicBody2D::get_collider); @@ -1085,7 +1049,7 @@ void KinematicBody2D::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/kinematic"),_SCS("set_collide_with_kinematic_bodies"),_SCS("can_collide_with_kinematic_bodies")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/rigid"),_SCS("set_collide_with_rigid_bodies"),_SCS("can_collide_with_rigid_bodies")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/character"),_SCS("set_collide_with_character_bodies"),_SCS("can_collide_with_character_bodies")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/margin",PROPERTY_HINT_RANGE,"0.01,256,0.01"),_SCS("set_collision_margin"),_SCS("get_collision_margin")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/margin",PROPERTY_HINT_RANGE,"0.001,256,0.001"),_SCS("set_collision_margin"),_SCS("get_collision_margin")); } @@ -1100,7 +1064,7 @@ KinematicBody2D::KinematicBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_KI colliding=false; collider=0; - margin=1; + margin=0.01; } KinematicBody2D::~KinematicBody2D() { diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 6596c0ce04..e7b65b1ef3 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -243,6 +243,7 @@ class KinematicBody2D : public PhysicsBody2D { bool colliding; Vector2 collision; Vector2 normal; + Vector2 collider_vel; ObjectID collider; @@ -254,16 +255,14 @@ protected: static void _bind_methods(); public: - bool is_trapped() const; - void untrap(); - Vector2 move(const Vector2& p_motion); Vector2 move_to(const Vector2& p_position); - bool can_move_to(const Vector2& p_position); + bool can_move_to(const Vector2& p_position,bool p_discrete=false); bool is_colliding() const; Vector2 get_collision_pos() const; Vector2 get_collision_normal() const; + Vector2 get_collider_velocity() const; ObjectID get_collider() const; void set_collide_with_static_bodies(bool p_enable); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 1f54040de4..5ac09e837f 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -462,7 +462,7 @@ void Node::_set_name_nocheck(const StringName& p_name) { void Node::set_name(const String& p_name) { - String name=p_name.replace(":","").replace("/",""); + String name=p_name.replace(":","").replace("/","").replace("@",""); ERR_FAIL_COND(name==""); data.name=name; @@ -479,45 +479,97 @@ void Node::set_name(const String& p_name) { } } +static bool node_hrcr=false; +static SafeRefCount node_hrcr_count; + +void Node::init_node_hrcr() { + node_hrcr_count.init(1); +} + +void Node::set_human_readable_collision_renaming(bool p_enabled) { + + node_hrcr=p_enabled; +} + + void Node::_validate_child_name(Node *p_child) { /* Make sure the name is unique */ - String basename = p_child->data.name; - if (basename=="") { - - basename = p_child->get_type(); - } - - int val=1; - - for(;;) { - - String attempted = val > 1 ? (basename + " " +itos(val) ) : basename; + if (node_hrcr) { - bool found=false; - - for (int i=0;i<data.children.size();i++) { - - if (data.children[i]==p_child) + //this approach to autoset node names is human readable but very slow + //it's turned on while running in the editor + + String basename = p_child->data.name; + + if (basename=="") { + + basename = p_child->get_type(); + } + + int val=1; + + for(;;) { + + String attempted = val > 1 ? (basename + " " +itos(val) ) : basename; + + bool found=false; + + for (int i=0;i<data.children.size();i++) { + + if (data.children[i]==p_child) + continue; + if (data.children[i]->get_name() == attempted) { + found=true; + break; + } + + } + + if (found) { + + val++; continue; - if (data.children[i]->get_name() == attempted) { - found=true; - break; } - + + p_child->data.name=attempted; + break; } - - if (found) { - - val++; - continue; + } else { + + //this approach to autoset node names is fast but not as readable + //it's the default and reserves the '@' character for unique names. + + bool unique=true; + + if (p_child->data.name==StringName() || p_child->data.name.operator String()[0]=='@') { + //new unique name must be assigned + unique=false; + } else { + //check if exists + Node **childs=data.children.ptr(); + int cc = data.children.size(); + + for(int i=0;i<cc;i++) { + if (childs[i]->data.name==p_child->data.name) { + unique=false; + break; + } + } + } + + if (!unique) { + + node_hrcr_count.ref(); +#ifdef DEBUG_ENABLED + String name = "@"+String(p_child->get_type_name())+itos(node_hrcr_count.get()); +#else + String name = "@"+itos(node_hrcr_count.get()); +#endif + p_child->data.name=name; } - - p_child->data.name=attempted; - break; } - } void Node::_add_child_nocheck(Node* p_child,const StringName& p_name) { @@ -541,6 +593,7 @@ void Node::_add_child_nocheck(Node* p_child,const StringName& p_name) { } + void Node::add_child(Node *p_child) { ERR_FAIL_NULL(p_child); diff --git a/scene/main/node.h b/scene/main/node.h index f38a782181..ec03fb19e8 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -261,6 +261,9 @@ public: void queue_delete(); + static void set_human_readable_collision_renaming(bool p_enabled); + static void init_node_hrcr(); + /* CANVAS */ Node(); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index ae67023d5b..007ecb88b7 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -223,6 +223,7 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init + Node::init_node_hrcr(); #ifdef OLD_SCENE_FORMAT_ENABLED ObjectTypeDB::register_type<SceneIO>(); @@ -452,7 +453,7 @@ void register_scene_types() { ObjectTypeDB::register_virtual_type<PhysicsBody2D>(); ObjectTypeDB::register_type<StaticBody2D>(); ObjectTypeDB::register_type<RigidBody2D>(); - //ObjectTypeDB::register_type<KinematicBody2D>(); + ObjectTypeDB::register_type<KinematicBody2D>(); ObjectTypeDB::register_type<Area2D>(); ObjectTypeDB::register_type<CollisionShape2D>(); ObjectTypeDB::register_type<CollisionPolygon2D>(); |