diff options
Diffstat (limited to 'scene')
31 files changed, 637 insertions, 93 deletions
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index a40b1fb39..827256c2f 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -512,6 +512,29 @@ bool Area2D::overlaps_body(Node* p_body) const{ } +void Area2D::set_collision_mask(uint32_t p_mask) { + + collision_mask=p_mask; + Physics2DServer::get_singleton()->area_set_collision_mask(get_rid(),p_mask); +} + +uint32_t Area2D::get_collision_mask() const { + + return collision_mask; +} + + +void Area2D::set_layer_mask(uint32_t p_mask) { + + layer_mask=p_mask; + Physics2DServer::get_singleton()->area_set_layer_mask(get_rid(),p_mask); +} + +uint32_t Area2D::get_layer_mask() const { + + return layer_mask; +} + void Area2D::_bind_methods() { @@ -542,6 +565,12 @@ void Area2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_priority","priority"),&Area2D::set_priority); ObjectTypeDB::bind_method(_MD("get_priority"),&Area2D::get_priority); + ObjectTypeDB::bind_method(_MD("set_collision_mask","collision_mask"),&Area2D::set_collision_mask); + ObjectTypeDB::bind_method(_MD("get_collision_mask"),&Area2D::get_collision_mask); + + ObjectTypeDB::bind_method(_MD("set_layer_mask","layer_mask"),&Area2D::set_layer_mask); + ObjectTypeDB::bind_method(_MD("get_layer_mask"),&Area2D::get_layer_mask); + ObjectTypeDB::bind_method(_MD("set_enable_monitoring","enable"),&Area2D::set_enable_monitoring); ObjectTypeDB::bind_method(_MD("is_monitoring_enabled"),&Area2D::is_monitoring_enabled); @@ -578,6 +607,8 @@ void Area2D::_bind_methods() { ADD_PROPERTYNZ( 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")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_layer_mask"),_SCS("get_layer_mask")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_mask"),_SCS("get_collision_mask")); } @@ -593,9 +624,10 @@ Area2D::Area2D() : CollisionObject2D(Physics2DServer::get_singleton()->area_crea priority=0; monitoring=false; monitorable=false; + collision_mask=1; + layer_mask=1; set_enable_monitoring(true); set_monitorable(true); - } Area2D::~Area2D() { diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index 5964230a5..0c064f54c 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -51,6 +51,8 @@ private: bool gravity_is_point; real_t linear_damp; real_t angular_damp; + uint32_t collision_mask; + uint32_t layer_mask; int priority; bool monitoring; bool monitorable; @@ -151,6 +153,12 @@ public: void set_monitorable(bool p_enable); bool is_monitorable() const; + void set_collision_mask(uint32_t p_mask); + uint32_t get_collision_mask() const; + + void set_layer_mask(uint32_t p_mask); + uint32_t get_layer_mask() const; + Array get_overlapping_bodies() const; //function for script Array get_overlapping_areas() const; //function for script diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 27a512845..70b88a661 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -132,8 +132,7 @@ Matrix32 Camera2D::get_camera_transform() { } - Point2 screen_offset = (centered ? (screen_size * 0.5 * zoom) : Point2());; - screen_offset; + Point2 screen_offset = (centered ? (screen_size * 0.5 * zoom) : Point2()); float angle = get_global_transform().get_rotation(); if(rotating){ diff --git a/scene/2d/navigation2d.cpp b/scene/2d/navigation2d.cpp index d427bf4bc..5a0250181 100644 --- a/scene/2d/navigation2d.cpp +++ b/scene/2d/navigation2d.cpp @@ -32,6 +32,7 @@ void Navigation2D::_navpoly_link(int p_id) { p.edges.resize(plen); Vector2 center; + float sum=0; for(int j=0;j<plen;j++) { @@ -46,8 +47,23 @@ void Navigation2D::_navpoly_link(int p_id) { center+=ep; e.point=_get_point(ep); p.edges[j]=e; + + + int idxn = indices[(j+1)%plen]; + if (idxn<0 || idxn>=len) { + valid=false; + break; + } + + Vector2 epn = nm.xform.xform(r[idxn]); + + sum+=(epn.x-ep.x)*(epn.y+ep.y); + + } + p.clockwise=sum>0; + if (!valid) { nm.polygons.pop_back(); ERR_CONTINUE(!valid); @@ -493,17 +509,30 @@ Vector<Vector2> Navigation2D::get_simple_path(const Vector2& p_start, const Vect left = _get_vertex(p->edges[prev].point); right = _get_vertex(p->edges[prev_n].point); - if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5) < 0){ + if (p->clockwise) { SWAP(left,right); } + /*if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5) < 0){ + SWAP(left,right); + }*/ } bool skip=false; + /* print_line("-----\nAPEX: "+(apex_point-end_point)); + print_line("LEFT:"); + print_line("\tPortal: "+(portal_left-end_point)); + print_line("\tPoint: "+(left-end_point)); + print_line("\tFree: "+itos(CLOCK_TANGENT(apex_point,portal_left,left) >= 0)); + print_line("RIGHT:"); + print_line("\tPortal: "+(portal_right-end_point)); + print_line("\tPoint: "+(right-end_point)); + print_line("\tFree: "+itos(CLOCK_TANGENT(apex_point,portal_right,right) <= 0)); +*/ if (CLOCK_TANGENT(apex_point,portal_left,left) >= 0){ //process - if (portal_left==apex_point || CLOCK_TANGENT(apex_point,left,portal_right) > 0) { + if (portal_left.distance_squared_to(apex_point)<CMP_EPSILON || CLOCK_TANGENT(apex_point,left,portal_right) > 0) { left_poly=p; portal_left=left; } else { @@ -519,12 +548,13 @@ Vector<Vector2> Navigation2D::get_simple_path(const Vector2& p_start, const Vect if (path[path.size()-1].distance_to(apex_point)>CMP_EPSILON) path.push_back(apex_point); skip=true; + //print_line("addpoint left"); } } if (!skip && CLOCK_TANGENT(apex_point,portal_right,right) <= 0){ //process - if (portal_right==apex_point || CLOCK_TANGENT(apex_point,right,portal_left) < 0) { + if (portal_right.distance_squared_to(apex_point)<CMP_EPSILON || CLOCK_TANGENT(apex_point,right,portal_left) < 0) { right_poly=p; portal_right=right; } else { @@ -539,6 +569,8 @@ Vector<Vector2> Navigation2D::get_simple_path(const Vector2& p_start, const Vect portal_left=apex_point; if (path[path.size()-1].distance_to(apex_point)>CMP_EPSILON) path.push_back(apex_point); + //print_line("addpoint right"); + } } diff --git a/scene/2d/navigation2d.h b/scene/2d/navigation2d.h index 7a33105b7..829b0f544 100644 --- a/scene/2d/navigation2d.h +++ b/scene/2d/navigation2d.h @@ -60,6 +60,8 @@ class Navigation2D : public Node2D { float distance; int prev_edge; + bool clockwise; + NavMesh *owner; }; diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index e7bc19960..3d2917d84 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -68,17 +68,34 @@ float PhysicsBody2D::get_one_way_collision_max_depth() const{ } +void PhysicsBody2D::_set_layers(uint32_t p_mask) { + + set_layer_mask(p_mask); + set_collision_mask(p_mask); +} + +uint32_t PhysicsBody2D::_get_layers() const{ + + return get_layer_mask(); +} + void PhysicsBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_layer_mask","mask"),&PhysicsBody2D::set_layer_mask); ObjectTypeDB::bind_method(_MD("get_layer_mask"),&PhysicsBody2D::get_layer_mask); + ObjectTypeDB::bind_method(_MD("set_collision_mask","mask"),&PhysicsBody2D::set_collision_mask); + ObjectTypeDB::bind_method(_MD("get_collision_mask"),&PhysicsBody2D::get_collision_mask); + ObjectTypeDB::bind_method(_MD("_set_layers","mask"),&PhysicsBody2D::_set_layers); + ObjectTypeDB::bind_method(_MD("_get_layers"),&PhysicsBody2D::_get_layers); ObjectTypeDB::bind_method(_MD("set_one_way_collision_direction","dir"),&PhysicsBody2D::set_one_way_collision_direction); ObjectTypeDB::bind_method(_MD("get_one_way_collision_direction"),&PhysicsBody2D::get_one_way_collision_direction); ObjectTypeDB::bind_method(_MD("set_one_way_collision_max_depth","depth"),&PhysicsBody2D::set_one_way_collision_max_depth); ObjectTypeDB::bind_method(_MD("get_one_way_collision_max_depth"),&PhysicsBody2D::get_one_way_collision_max_depth); ObjectTypeDB::bind_method(_MD("add_collision_exception_with","body:PhysicsBody2D"),&PhysicsBody2D::add_collision_exception_with); ObjectTypeDB::bind_method(_MD("remove_collision_exception_with","body:PhysicsBody2D"),&PhysicsBody2D::remove_collision_exception_with); - ADD_PROPERTY(PropertyInfo(Variant::INT,"layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_layer_mask"),_SCS("get_layer_mask")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"layers",PROPERTY_HINT_ALL_FLAGS,"",0),_SCS("_set_layers"),_SCS("_get_layers")); //for backwards compat + ADD_PROPERTY(PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_layer_mask"),_SCS("get_layer_mask")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"collision/mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_mask"),_SCS("get_collision_mask")); ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"one_way_collision/direction"),_SCS("set_one_way_collision_direction"),_SCS("get_one_way_collision_direction")); ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"one_way_collision/max_depth"),_SCS("set_one_way_collision_max_depth"),_SCS("get_one_way_collision_max_depth")); } @@ -94,9 +111,22 @@ uint32_t PhysicsBody2D::get_layer_mask() const { return mask; } +void PhysicsBody2D::set_collision_mask(uint32_t p_mask) { + + collision_mask=p_mask; + Physics2DServer::get_singleton()->body_set_collision_mask(get_rid(),p_mask); +} + +uint32_t PhysicsBody2D::get_collision_mask() const { + + return collision_mask; +} + + PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode) : CollisionObject2D( Physics2DServer::get_singleton()->body_create(p_mode), false) { mask=1; + collision_mask=1; set_one_way_collision_max_depth(0); set_pickable(false); @@ -909,6 +939,19 @@ Variant KinematicBody2D::_get_collider() const { return obj; } +void KinematicBody2D::revert_motion() { + + Matrix32 gt = get_global_transform(); + gt.elements[2]-=travel; + travel=Vector2(); + set_global_transform(gt); + +} + +Vector2 KinematicBody2D::get_travel() const { + + return travel; +} Vector2 KinematicBody2D::move(const Vector2& p_motion) { @@ -926,6 +969,7 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { Matrix32 gt = get_global_transform(); gt.elements[2]+=result.motion; set_global_transform(gt); + travel=result.motion; return result.remainder; #else @@ -1157,6 +1201,8 @@ void KinematicBody2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("move_to","position"),&KinematicBody2D::move_to); ObjectTypeDB::bind_method(_MD("test_move","rel_vec"),&KinematicBody2D::test_move); + ObjectTypeDB::bind_method(_MD("get_travel"),&KinematicBody2D::get_travel); + ObjectTypeDB::bind_method(_MD("revert_motion"),&KinematicBody2D::revert_motion); ObjectTypeDB::bind_method(_MD("is_colliding"),&KinematicBody2D::is_colliding); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index b8cba6e5b..03f95959b 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -39,8 +39,14 @@ class PhysicsBody2D : public CollisionObject2D { OBJ_TYPE(PhysicsBody2D,CollisionObject2D); uint32_t mask; + uint32_t collision_mask; Vector2 one_way_collision_direction; float one_way_collision_max_depth; + + + void _set_layers(uint32_t p_mask); + uint32_t _get_layers() const; + protected: void _notification(int p_what); @@ -52,6 +58,9 @@ public: void set_layer_mask(uint32_t p_mask); uint32_t get_layer_mask() const; + void set_collision_mask(uint32_t p_mask); + uint32_t get_collision_mask() const; + void add_collision_exception_with(Node* p_node); //must be physicsbody void remove_collision_exception_with(Node* p_node); @@ -276,6 +285,7 @@ class KinematicBody2D : public PhysicsBody2D { ObjectID collider; int collider_shape; Variant collider_metadata; + Vector2 travel; Variant _get_collider() const; @@ -290,6 +300,10 @@ public: bool test_move(const Vector2& p_motion); bool is_colliding() const; + + Vector2 get_travel() const; + void revert_motion(); + Vector2 get_collision_pos() const; Vector2 get_collision_normal() const; Vector2 get_collider_velocity() const; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index bf1677ae6..2fca1e67e 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -519,6 +519,7 @@ Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const q.body=Physics2DServer::get_singleton()->body_create(use_kinematic?Physics2DServer::BODY_MODE_KINEMATIC:Physics2DServer::BODY_MODE_STATIC); Physics2DServer::get_singleton()->body_attach_object_instance_ID(q.body,get_instance_ID()); Physics2DServer::get_singleton()->body_set_layer_mask(q.body,collision_layer); + Physics2DServer::get_singleton()->body_set_collision_mask(q.body,collision_mask); Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_FRICTION,friction); Physics2DServer::get_singleton()->body_set_param(q.body,Physics2DServer::BODY_PARAM_BOUNCE,bounce); @@ -790,7 +791,7 @@ Rect2 TileMap::get_item_rect() const { return rect_cache; } -void TileMap::set_collision_layer_mask(uint32_t p_layer) { +void TileMap::set_collision_layer(uint32_t p_layer) { collision_layer=p_layer; for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) { @@ -800,6 +801,16 @@ void TileMap::set_collision_layer_mask(uint32_t p_layer) { } } +void TileMap::set_collision_mask(uint32_t p_mask) { + + collision_mask=p_mask; + for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) { + + Quadrant &q=E->get(); + Physics2DServer::get_singleton()->body_set_collision_mask(q.body,collision_mask); + } +} + bool TileMap::get_collision_use_kinematic() const{ return use_kinematic; @@ -844,11 +855,16 @@ float TileMap::get_collision_bounce() const{ } -uint32_t TileMap::get_collision_layer_mask() const { +uint32_t TileMap::get_collision_layer() const { return collision_layer; } +uint32_t TileMap::get_collision_mask() const { + + return collision_mask; +} + void TileMap::set_mode(Mode p_mode) { _clear_quadrants(); @@ -1077,8 +1093,11 @@ void TileMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_collision_use_kinematic","use_kinematic"),&TileMap::set_collision_use_kinematic); ObjectTypeDB::bind_method(_MD("get_collision_use_kinematic"),&TileMap::get_collision_use_kinematic); - ObjectTypeDB::bind_method(_MD("set_collision_layer_mask","mask"),&TileMap::set_collision_layer_mask); - ObjectTypeDB::bind_method(_MD("get_collision_layer_mask"),&TileMap::get_collision_layer_mask); + ObjectTypeDB::bind_method(_MD("set_collision_layer","mask"),&TileMap::set_collision_layer); + ObjectTypeDB::bind_method(_MD("get_collision_layer"),&TileMap::get_collision_layer); + + ObjectTypeDB::bind_method(_MD("set_collision_mask","mask"),&TileMap::set_collision_mask); + ObjectTypeDB::bind_method(_MD("get_collision_mask"),&TileMap::get_collision_mask); ObjectTypeDB::bind_method(_MD("set_collision_friction","value"),&TileMap::set_collision_friction); ObjectTypeDB::bind_method(_MD("get_collision_friction"),&TileMap::get_collision_friction); @@ -1117,7 +1136,9 @@ void TileMap::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collision/use_kinematic",PROPERTY_HINT_NONE,""),_SCS("set_collision_use_kinematic"),_SCS("get_collision_use_kinematic")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_friction"),_SCS("get_collision_friction")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_bounce"),_SCS("get_collision_bounce")); - ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_layer_mask"),_SCS("get_collision_layer_mask")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_layer"),_SCS("get_collision_layer")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_mask"),_SCS("get_collision_mask")); + ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_tile_data"),_SCS("_get_tile_data")); ADD_SIGNAL(MethodInfo("settings_changed")); @@ -1146,6 +1167,7 @@ TileMap::TileMap() { center_x=false; center_y=false; collision_layer=1; + collision_mask=1; friction=1; bounce=0; mode=MODE_SQUARE; diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 233529f01..84ca65da4 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -146,6 +146,8 @@ private: float friction; float bounce; uint32_t collision_layer; + uint32_t collision_mask; + TileOrigin tile_origin; void _fix_cell_transform(Matrix32& xform, const Cell& p_cell, const Vector2 &p_offset, const Size2 &p_sc); @@ -207,8 +209,11 @@ public: Rect2 get_item_rect() const; - void set_collision_layer_mask(uint32_t p_layer); - uint32_t get_collision_layer_mask() const; + void set_collision_layer(uint32_t p_layer); + uint32_t get_collision_layer() const; + + void set_collision_mask(uint32_t p_mask); + uint32_t get_collision_mask() const; void set_collision_use_kinematic(bool p_use_kinematic); bool get_collision_use_kinematic() const; diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp index 8866a6580..48820706d 100644 --- a/scene/3d/navigation.cpp +++ b/scene/3d/navigation.cpp @@ -30,6 +30,7 @@ void Navigation::_navmesh_link(int p_id) { p.edges.resize(plen); Vector3 center; + float sum=0; for(int j=0;j<plen;j++) { @@ -44,8 +45,19 @@ void Navigation::_navmesh_link(int p_id) { center+=ep; e.point=_get_point(ep); p.edges[j]=e; + + if (j>=2) { + Vector3 epa = nm.xform.xform(r[indices[j-2]]); + Vector3 epb = nm.xform.xform(r[indices[j-1]]); + + sum+=up.dot((epb-epa).cross(ep-epa)); + + } + } + p.clockwise=sum>0; + if (!valid) { nm.polygons.pop_back(); ERR_CONTINUE(!valid); @@ -399,7 +411,8 @@ Vector<Vector3> Navigation::get_simple_path(const Vector3& p_start, const Vector left = _get_vertex(p->edges[prev].point); right = _get_vertex(p->edges[prev_n].point); - if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5).dot(up) < 0){ + //if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5).dot(up) < 0){ + if (p->clockwise) { SWAP(left,right); } } diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h index 54cec8f1f..0f7f67571 100644 --- a/scene/3d/navigation.h +++ b/scene/3d/navigation.h @@ -59,6 +59,8 @@ class Navigation : public Spatial { float distance; int prev_edge; + bool clockwise; + NavMesh *owner; }; diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 35f6523c6..4952f742d 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -292,7 +292,7 @@ SpriteBase3D::SpriteBase3D() { parent_sprite=NULL; pI=NULL; - for(int i=0;i<4;i++) + for(int i=0;i<FLAG_MAX;i++) flags[i]=i==FLAG_TRANSPARENT; axis=Vector3::AXIS_Z; diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index a7a4129a5..73d93e50e 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -29,6 +29,81 @@ #include "tween.h" #include "method_bind_ext.inc" +void Tween::_add_pending_command(StringName p_key + ,const Variant& p_arg1 ,const Variant& p_arg2 ,const Variant& p_arg3 ,const Variant& p_arg4 ,const Variant& p_arg5 + ,const Variant& p_arg6 ,const Variant& p_arg7 ,const Variant& p_arg8 ,const Variant& p_arg9 ,const Variant& p_arg10 +) { + + pending_commands.push_back(PendingCommand()); + PendingCommand& cmd = pending_commands.back()->get(); + + cmd.key = p_key; + int& count = cmd.args; + if(p_arg10.get_type() != Variant::NIL) + count = 10; + else if(p_arg9.get_type() != Variant::NIL) + count = 9; + else if(p_arg8.get_type() != Variant::NIL) + count = 8; + else if(p_arg7.get_type() != Variant::NIL) + count = 7; + else if(p_arg6.get_type() != Variant::NIL) + count = 6; + else if(p_arg5.get_type() != Variant::NIL) + count = 5; + else if(p_arg4.get_type() != Variant::NIL) + count = 4; + else if(p_arg3.get_type() != Variant::NIL) + count = 3; + else if(p_arg2.get_type() != Variant::NIL) + count = 2; + else if(p_arg1.get_type() != Variant::NIL) + count = 1; + if(count > 0) + cmd.arg[0] = p_arg1; + if(count > 1) + cmd.arg[1] = p_arg2; + if(count > 2) + cmd.arg[2] = p_arg3; + if(count > 3) + cmd.arg[3] = p_arg4; + if(count > 4) + cmd.arg[4] = p_arg5; + if(count > 5) + cmd.arg[5] = p_arg6; + if(count > 6) + cmd.arg[6] = p_arg7; + if(count > 7) + cmd.arg[7] = p_arg8; + if(count > 8) + cmd.arg[8] = p_arg9; + if(count > 9) + cmd.arg[9] = p_arg10; +} + +void Tween::_process_pending_commands() { + + for(List<PendingCommand>::Element *E=pending_commands.front();E;E=E->next()) { + + PendingCommand& cmd = E->get(); + Variant::CallError err; + Variant *arg[10] = { + &cmd.arg[0], + &cmd.arg[1], + &cmd.arg[2], + &cmd.arg[3], + &cmd.arg[4], + &cmd.arg[5], + &cmd.arg[6], + &cmd.arg[7], + &cmd.arg[8], + &cmd.arg[9], + }; + this->call(cmd.key, (const Variant **) arg, cmd.args, err); + } + pending_commands.clear(); +} + bool Tween::_set(const StringName& p_name, const Variant& p_value) { String name=p_name; @@ -456,6 +531,8 @@ bool Tween::_apply_tween_value(InterpolateData& p_data, Variant& value) { void Tween::_tween_process(float p_delta) { + _process_pending_commands(); + if (speed_scale == 0) return; p_delta *= speed_scale; @@ -551,8 +628,12 @@ void Tween::_tween_process(float p_delta) { _apply_tween_value(data, result); - if(data.finish) + if (data.finish) { emit_signal("tween_complete",object,data.key); + // not repeat mode, remove completed action + if (!repeat) + call_deferred("remove", object, data.key); + } } pending_update --; } @@ -734,7 +815,10 @@ bool Tween::resume_all() { bool Tween::remove(Object *p_object, String p_key) { - ERR_FAIL_COND_V(pending_update != 0, false); + if(pending_update != 0) { + call_deferred("remove", p_object, p_key); + return true; + } for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); @@ -751,7 +835,10 @@ bool Tween::remove(Object *p_object, String p_key) { bool Tween::remove_all() { - ERR_FAIL_COND_V(pending_update != 0, false); + if(pending_update != 0) { + call_deferred("remove_all"); + return true; + } set_active(false); _set_process(false); interpolates.clear(); @@ -940,7 +1027,19 @@ bool Tween::interpolate_property(Object *p_object , EaseType p_ease_type , real_t p_delay ) { - ERR_FAIL_COND_V(pending_update != 0, false); + if(pending_update != 0) { + _add_pending_command("interpolate_property" + , p_object + , p_property + , p_initial_val + , p_final_val + , p_times_in_sec + , p_trans_type + , p_ease_type + , p_delay + ); + return true; + } // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); @@ -987,7 +1086,19 @@ bool Tween::interpolate_method(Object *p_object , EaseType p_ease_type , real_t p_delay ) { - ERR_FAIL_COND_V(pending_update != 0, false); + if(pending_update != 0) { + _add_pending_command("interpolate_method" + , p_object + , p_method + , p_initial_val + , p_final_val + , p_times_in_sec + , p_trans_type + , p_ease_type + , p_delay + ); + return true; + } // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); @@ -999,6 +1110,7 @@ bool Tween::interpolate_method(Object *p_object ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false); ERR_FAIL_COND_V(p_delay < 0, false); + ERR_EXPLAIN("Object has no method named: %s" + p_method); ERR_FAIL_COND_V(!p_object->has_method(p_method), false); InterpolateData data; @@ -1029,10 +1141,23 @@ bool Tween::interpolate_callback(Object *p_object , VARIANT_ARG_DECLARE ) { - ERR_FAIL_COND_V(pending_update != 0, false); + if(pending_update != 0) { + _add_pending_command("interpolate_callback" + , p_object + , p_times_in_sec + , p_callback + , p_arg1 + , p_arg2 + , p_arg3 + , p_arg4 + , p_arg5 + ); + return true; + } ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_times_in_sec < 0, false); + ERR_EXPLAIN("Object has no callback named: %s" + p_callback); ERR_FAIL_COND_V(!p_object->has_method(p_callback), false); InterpolateData data; @@ -1080,10 +1205,23 @@ bool Tween::interpolate_deferred_callback(Object *p_object , VARIANT_ARG_DECLARE ) { - ERR_FAIL_COND_V(pending_update != 0, false); + if(pending_update != 0) { + _add_pending_command("interpolate_deferred_callback" + , p_object + , p_times_in_sec + , p_callback + , p_arg1 + , p_arg2 + , p_arg3 + , p_arg4 + , p_arg5 + ); + return true; + } ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_times_in_sec < 0, false); + ERR_EXPLAIN("Object has no callback named: %s" + p_callback); ERR_FAIL_COND_V(!p_object->has_method(p_callback), false); InterpolateData data; @@ -1135,7 +1273,20 @@ bool Tween::follow_property(Object *p_object , EaseType p_ease_type , real_t p_delay ) { - ERR_FAIL_COND_V(pending_update != 0, false); + if(pending_update != 0) { + _add_pending_command("follow_property" + , p_object + , p_property + , p_initial_val + , p_target + , p_target_property + , p_times_in_sec + , p_trans_type + , p_ease_type + , p_delay + ); + return true; + } // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); @@ -1188,7 +1339,20 @@ bool Tween::follow_method(Object *p_object , EaseType p_ease_type , real_t p_delay ) { - ERR_FAIL_COND_V(pending_update != 0, false); + if(pending_update != 0) { + _add_pending_command("follow_method" + , p_object + , p_method + , p_initial_val + , p_target + , p_target_method + , p_times_in_sec + , p_trans_type + , p_ease_type + , p_delay + ); + return true; + } // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); @@ -1199,7 +1363,9 @@ bool Tween::follow_method(Object *p_object ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false); ERR_FAIL_COND_V(p_delay < 0, false); + ERR_EXPLAIN("Object has no method named: %s" + p_method); ERR_FAIL_COND_V(!p_object->has_method(p_method), false); + ERR_EXPLAIN("Target has no method named: %s" + p_target_method); ERR_FAIL_COND_V(!p_target->has_method(p_target_method), false); Variant::CallError error; @@ -1240,7 +1406,20 @@ bool Tween::targeting_property(Object *p_object , EaseType p_ease_type , real_t p_delay ) { - ERR_FAIL_COND_V(pending_update != 0, false); + if(pending_update != 0) { + _add_pending_command("targeting_property" + , p_object + , p_property + , p_initial + , p_initial_property + , p_final_val + , p_times_in_sec + , p_trans_type + , p_ease_type + , p_delay + ); + return true; + } // convert INT to REAL is better for interpolaters if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); @@ -1298,7 +1477,20 @@ bool Tween::targeting_method(Object *p_object , EaseType p_ease_type , real_t p_delay ) { - ERR_FAIL_COND_V(pending_update != 0, false); + if(pending_update != 0) { + _add_pending_command("targeting_method" + , p_object + , p_method + , p_initial + , p_initial_method + , p_final_val + , p_times_in_sec + , p_trans_type + , p_ease_type + , p_delay + ); + return true; + } // convert INT to REAL is better for interpolaters if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); @@ -1309,7 +1501,9 @@ bool Tween::targeting_method(Object *p_object ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false); ERR_FAIL_COND_V(p_delay < 0, false); + ERR_EXPLAIN("Object has no method named: %s" + p_method); ERR_FAIL_COND_V(!p_object->has_method(p_method), false); + ERR_EXPLAIN("Initial Object has no method named: %s" + p_initial_method); ERR_FAIL_COND_V(!p_initial->has_method(p_initial_method), false); Variant::CallError error; diff --git a/scene/animation/tween.h b/scene/animation/tween.h index 76402bcd7..d504c63d8 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -110,6 +110,27 @@ private: List<InterpolateData> interpolates; + struct PendingCommand { + StringName key; + int args; + Variant arg[10]; + }; + List<PendingCommand> pending_commands; + + void _add_pending_command(StringName p_key + ,const Variant& p_arg1=Variant() + ,const Variant& p_arg2=Variant() + ,const Variant& p_arg3=Variant() + ,const Variant& p_arg4=Variant() + ,const Variant& p_arg5=Variant() + ,const Variant& p_arg6=Variant() + ,const Variant& p_arg7=Variant() + ,const Variant& p_arg8=Variant() + ,const Variant& p_arg9=Variant() + ,const Variant& p_arg10=Variant() + ); + void _process_pending_commands(); + typedef real_t (*interpolater)(real_t t, real_t b, real_t c, real_t d); static interpolater interpolaters[TRANS_COUNT][EASE_COUNT]; diff --git a/scene/animation/tween_interpolaters.cpp b/scene/animation/tween_interpolaters.cpp index c052d752f..9128d220d 100644 --- a/scene/animation/tween_interpolaters.cpp +++ b/scene/animation/tween_interpolaters.cpp @@ -285,18 +285,18 @@ namespace cubic { namespace circ { static real_t in(real_t t, real_t b, real_t c, real_t d) { - return -c * (sqrt(1 - (t /= d) * t) - 1) + b; + return -c * (sqrt(1 - (t /= d) * t) - 1) + b; // TODO: ehrich: operation with t is undefined } static real_t out(real_t t, real_t b, real_t c, real_t d) { - return c * sqrt(1 - (t = t / d - 1) * t) + b; + return c * sqrt(1 - (t = t / d - 1) * t) + b; // TODO: ehrich: operation with t is undefined } static real_t in_out(real_t t, real_t b, real_t c, real_t d) { if ((t /= d / 2) < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b; - return c / 2 * (sqrt(1 - t * (t -= 2)) + 1) + b; + return c / 2 * (sqrt(1 - t * (t -= 2)) + 1) + b; // TODO: ehrich: operation with t is undefined } static real_t out_in(real_t t, real_t b, real_t c, real_t d) @@ -364,15 +364,15 @@ namespace back { static real_t out(real_t t, real_t b, real_t c, real_t d) { float s = 1.70158f; - return c * ((t = t / d- 1) * t * ((s + 1) * t + s) + 1) + b; + return c * ((t = t / d- 1) * t * ((s + 1) * t + s) + 1) + b; // TODO: ehrich: operation with t is undefined } static real_t in_out(real_t t, real_t b, real_t c, real_t d) { float s = 1.70158f; - if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525f)) + 1) * t - s)) + b; + if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525f)) + 1) * t - s)) + b; // TODO: ehrich: operation with s is undefined float postFix = t -= 2; - return c / 2 * ((postFix) * t * (((s *= (1.525f)) + 1) * t + s) + 2) + b; + return c / 2 * ((postFix) * t * (((s *= (1.525f)) + 1) * t + s) + 2) + b; // TODO: ehrich: operation with s is undefined } static real_t out_in(real_t t, real_t b, real_t c, real_t d) diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index 57dd29ad0..5b837d699 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -115,6 +115,8 @@ void Button::_notification(int p_what) { text_ofs.y+=style->get_offset().y; } break; case ALIGN_CENTER: { + if (text_ofs.x<0) + text_ofs.x=0; text_ofs+=icon_ofs; text_ofs+=style->get_offset(); } break; diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp index 309152ba8..2aa82bc5f 100644 --- a/scene/gui/check_box.cpp +++ b/scene/gui/check_box.cpp @@ -59,7 +59,7 @@ bool CheckBox::is_radio() Node* parent = this; do { parent = parent->get_parent(); - if (dynamic_cast< ButtonGroup* >(parent)) + if (parent->cast_to<ButtonGroup>()) break; } while (parent); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 50ce657d2..13cf87ac2 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -92,7 +92,6 @@ void FileDialog::_file_entered(const String& p_file) { } void FileDialog::_save_confirm_pressed() { - String f=dir_access->get_current_dir().plus_file(file->get_text()); emit_signal("file_selected",f); hide(); diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 6afff81fd..dac21275d 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -99,7 +99,7 @@ void Label::_notification(int p_what) { int chars_total=0; int vbegin=0,vsep=0; - + if (lines_total && lines_total < lines_visible) { @@ -136,10 +136,9 @@ void Label::_notification(int p_what) { if (!wc) return; - + int c = 0; int line=0; while(wc) { - /* handle lines not meant to be drawn quickly */ if (line>line_to) break; @@ -170,8 +169,8 @@ void Label::_notification(int p_what) { while(to && to->char_pos>=0) { taken+=to->pixel_width; - if (to!=from) { - spaces++; + if (to!=from && to->space_count) { + spaces+=to->space_count; } to=to->next; } @@ -212,15 +211,15 @@ void Label::_notification(int p_what) { ERR_PRINT("BUG"); return; } - if (from!=wc) { + if (from->space_count) { /* spacing */ - x_ofs+=space_w; + x_ofs+=space_w*from->space_count; if (can_fill && align==ALIGN_FILL && spaces) { - + x_ofs+=int((size.width-(taken+space_w*spaces))/spaces); } - - + + } @@ -253,7 +252,7 @@ void Label::_notification(int p_what) { } for (int i=0;i<from->word_len;i++) { - + if (visible_chars < 0 || chars_total<visible_chars) { CharType c = text[i+pos]; CharType n = text[i+pos+1]; @@ -361,11 +360,12 @@ void Label::regenerate_word_cache() { int width=autowrap?get_size().width:get_longest_line_width(); Ref<Font> font = get_font("font"); - + int current_word_size=0; int word_pos=0; int line_width=0; - int last_width=0; + int space_count=0; + int space_width=font->get_char_size(' ').width; line_count=1; total_char_cache=0; @@ -374,16 +374,17 @@ void Label::regenerate_word_cache() { for (int i=0;i<text.size()+1;i++) { CharType current=i<text.length()?text[i]:' '; //always a space at the end, so the algo works - + if (uppercase) current=String::char_uppercase(current); + bool not_latin = current>=33 && (current < 65||current >90) && (current<97||current>122) && (current<48||current>57); bool insert_newline=false; - + int char_width; + if (current<33) { - + if (current_word_size>0) { - WordCache *wc = memnew( WordCache ); if (word_cache) { last->next=wc; @@ -391,14 +392,16 @@ void Label::regenerate_word_cache() { word_cache=wc; } last=wc; - + wc->pixel_width=current_word_size; wc->char_pos=word_pos; wc->word_len=i-word_pos; + wc->space_count = space_count; current_word_size=0; - + space_count=0; + } - + if (current=='\n') { insert_newline=true; @@ -408,26 +411,49 @@ void Label::regenerate_word_cache() { if (i<text.length() && text[i] == ' ') { total_char_cache--; // do not count spaces + if (line_width > 0 || last==NULL || last->char_pos!=WordCache::CHAR_WRAPLINE) { + space_count++; + line_width+=space_width; + }else { + space_count=0; + } } } else { - + // latin characters if (current_word_size==0) { - if (line_width>0) // add a space before the new word if a word existed before - line_width+=font->get_char_size(' ').width; word_pos=i; } - int char_width=font->get_char_size(current).width; + char_width=font->get_char_size(current).width; current_word_size+=char_width; line_width+=char_width; total_char_cache++; } - - if ((autowrap && line_width>=width && last_width<width) || insert_newline) { - + + if ((autowrap && (line_width >= width) && ((last && last->char_pos >= 0) || not_latin)) || insert_newline) { + if (not_latin) { + if (current_word_size>0) { + WordCache *wc = memnew( WordCache ); + if (word_cache) { + last->next=wc; + } else { + word_cache=wc; + } + last=wc; + + wc->pixel_width=current_word_size-char_width; + wc->char_pos=word_pos; + wc->word_len=i-word_pos; + wc->space_count = space_count; + current_word_size=char_width; + space_count=0; + word_pos=i; + } + } + WordCache *wc = memnew( WordCache ); if (word_cache) { last->next=wc; @@ -435,18 +461,16 @@ void Label::regenerate_word_cache() { word_cache=wc; } last=wc; - + wc->pixel_width=0; wc->char_pos=insert_newline?WordCache::CHAR_NEWLINE:WordCache::CHAR_WRAPLINE; line_width=current_word_size; line_count++; + space_count=0; - } - last_width=line_width; - } //total_char_cache -= line_count + 1; // do not count new lines (including the first one) @@ -465,7 +489,7 @@ void Label::regenerate_word_cache() { set_max(line_count); word_cache_dirty=false; - + } diff --git a/scene/gui/label.h b/scene/gui/label.h index 3b0dddc1a..81e3ab567 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -75,8 +75,9 @@ private: int char_pos; // if -1, then newline int word_len; int pixel_width; + int space_count; WordCache *next; - WordCache() { char_pos=0; word_len=0; pixel_width=0; next=0; } + WordCache() { char_pos=0; word_len=0; pixel_width=0; next=0; space_count=0;} }; bool word_cache_dirty; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 14aa3da85..fec9e401f 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -272,7 +272,7 @@ void LineEdit::_input_event(InputEvent p_event) { if (editable) { selection_delete(); - CharType ucodestr[2]={k.unicode,0}; + CharType ucodestr[2]={(CharType)k.unicode,0}; append_at_cursor(ucodestr); emit_signal("text_changed",text); _change_notify("text"); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 4be53839b..6b2e5aea7 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -235,6 +235,9 @@ if (m_height > line_height) {\ while (c[end]!=0 && !(end && c[end-1]==' ' && c[end]!=' ')) { int cw = font->get_char_size(c[end],c[end+1]).width; + if (c[end]=='\t') { + cw=tab_size*font->get_char_size(' ').width; + } w+=cw; if (c[end]==' ') { @@ -268,7 +271,9 @@ if (m_height > line_height) {\ } if (found_space) { - fw+=l.offset_caches[line]/l.space_caches[line]; + int ln = MIN(l.offset_caches.size()-1,line); + + fw+=l.offset_caches[ln]/l.space_caches[ln]; } } @@ -290,6 +295,9 @@ if (m_height > line_height) {\ int cw=font->get_char_size(c[i],c[i+1]).x; + if (c[i]=='\t') { + cw=tab_size*font->get_char_size(' ').width; + } if (p_click_pos.x-cw/2>pofs) { @@ -330,6 +338,10 @@ if (m_height > line_height) {\ cw=font->draw_char(ci,Point2(pofs,y+lh-(fh-ascent)),c[i],c[i+1],color); } + if (c[i]=='\t') { + cw=tab_size*font->get_char_size(' ').width; + } + //print_line("draw char: "+String::chr(c[i])); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 1e8243216..db8fbf7a6 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -489,7 +489,7 @@ void TextEdit::_notification(int p_what) { CharType cc = text[i][j]; //ignore any brackets inside a string - if (cc== '"' | cc == '\'') { + if (cc== '"' || cc == '\'') { CharType quotation = cc; do { j++; @@ -560,7 +560,7 @@ void TextEdit::_notification(int p_what) { CharType cc = text[i][j]; //ignore any brackets inside a string - if (cc== '"' | cc == '\'') { + if (cc== '"' || cc == '\'') { CharType quotation = cc; do { j--; @@ -1249,7 +1249,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } - if (!mb.doubleclick && (OS::get_singleton()->get_ticks_msec()-last_dblclk)<600) { + if (!mb.doubleclick && (OS::get_singleton()->get_ticks_msec()-last_dblclk)<600 && cursor.line==prev_line) { //tripleclick select line select(cursor.line,0,cursor.line,text[cursor.line].length()); last_dblclk=0; @@ -1440,7 +1440,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } else { //different char, go back - const CharType chr[2] = {k.unicode, 0}; + const CharType chr[2] = {(CharType)k.unicode, 0}; if(auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { _consume_pair_symbol(chr[0]); } else { @@ -2062,7 +2062,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (readonly) break; - const CharType chr[2] = {k.unicode, 0}; + const CharType chr[2] = {(CharType)k.unicode, 0}; if(auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { _consume_pair_symbol(chr[0]); @@ -3494,6 +3494,9 @@ void TextEdit::set_line(int line, String new_text) return; _remove_text(line, 0, line, text[line].length()); _insert_text(line, 0, new_text); + if (cursor.line==line) { + cursor.column=MIN(cursor.column,new_text.length()); + } } void TextEdit::insert_at(const String &p_text, int at) diff --git a/scene/main/node.cpp b/scene/main/node.cpp index e0181b923..5c60b9fbf 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1417,6 +1417,41 @@ void Node::_duplicate_and_reown(Node* p_new_parent, const Map<Node*,Node*>& p_re } + +void Node::_duplicate_signals(const Node* p_original,Node* p_copy) const { + + if (this!=p_original && get_owner()!=p_original) + return; + + List<Connection> conns; + get_all_signal_connections(&conns); + + for (List<Connection>::Element *E=conns.front();E;E=E->next()) { + + if (E->get().flags&CONNECT_PERSIST) { + //user connected + NodePath p = p_original->get_path_to(this); + Node *copy = p_copy->get_node(p); + + Node *target = E->get().target->cast_to<Node>(); + if (!target) + continue; + NodePath ptarget = p_original->get_path_to(target); + Node *copytarget = p_copy->get_node(ptarget); + + if (copy && copytarget) { + copy->connect(E->get().signal,copytarget,E->get().method,E->get().binds,CONNECT_PERSIST); + } + } + } + + for(int i=0;i<get_child_count();i++) { + get_child(i)->_duplicate_signals(p_original,p_copy); + } + +} + + Node *Node::duplicate_and_reown(const Map<Node*,Node*>& p_reown_map) const { @@ -1455,6 +1490,7 @@ Node *Node::duplicate_and_reown(const Map<Node*,Node*>& p_reown_map) const { get_child(i)->_duplicate_and_reown(node,p_reown_map); } + _duplicate_signals(this,node); return node; } diff --git a/scene/main/node.h b/scene/main/node.h index aeada3c5b..be32c4e72 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -126,6 +126,7 @@ private: void _propagate_pause_owner(Node*p_owner); Array _get_node_and_resource(const NodePath& p_path); + void _duplicate_signals(const Node* p_original,Node* p_copy) const; void _duplicate_and_reown(Node* p_new_parent, const Map<Node*,Node*>& p_reown_map) const; Array _get_children() const; Array _get_groups() const; @@ -170,6 +171,7 @@ public: NOTIFICATION_PROCESS = 17, NOTIFICATION_PARENTED=18, NOTIFICATION_UNPARENTED=19, + NOTIFICATION_INSTANCED=20, }; /* NODE/TREE */ diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp index 2e3e7db0a..3a80382a4 100644 --- a/scene/main/timer.cpp +++ b/scene/main/timer.cpp @@ -45,14 +45,14 @@ void Timer::_notification(int p_what) { } } break; case NOTIFICATION_PROCESS: { - - if (!is_processing()) + if (timer_process_mode == TIMER_PROCESS_FIXED || !is_processing()) return; time_left -= get_process_delta_time(); if (time_left<0) { if (!one_shot) - time_left=wait_time+time_left; + //time_left=wait_time+time_left; + time_left = wait_time; else stop(); @@ -60,13 +60,27 @@ void Timer::_notification(int p_what) { } } break; + case NOTIFICATION_FIXED_PROCESS: { + if (timer_process_mode == TIMER_PROCESS_IDLE || !is_fixed_processing()) + return; + time_left -= get_fixed_process_delta_time(); + + if (time_left<0) { + if (!one_shot) + //time_left = wait_time + time_left; + time_left = wait_time; + else + stop(); + emit_signal("timeout"); + } + + } break; } } void Timer::set_wait_time(float p_time) { - ERR_EXPLAIN("time should be greater than zero."); ERR_FAIL_COND(p_time<=0); wait_time=p_time; @@ -96,14 +110,13 @@ bool Timer::has_autostart() const { } void Timer::start() { - time_left=wait_time; - set_process(true); + _set_process(true); } void Timer::stop() { time_left=-1; - set_process(false); + _set_process(false); autostart=false; } @@ -112,6 +125,41 @@ float Timer::get_time_left() const { return time_left >0 ? time_left : 0; } +void Timer::set_timer_process_mode(TimerProcessMode p_mode) { + + if (timer_process_mode == p_mode) + return; + + switch (timer_process_mode) { + case TIMER_PROCESS_FIXED: + if (is_fixed_processing()) { + set_fixed_process(false); + set_process(true); + } + break; + case TIMER_PROCESS_IDLE: + if (is_processing()) { + set_process(false); + set_fixed_process(true); + } + break; + } + timer_process_mode = p_mode; +} + +Timer::TimerProcessMode Timer::get_timer_process_mode() const{ + + return timer_process_mode; +} + + +void Timer::_set_process(bool p_process, bool p_force) +{ + switch (timer_process_mode) { + case TIMER_PROCESS_FIXED: set_fixed_process(p_process); break; + case TIMER_PROCESS_IDLE: set_process(p_process); break; + } +} void Timer::_bind_methods() { @@ -129,8 +177,12 @@ void Timer::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_time_left"),&Timer::get_time_left); + ObjectTypeDB::bind_method(_MD("set_timer_process_mode", "mode"), &Timer::set_timer_process_mode); + ObjectTypeDB::bind_method(_MD("get_timer_process_mode"), &Timer::get_timer_process_mode); + ADD_SIGNAL( MethodInfo("timeout") ); + ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_timer_process_mode"), _SCS("get_timer_process_mode")); ADD_PROPERTY( PropertyInfo(Variant::REAL, "wait_time", PROPERTY_HINT_EXP_RANGE, "0.01,4096,0.01" ), _SCS("set_wait_time"), _SCS("get_wait_time") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL, "one_shot" ), _SCS("set_one_shot"), _SCS("is_one_shot") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL, "autostart" ), _SCS("set_autostart"), _SCS("has_autostart") ); @@ -138,8 +190,7 @@ void Timer::_bind_methods() { } Timer::Timer() { - - + timer_process_mode = TIMER_PROCESS_IDLE; autostart=false; wait_time=1; one_shot=false; diff --git a/scene/main/timer.h b/scene/main/timer.h index 021638ccf..4b9cecba8 100644 --- a/scene/main/timer.h +++ b/scene/main/timer.h @@ -46,6 +46,11 @@ protected: static void _bind_methods(); public: + enum TimerProcessMode { + TIMER_PROCESS_FIXED, + TIMER_PROCESS_IDLE, + }; + void set_wait_time(float p_time); float get_wait_time() const; @@ -60,7 +65,16 @@ public: float get_time_left() const; + void set_timer_process_mode(TimerProcessMode p_mode); + TimerProcessMode get_timer_process_mode() const; Timer(); + +private: + TimerProcessMode timer_process_mode; + void _set_process(bool p_process, bool p_force = false); + }; +VARIANT_ENUM_CAST(Timer::TimerProcessMode); + #endif // TIMER_H diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 0f11a6670..095406dad 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -1216,8 +1216,8 @@ T Animation::_interpolate( const Vector< TKey<T> >& p_keys, float p_time, Inter if (p_ok) *p_ok=true; - - int next; + + int next=0; float c=0; // prepare for all cases of interpolation diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 9f3651073..a1cb1205e 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -182,6 +182,8 @@ Node *PackedScene::instance(bool p_gen_edit_state) const { if (get_path()!="" && get_path().find("::")==-1) s->set_filename(get_path()); + + s->notification(Node::NOTIFICATION_INSTANCED); return ret_nodes[0]; } diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp index 131b0e193..24d597885 100644 --- a/scene/resources/shader_graph.cpp +++ b/scene/resources/shader_graph.cpp @@ -2160,7 +2160,7 @@ void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<Str "floor($)", "round($)", "ceil($)", - "frac($)", + "fract($)", "min(max($,0),1)", "-($)", }; @@ -2378,7 +2378,7 @@ void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<Str String name = p_node->param1; Vector3 dv=p_node->param2; - code +="uniform float "+name+"=vec3("+rtos(dv.x)+","+rtos(dv.y)+","+rtos(dv.z)+");\n"; + code +="uniform vec3 "+name+"=vec3("+rtos(dv.x)+","+rtos(dv.y)+","+rtos(dv.z)+");\n"; code += OUTNAME(p_node->id,0)+"="+name+";\n"; }break; case NODE_RGB_INPUT: { diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index 8350bf8cc..21bdb6c0a 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -105,6 +105,9 @@ bool Theme::_get(const StringName& p_name,Variant &r_ret) const { void Theme::_get_property_list( List<PropertyInfo> *p_list) const { + + List<PropertyInfo> list; + const StringName *key=NULL; while((key=icon_map.next(key))) { @@ -113,7 +116,7 @@ void Theme::_get_property_list( List<PropertyInfo> *p_list) const { while((key2=icon_map[*key].next(key2))) { - p_list->push_back( PropertyInfo( Variant::OBJECT, String()+*key+"/icons/"+*key2, PROPERTY_HINT_RESOURCE_TYPE, "Texture" ) ); + list.push_back( PropertyInfo( Variant::OBJECT, String()+*key+"/icons/"+*key2, PROPERTY_HINT_RESOURCE_TYPE, "Texture" ) ); } } @@ -125,7 +128,7 @@ void Theme::_get_property_list( List<PropertyInfo> *p_list) const { while((key2=style_map[*key].next(key2))) { - p_list->push_back( PropertyInfo( Variant::OBJECT, String()+*key+"/styles/"+*key2, PROPERTY_HINT_RESOURCE_TYPE, "StyleBox" ) ); + list.push_back( PropertyInfo( Variant::OBJECT, String()+*key+"/styles/"+*key2, PROPERTY_HINT_RESOURCE_TYPE, "StyleBox" ) ); } } @@ -138,7 +141,7 @@ void Theme::_get_property_list( List<PropertyInfo> *p_list) const { while((key2=font_map[*key].next(key2))) { - p_list->push_back( PropertyInfo( Variant::OBJECT, String()+*key+"/fonts/"+*key2, PROPERTY_HINT_RESOURCE_TYPE, "Font" ) ); + list.push_back( PropertyInfo( Variant::OBJECT, String()+*key+"/fonts/"+*key2, PROPERTY_HINT_RESOURCE_TYPE, "Font" ) ); } } @@ -150,7 +153,7 @@ void Theme::_get_property_list( List<PropertyInfo> *p_list) const { while((key2=color_map[*key].next(key2))) { - p_list->push_back( PropertyInfo( Variant::COLOR, String()+*key+"/colors/"+*key2 ) ); + list.push_back( PropertyInfo( Variant::COLOR, String()+*key+"/colors/"+*key2 ) ); } } @@ -162,9 +165,14 @@ void Theme::_get_property_list( List<PropertyInfo> *p_list) const { while((key2=constant_map[*key].next(key2))) { - p_list->push_back( PropertyInfo( Variant::INT, String()+*key+"/constants/"+*key2 ) ); + list.push_back( PropertyInfo( Variant::INT, String()+*key+"/constants/"+*key2 ) ); } } + + list.sort(); + for(List<PropertyInfo>::Element *E=list.front();E;E=E->next()) { + p_list->push_back(E->get()); + } } |
