diff options
Diffstat (limited to 'scene')
52 files changed, 1421 insertions, 307 deletions
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 92d5088b81..49229ba500 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -1172,6 +1172,14 @@ Matrix32 CanvasItem::get_viewport_transform() const { } +void CanvasItem::set_notify_local_transform(bool p_enable) { + notify_local_transform=p_enable; +} + +bool CanvasItem::is_local_transform_notification_enabled() const { + return notify_local_transform; +} + CanvasItem::CanvasItem() : xform_change(this) { @@ -1191,6 +1199,7 @@ CanvasItem::CanvasItem() : xform_change(this) { canvas_layer=NULL; use_parent_material=false; global_invalid=true; + notify_local_transform=false; light_mask=1; C=NULL; diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 6d8308dbe4..4885256c64 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -126,6 +126,7 @@ private: bool block_transform_notify; bool behind; bool use_parent_material; + bool notify_local_transform; Ref<CanvasItemMaterial> material; @@ -155,7 +156,7 @@ private: protected: - _FORCE_INLINE_ void _notify_transform() { if (!is_inside_tree()) return; _notify_transform(this); if (!block_transform_notify) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); } + _FORCE_INLINE_ void _notify_transform() { if (!is_inside_tree()) return; _notify_transform(this); if (!block_transform_notify && notify_local_transform) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); } void item_rect_changed(); @@ -263,6 +264,10 @@ public: Vector2 get_global_mouse_pos() const; Vector2 get_local_mouse_pos() const; + void set_notify_local_transform(bool p_enable); + bool is_local_transform_notification_enabled() const; + + CanvasItem(); ~CanvasItem(); }; diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index ceea41d1c8..8a5e2f51d1 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -33,7 +33,7 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { - if (unparenting) + if (unparenting || !can_update_body) return; CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>(); @@ -49,6 +49,7 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { //here comes the sun, lalalala //decompose concave into multiple convex polygons and add them Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon); + shape_from=co->get_shape_count(); for(int i=0;i<decomp.size();i++) { Ref<ConvexPolygonShape2D> convex = memnew( ConvexPolygonShape2D ); convex->set_points(decomp[i]); @@ -57,6 +58,11 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { co->set_shape_as_trigger(co->get_shape_count()-1,true); } + shape_to=co->get_shape_count()-1; + if (shape_to<shape_from) { + shape_from=-1; + shape_to=-1; + } } else { @@ -78,6 +84,9 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { if (trigger) co->set_shape_as_trigger(co->get_shape_count()-1,true); + shape_from=co->get_shape_count()-1; + shape_to=co->get_shape_count()-1; + } @@ -86,6 +95,8 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { void CollisionPolygon2D::_update_parent() { + if (!can_update_body) + return; Node *parent = get_parent(); if (!parent) return; @@ -101,12 +112,24 @@ void CollisionPolygon2D::_notification(int p_what) { switch(p_what) { case NOTIFICATION_ENTER_TREE: { unparenting=false; + can_update_body=get_tree()->is_editor_hint(); + } break; + case NOTIFICATION_EXIT_TREE: { + can_update_body=false; } break; case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { if (!is_inside_tree()) break; - _update_parent(); + if (can_update_body) { + _update_parent(); + } else if (shape_from>=0 && shape_to>=0) { + CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); + for(int i=shape_from;i<=shape_to;i++) { + co->set_shape_transform(i,get_transform()); + } + } + } break; @@ -141,20 +164,22 @@ void CollisionPolygon2D::set_polygon(const Vector<Point2>& p_polygon) { polygon=p_polygon; - for(int i=0;i<polygon.size();i++) { - if (i==0) - aabb=Rect2(polygon[i],Size2()); - else - aabb.expand_to(polygon[i]); - } - if (aabb==Rect2()) { + if (can_update_body) { + for(int i=0;i<polygon.size();i++) { + if (i==0) + aabb=Rect2(polygon[i],Size2()); + else + aabb.expand_to(polygon[i]); + } + if (aabb==Rect2()) { - aabb=Rect2(-10,-10,20,20); - } else { - aabb.pos-=aabb.size*0.3; - aabb.size+=aabb.size*0.6; + aabb=Rect2(-10,-10,20,20); + } else { + aabb.pos-=aabb.size*0.3; + aabb.size+=aabb.size*0.6; + } + _update_parent(); } - _update_parent(); update(); } @@ -184,6 +209,13 @@ void CollisionPolygon2D::set_trigger(bool p_trigger) { trigger=p_trigger; _update_parent(); + if (!can_update_body && is_inside_tree() && shape_from>=0 && shape_to>=0) { + CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); + for(int i=shape_from;i<=shape_to;i++) { + co->set_shape_as_trigger(i,p_trigger); + } + + } } bool CollisionPolygon2D::is_trigger() const{ @@ -192,6 +224,17 @@ bool CollisionPolygon2D::is_trigger() const{ } +void CollisionPolygon2D::_set_shape_range(const Vector2& p_range) { + + shape_from=p_range.x; + shape_to=p_range.y; +} + +Vector2 CollisionPolygon2D::_get_shape_range() const { + + return Vector2(shape_from,shape_to); +} + void CollisionPolygon2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon2D::_add_to_collision_object); @@ -204,9 +247,17 @@ void CollisionPolygon2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_trigger"),&CollisionPolygon2D::set_trigger); ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionPolygon2D::is_trigger); + ObjectTypeDB::bind_method(_MD("_set_shape_range","shape_range"),&CollisionPolygon2D::_set_shape_range); + ObjectTypeDB::bind_method(_MD("_get_shape_range"),&CollisionPolygon2D::_get_shape_range); + + ObjectTypeDB::bind_method(_MD("get_collision_object_first_shape"),&CollisionPolygon2D::get_collision_object_first_shape); + ObjectTypeDB::bind_method(_MD("get_collision_object_last_shape"),&CollisionPolygon2D::get_collision_object_last_shape); + ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Segments"),_SCS("set_build_mode"),_SCS("get_build_mode")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"shape_range",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_shape_range"),_SCS("_get_shape_range")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger")); + } CollisionPolygon2D::CollisionPolygon2D() { @@ -215,6 +266,9 @@ CollisionPolygon2D::CollisionPolygon2D() { build_mode=BUILD_SOLIDS; trigger=false; unparenting=false; - + shape_from=-1; + shape_to=-1; + can_update_body=false; + set_notify_local_transform(true); } diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h index 4e78868082..4bc9713c8a 100644 --- a/scene/2d/collision_polygon_2d.h +++ b/scene/2d/collision_polygon_2d.h @@ -56,6 +56,14 @@ protected: void _add_to_collision_object(Object *p_obj); void _update_parent(); + bool can_update_body; + int shape_from; + int shape_to; + + void _set_shape_range(const Vector2& p_range); + Vector2 _get_shape_range() const; + + protected: void _notification(int p_what); @@ -72,6 +80,10 @@ public: Vector<Point2> get_polygon() const; virtual Rect2 get_item_rect() const; + + int get_collision_object_first_shape() const { return shape_from; } + int get_collision_object_last_shape() const { return shape_to; } + CollisionPolygon2D(); }; diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index 5012c54b17..a0a015a99e 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -44,10 +44,12 @@ void CollisionShape2D::_add_to_collision_object(Object *p_obj) { CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>(); ERR_FAIL_COND(!co); + update_shape_index=co->get_shape_count(); co->add_shape(shape,get_transform()); if (trigger) co->set_shape_as_trigger(co->get_shape_count()-1,true); + } void CollisionShape2D::_shape_changed() { @@ -74,12 +76,27 @@ void CollisionShape2D::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { unparenting=false; + can_update_body=get_tree()->is_editor_hint(); + } break; case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { if (!is_inside_tree()) break; - _update_parent(); + if (can_update_body) { + _update_parent(); + } else if (update_shape_index>=0){ + + CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); + if (co) { + co->set_shape_transform(update_shape_index,get_transform()); + } + + } + + } break; + case NOTIFICATION_EXIT_TREE: { + can_update_body=false; } break; /* @@ -92,6 +109,9 @@ void CollisionShape2D::_notification(int p_what) { } break;*/ case NOTIFICATION_DRAW: { + if (!get_tree()->is_editor_hint()) + return; + rect=Rect2(); Color draw_col=Color(0,0.6,0.7,0.5); @@ -209,7 +229,14 @@ void CollisionShape2D::set_shape(const Ref<Shape2D>& p_shape) { shape->disconnect("changed",this,"_shape_changed"); shape=p_shape; update(); - _update_parent(); + if (is_inside_tree() && can_update_body) + _update_parent(); + if (is_inside_tree() && !can_update_body && update_shape_index>=0) { + CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); + if (co) { + co->set_shape(update_shape_index,p_shape); + } + } if (shape.is_valid()) shape->connect("changed",this,"_shape_changed"); @@ -228,7 +255,14 @@ Rect2 CollisionShape2D::get_item_rect() const { void CollisionShape2D::set_trigger(bool p_trigger) { trigger=p_trigger; - _update_parent(); + if (can_update_body) { + _update_parent(); + } else if (is_inside_tree() && update_shape_index>=0){ + CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); + if (co) { + co->set_shape_as_trigger(update_shape_index,p_trigger); + } + } } bool CollisionShape2D::is_trigger() const{ @@ -236,6 +270,19 @@ bool CollisionShape2D::is_trigger() const{ return trigger; } + +void CollisionShape2D::_set_update_shape_index(int p_index) { + + + update_shape_index=p_index; +} + +int CollisionShape2D::_get_update_shape_index() const{ + + return update_shape_index; +} + + void CollisionShape2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_shape","shape"),&CollisionShape2D::set_shape); @@ -245,14 +292,23 @@ void CollisionShape2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_trigger","enable"),&CollisionShape2D::set_trigger); ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionShape2D::is_trigger); + ObjectTypeDB::bind_method(_MD("_set_update_shape_index","index"),&CollisionShape2D::_set_update_shape_index); + ObjectTypeDB::bind_method(_MD("_get_update_shape_index"),&CollisionShape2D::_get_update_shape_index); + + ObjectTypeDB::bind_method(_MD("get_collision_object_shape_index"),&CollisionShape2D::get_collision_object_shape_index); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D"),_SCS("set_shape"),_SCS("get_shape")); ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_NOEDITOR), _SCS("_set_update_shape_index"), _SCS("_get_update_shape_index")); + } CollisionShape2D::CollisionShape2D() { rect=Rect2(-Point2(10,10),Point2(20,20)); - + set_notify_local_transform(true); trigger=false; unparenting = false; + can_update_body = false; + update_shape_index=-1; } diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h index 507912d31e..82e1137174 100644 --- a/scene/2d/collision_shape_2d.h +++ b/scene/2d/collision_shape_2d.h @@ -39,7 +39,13 @@ class CollisionShape2D : public Node2D { Rect2 rect; bool trigger; bool unparenting; + bool can_update_body; void _shape_changed(); + int update_shape_index; + + void _set_update_shape_index(int p_index); + int _get_update_shape_index() const; + protected: void _update_parent(); @@ -55,6 +61,8 @@ public: void set_trigger(bool p_trigger); bool is_trigger() const; + int get_collision_object_shape_index() const { return _get_update_shape_index(); } + CollisionShape2D(); }; diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index c521952f9b..6705cebf37 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -322,8 +322,8 @@ void Sprite::_bind_methods() { ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset")); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h")); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v")); - ADD_PROPERTYNO( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes")); - ADD_PROPERTYNO( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes")); + ADD_PROPERTYNO( PropertyInfo( Variant::INT, "vframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_vframes"),_SCS("get_vframes")); + ADD_PROPERTYNO( PropertyInfo( Variant::INT, "hframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_hframes"),_SCS("get_hframes")); ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate")); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region")); diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index 58cbbdba22..ff35837bc0 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -83,15 +83,25 @@ real_t Area::get_gravity() const{ return gravity; } +void Area::set_linear_damp(real_t p_linear_damp){ -void Area::set_density(real_t p_density){ + linear_damp=p_linear_damp; + PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_LINEAR_DAMP,p_linear_damp); +} +real_t Area::get_linear_damp() const{ + + return linear_damp; +} - density=p_density; - PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_DENSITY,p_density); +void Area::set_angular_damp(real_t p_angular_damp){ + + angular_damp=p_angular_damp; + PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_ANGULAR_DAMP,p_angular_damp); } -real_t Area::get_density() const{ - return density; +real_t Area::get_angular_damp() const{ + + return angular_damp; } void Area::set_priority(real_t p_priority){ @@ -533,8 +543,11 @@ void Area::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_gravity","gravity"),&Area::set_gravity); ObjectTypeDB::bind_method(_MD("get_gravity"),&Area::get_gravity); - ObjectTypeDB::bind_method(_MD("set_density","density"),&Area::set_density); - ObjectTypeDB::bind_method(_MD("get_density"),&Area::get_density); + ObjectTypeDB::bind_method(_MD("set_angular_damp","angular_damp"),&Area::set_angular_damp); + ObjectTypeDB::bind_method(_MD("get_angular_damp"),&Area::get_angular_damp); + + ObjectTypeDB::bind_method(_MD("set_linear_damp","linear_damp"),&Area::set_linear_damp); + ObjectTypeDB::bind_method(_MD("get_linear_damp"),&Area::get_linear_damp); ObjectTypeDB::bind_method(_MD("set_priority","priority"),&Area::set_priority); ObjectTypeDB::bind_method(_MD("get_priority"),&Area::get_priority); @@ -571,7 +584,8 @@ void Area::_bind_methods() { 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")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"gravity_vec"),_SCS("set_gravity_vector"),_SCS("get_gravity_vector")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),_SCS("set_gravity"),_SCS("get_gravity")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"density",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_density"),_SCS("get_density")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_linear_damp"),_SCS("get_linear_damp")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_angular_damp"),_SCS("get_angular_damp")); 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")); @@ -586,7 +600,8 @@ Area::Area() : CollisionObject(PhysicsServer::get_singleton()->area_create(),tru set_gravity_vector(Vector3(0,-1,0)); gravity_is_point=false; gravity_distance_scale=0; - density=0.1; + linear_damp=0.1; + angular_damp=1; priority=0; monitoring=false; set_ray_pickable(false); diff --git a/scene/3d/area.h b/scene/3d/area.h index fa7500c47c..f03955d1e7 100644 --- a/scene/3d/area.h +++ b/scene/3d/area.h @@ -50,7 +50,8 @@ private: real_t gravity; bool gravity_is_point; real_t gravity_distance_scale; - real_t density; + real_t angular_damp; + real_t linear_damp; int priority; bool monitoring; bool monitorable; @@ -139,8 +140,11 @@ public: void set_gravity(real_t p_gravity); real_t get_gravity() const; - void set_density(real_t p_density); - real_t get_density() const; + void set_angular_damp(real_t p_angular_damp); + real_t get_angular_damp() const; + + void set_linear_damp(real_t p_linear_damp); + real_t get_linear_damp() const; void set_priority(real_t p_priority); real_t get_priority() const; diff --git a/scene/3d/body_shape.cpp b/scene/3d/body_shape.cpp index c49d1b028c..709a79a5f4 100644 --- a/scene/3d/body_shape.cpp +++ b/scene/3d/body_shape.cpp @@ -43,7 +43,10 @@ void CollisionShape::_update_body() { - + if (!get_tree() || !can_update_body) + return; + if (!get_tree()->is_editor_hint()) + return; if (get_parent() && get_parent()->cast_to<CollisionObject>()) get_parent()->cast_to<CollisionObject>()->_update_shapes_from_children(); @@ -310,10 +313,13 @@ void CollisionShape::_add_to_collision_object(Object* p_cshape) { if (shape.is_valid()) { + update_shape_index=co->get_shape_count(); co->add_shape(shape,get_transform()); - if (trigger) - co->set_shape_as_trigger( co->get_shape_count() -1, true ); - } + if (trigger) + co->set_shape_as_trigger( co->get_shape_count() -1, true ); + } else { + update_shape_index=-1; + } } void CollisionShape::_notification(int p_what) { @@ -322,12 +328,14 @@ void CollisionShape::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { unparenting=false; + can_update_body=get_tree()->is_editor_hint(); + set_notify_local_transform(!can_update_body); //indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario()); } break; case NOTIFICATION_TRANSFORM_CHANGED: { // VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform()); - if (updating_body) { + if (can_update_body && updating_body) { _update_body(); } } break; @@ -336,16 +344,30 @@ void CollisionShape::_notification(int p_what) { VisualServer::get_singleton()->free(indicator_instance); indicator_instance=RID(); }*/ + can_update_body=false; + set_notify_local_transform(false); } break; case NOTIFICATION_UNPARENTED: { unparenting=true; - if (updating_body) + if (can_update_body && updating_body) _update_body(); } break; case NOTIFICATION_PARENTED: { - if (updating_body) + if (can_update_body && updating_body) _update_body(); } break; + case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { + + if (!can_update_body && update_shape_index>=0) { + + CollisionObject *co = get_parent()->cast_to<CollisionObject>(); + if (co) { + co->set_shape_transform(update_shape_index,get_transform()); + } + } + + } break; + } } @@ -357,6 +379,18 @@ void CollisionShape::resource_changed(RES res) { } +void CollisionShape::_set_update_shape_index(int p_index) { + + + update_shape_index=p_index; +} + +int CollisionShape::_get_update_shape_index() const{ + + return update_shape_index; +} + + void CollisionShape::_bind_methods() { //not sure if this should do anything @@ -368,10 +402,14 @@ void CollisionShape::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionShape::is_trigger); ObjectTypeDB::bind_method(_MD("make_convex_from_brothers"),&CollisionShape::make_convex_from_brothers); ObjectTypeDB::set_method_flags("CollisionShape","make_convex_from_brothers",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); + ObjectTypeDB::bind_method(_MD("_set_update_shape_index","index"),&CollisionShape::_set_update_shape_index); + ObjectTypeDB::bind_method(_MD("_get_update_shape_index"),&CollisionShape::_get_update_shape_index); + ObjectTypeDB::bind_method(_MD("get_collision_object_shape_index"),&CollisionShape::get_collision_object_shape_index); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), _SCS("set_shape"), _SCS("get_shape")); - ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_NOEDITOR), _SCS("_set_update_shape_index"), _SCS("_get_update_shape_index")); } @@ -383,8 +421,15 @@ void CollisionShape::set_shape(const Ref<Shape> &p_shape) { if (!shape.is_null()) shape->register_owner(this); update_gizmo(); - if (updating_body) + if (updating_body) { _update_body(); + } else if (can_update_body && update_shape_index>=0 && is_inside_tree()){ + CollisionObject *co = get_parent()->cast_to<CollisionObject>(); + if (co) { + co->set_shape(update_shape_index,p_shape); + } + + } } Ref<Shape> CollisionShape::get_shape() const { @@ -405,8 +450,14 @@ bool CollisionShape::is_updating_body() const { void CollisionShape::set_trigger(bool p_trigger) { trigger=p_trigger; - if (updating_body) + if (updating_body) { _update_body(); + } else if (can_update_body && update_shape_index>=0 && is_inside_tree()){ + CollisionObject *co = get_parent()->cast_to<CollisionObject>(); + if (co) { + co->set_shape_as_trigger(update_shape_index,p_trigger); + } + } } bool CollisionShape::is_trigger() const{ @@ -419,7 +470,9 @@ CollisionShape::CollisionShape() { //indicator = VisualServer::get_singleton()->mesh_create(); updating_body=true; unparenting=false; - trigger=false; + update_shape_index=-1; + trigger=false; + can_update_body=false; } CollisionShape::~CollisionShape() { diff --git a/scene/3d/body_shape.h b/scene/3d/body_shape.h index b3c0006d79..c1ebf806a9 100644 --- a/scene/3d/body_shape.h +++ b/scene/3d/body_shape.h @@ -56,8 +56,16 @@ class CollisionShape : public Spatial { bool unparenting; bool trigger; + bool can_update_body; + + int update_shape_index; + void _update_body(); void _add_to_collision_object(Object* p_cshape); + + void _set_update_shape_index(int p_index); + int _get_update_shape_index() const; + protected: void _notification(int p_what); @@ -73,8 +81,10 @@ public: void set_updating_body(bool p_update); bool is_updating_body() const; - void set_trigger(bool p_trigger); - bool is_trigger() const; + void set_trigger(bool p_trigger); + bool is_trigger() const; + + int get_collision_object_shape_index() const { return _get_update_shape_index(); } CollisionShape(); ~CollisionShape(); diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp index 4ab1a1a1ab..c857b4851a 100644 --- a/scene/3d/collision_polygon.cpp +++ b/scene/3d/collision_polygon.cpp @@ -6,6 +6,8 @@ void CollisionPolygon::_add_to_collision_object(Object *p_obj) { + if (!can_update_body) + return; CollisionObject *co = p_obj->cast_to<CollisionObject>(); ERR_FAIL_COND(!co); @@ -23,6 +25,7 @@ void CollisionPolygon::_add_to_collision_object(Object *p_obj) { //here comes the sun, lalalala //decompose concave into multiple convex polygons and add them + shape_from=co->get_shape_count(); for(int i=0;i<decomp.size();i++) { Ref<ConvexPolygonShape> convex = memnew( ConvexPolygonShape ); DVector<Vector3> cp; @@ -43,6 +46,11 @@ void CollisionPolygon::_add_to_collision_object(Object *p_obj) { co->add_shape(convex,get_transform()); } + shape_to=co->get_shape_count()-1; + if (shape_to<shape_from) { + shape_from=-1; + shape_to=-1; + } } else { #if 0 @@ -71,6 +79,9 @@ void CollisionPolygon::_add_to_collision_object(Object *p_obj) { void CollisionPolygon::_update_parent() { + if (!can_update_body) + return; + Node *parent = get_parent(); if (!parent) return; @@ -80,15 +91,50 @@ void CollisionPolygon::_update_parent() { co->_update_shapes_from_children(); } +void CollisionPolygon::_set_shape_range(const Vector2& p_range) { + + shape_from=p_range.x; + shape_to=p_range.y; +} + +Vector2 CollisionPolygon::_get_shape_range() const { + + return Vector2(shape_from,shape_to); +} + void CollisionPolygon::_notification(int p_what) { switch(p_what) { + case NOTIFICATION_ENTER_TREE: { + can_update_body=get_tree()->is_editor_hint(); + set_notify_local_transform(!can_update_body); + + //indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario()); + } break; + case NOTIFICATION_EXIT_TREE: { + can_update_body=false; + set_notify_local_transform(false); + } break; case NOTIFICATION_TRANSFORM_CHANGED: { if (!is_inside_tree()) break; - _update_parent(); + if (can_update_body) { + _update_parent(); + } + + } break; + case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { + if (!can_update_body && shape_from>=0 && shape_from>=0) { + + CollisionObject *co = get_parent()->cast_to<CollisionObject>(); + if (co) { + for(int i=shape_from;i<=shape_to;i++) { + co->set_shape_transform(i,get_transform()); + } + } + } } break; #if 0 @@ -119,29 +165,31 @@ void CollisionPolygon::_notification(int p_what) { void CollisionPolygon::set_polygon(const Vector<Point2>& p_polygon) { polygon=p_polygon; + if (can_update_body) { - for(int i=0;i<polygon.size();i++) { + for(int i=0;i<polygon.size();i++) { - Vector3 p1(polygon[i].x,polygon[i].y,depth*0.5); + Vector3 p1(polygon[i].x,polygon[i].y,depth*0.5); - if (i==0) - aabb=AABB(p1,Vector3()); - else - aabb.expand_to(p1); + if (i==0) + aabb=AABB(p1,Vector3()); + else + aabb.expand_to(p1); - Vector3 p2(polygon[i].x,polygon[i].y,-depth*0.5); - aabb.expand_to(p2); + Vector3 p2(polygon[i].x,polygon[i].y,-depth*0.5); + aabb.expand_to(p2); - } - if (aabb==AABB()) { + } + if (aabb==AABB()) { - aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); - } else { - aabb.pos-=aabb.size*0.3; - aabb.size+=aabb.size*0.6; + aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); + } else { + aabb.pos-=aabb.size*0.3; + aabb.size+=aabb.size*0.6; + } + _update_parent(); } - _update_parent(); update_gizmo(); } @@ -154,6 +202,8 @@ void CollisionPolygon::set_build_mode(BuildMode p_mode) { ERR_FAIL_INDEX(p_mode,2); build_mode=p_mode; + if (!can_update_body) + return; _update_parent(); } @@ -170,6 +220,8 @@ AABB CollisionPolygon::get_item_rect() const { void CollisionPolygon::set_depth(float p_depth) { depth=p_depth; + if (!can_update_body) + return; _update_parent(); update_gizmo(); } @@ -183,22 +235,34 @@ float CollisionPolygon::get_depth() const { void CollisionPolygon::_bind_methods() { ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon::_add_to_collision_object); - ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&CollisionPolygon::set_polygon); - ObjectTypeDB::bind_method(_MD("get_polygon"),&CollisionPolygon::get_polygon); + + ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon::set_build_mode); + ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon::get_build_mode); ObjectTypeDB::bind_method(_MD("set_depth","depth"),&CollisionPolygon::set_depth); ObjectTypeDB::bind_method(_MD("get_depth"),&CollisionPolygon::get_depth); - ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon::set_build_mode); - ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon::get_build_mode); + ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&CollisionPolygon::set_polygon); + ObjectTypeDB::bind_method(_MD("get_polygon"),&CollisionPolygon::get_polygon); + + ObjectTypeDB::bind_method(_MD("_set_shape_range","shape_range"),&CollisionPolygon::_set_shape_range); + ObjectTypeDB::bind_method(_MD("_get_shape_range"),&CollisionPolygon::_get_shape_range); + + ObjectTypeDB::bind_method(_MD("get_collision_object_first_shape"),&CollisionPolygon::get_collision_object_first_shape); + ObjectTypeDB::bind_method(_MD("get_collision_object_last_shape"),&CollisionPolygon::get_collision_object_last_shape); ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Triangles"),_SCS("set_build_mode"),_SCS("get_build_mode")); - ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"depth"),_SCS("set_depth"),_SCS("get_depth")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"shape_range",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_shape_range"),_SCS("_get_shape_range")); } CollisionPolygon::CollisionPolygon() { + shape_from=-1; + shape_to=-1; + can_update_body=false; + aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); build_mode=BUILD_SOLIDS; depth=1.0; diff --git a/scene/3d/collision_polygon.h b/scene/3d/collision_polygon.h index efb3666778..9b9afea34f 100644 --- a/scene/3d/collision_polygon.h +++ b/scene/3d/collision_polygon.h @@ -24,9 +24,17 @@ protected: BuildMode build_mode; Vector<Point2> polygon; + void _add_to_collision_object(Object *p_obj); void _update_parent(); + bool can_update_body; + int shape_from; + int shape_to; + + void _set_shape_range(const Vector2& p_range); + Vector2 _get_shape_range() const; + protected: void _notification(int p_what); @@ -43,6 +51,10 @@ public: Vector<Point2> get_polygon() const; virtual AABB get_item_rect() const; + + int get_collision_object_first_shape() const { return shape_from; } + int get_collision_object_last_shape() const { return shape_to; } + CollisionPolygon(); }; diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 3d5091f667..d61859a3d0 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -133,6 +133,8 @@ real_t StaticBody::get_bounce() const{ return bounce; } + + void StaticBody::set_constant_linear_velocity(const Vector3& p_vel) { constant_linear_velocity=p_vel; @@ -494,6 +496,42 @@ real_t RigidBody::get_bounce() const{ return bounce; } + +void RigidBody::set_gravity_scale(real_t p_gravity_scale){ + + gravity_scale=p_gravity_scale; + PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_GRAVITY_SCALE,gravity_scale); + +} +real_t RigidBody::get_gravity_scale() const{ + + return gravity_scale; +} + +void RigidBody::set_linear_damp(real_t p_linear_damp){ + + ERR_FAIL_COND(p_linear_damp<-1); + linear_damp=p_linear_damp; + PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_LINEAR_DAMP,linear_damp); + +} +real_t RigidBody::get_linear_damp() const{ + + return linear_damp; +} + +void RigidBody::set_angular_damp(real_t p_angular_damp){ + + ERR_FAIL_COND(p_angular_damp<-1); + angular_damp=p_angular_damp; + PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_ANGULAR_DAMP,angular_damp); + +} +real_t RigidBody::get_angular_damp() const{ + + return angular_damp; +} + void RigidBody::set_axis_velocity(const Vector3& p_axis) { Vector3 v = state? state->get_linear_velocity() : linear_velocity; @@ -685,6 +723,16 @@ void RigidBody::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_angular_velocity","angular_velocity"),&RigidBody::set_angular_velocity); ObjectTypeDB::bind_method(_MD("get_angular_velocity"),&RigidBody::get_angular_velocity); + ObjectTypeDB::bind_method(_MD("set_gravity_scale","gravity_scale"),&RigidBody::set_gravity_scale); + ObjectTypeDB::bind_method(_MD("get_gravity_scale"),&RigidBody::get_gravity_scale); + + ObjectTypeDB::bind_method(_MD("set_linear_damp","linear_damp"),&RigidBody::set_linear_damp); + ObjectTypeDB::bind_method(_MD("get_linear_damp"),&RigidBody::get_linear_damp); + + ObjectTypeDB::bind_method(_MD("set_angular_damp","angular_damp"),&RigidBody::set_angular_damp); + ObjectTypeDB::bind_method(_MD("get_angular_damp"),&RigidBody::get_angular_damp); + + ObjectTypeDB::bind_method(_MD("set_max_contacts_reported","amount"),&RigidBody::set_max_contacts_reported); ObjectTypeDB::bind_method(_MD("get_max_contacts_reported"),&RigidBody::get_max_contacts_reported); @@ -722,6 +770,7 @@ void RigidBody::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::REAL,"weight",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01",PROPERTY_USAGE_EDITOR),_SCS("set_weight"),_SCS("get_weight")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_bounce"),_SCS("get_bounce")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_scale",PROPERTY_HINT_RANGE,"-128,128,0.01"),_SCS("set_gravity_scale"),_SCS("get_gravity_scale")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"custom_integrator"),_SCS("set_use_custom_integrator"),_SCS("is_using_custom_integrator")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"continuous_cd"),_SCS("set_use_continuous_collision_detection"),_SCS("is_using_continuous_collision_detection")); ADD_PROPERTY( PropertyInfo(Variant::INT,"contacts_reported"),_SCS("set_max_contacts_reported"),_SCS("get_max_contacts_reported")); @@ -731,6 +780,8 @@ void RigidBody::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::INT,"axis_lock",PROPERTY_HINT_ENUM,"Disabled,Lock X,Lock Y,Lock Z"),_SCS("set_axis_lock"),_SCS("get_axis_lock")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"velocity/linear"),_SCS("set_linear_velocity"),_SCS("get_linear_velocity")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"velocity/angular"),_SCS("set_angular_velocity"),_SCS("get_angular_velocity")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"damp_override/linear",PROPERTY_HINT_RANGE,"-1,128,0.01"),_SCS("set_linear_damp"),_SCS("get_linear_damp")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"damp_override/angular",PROPERTY_HINT_RANGE,"-1,128,0.01"),_SCS("set_angular_damp"),_SCS("get_angular_damp")); ADD_SIGNAL( MethodInfo("body_enter_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape"))); ADD_SIGNAL( MethodInfo("body_exit_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape"))); @@ -753,6 +804,10 @@ RigidBody::RigidBody() : PhysicsBody(PhysicsServer::BODY_MODE_RIGID) { max_contacts_reported=0; state=NULL; + gravity_scale=1; + linear_damp=-1; + angular_damp=-1; + //angular_velocity=0; sleeping=false; ccd=false; diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 0ff3b360af..66490ba925 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -129,6 +129,10 @@ private: Vector3 linear_velocity; Vector3 angular_velocity; + real_t gravity_scale; + real_t linear_damp; + real_t angular_damp; + bool sleeping; bool ccd; @@ -217,6 +221,16 @@ public: void set_angular_velocity(const Vector3&p_velocity); Vector3 get_angular_velocity() const; + void set_gravity_scale(real_t p_gravity_scale); + real_t get_gravity_scale() const; + + void set_linear_damp(real_t p_linear_damp); + real_t get_linear_damp() const; + + void set_angular_damp(real_t p_angular_damp); + real_t get_angular_damp() const; + + void set_use_custom_integrator(bool p_enable); bool is_using_custom_integrator(); diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index 7117c59176..a65f68ed2c 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -231,6 +231,11 @@ void Spatial::set_transform(const Transform& p_transform) { _change_notify("transform/rotation"); _change_notify("transform/scale"); _propagate_transform_changed(this); + if (data.notify_local_transform) { + notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); + } + + } @@ -335,6 +340,9 @@ void Spatial::set_translation(const Vector3& p_translation) { data.local_transform.origin=p_translation; _propagate_transform_changed(this); + if (data.notify_local_transform) { + notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); + } } @@ -348,6 +356,9 @@ void Spatial::set_rotation(const Vector3& p_euler){ data.rotation=p_euler; data.dirty|=DIRTY_LOCAL; _propagate_transform_changed(this); + if (data.notify_local_transform) { + notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); + } } void Spatial::set_scale(const Vector3& p_scale){ @@ -360,6 +371,9 @@ void Spatial::set_scale(const Vector3& p_scale){ data.scale=p_scale; data.dirty|=DIRTY_LOCAL; _propagate_transform_changed(this); + if (data.notify_local_transform) { + notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); + } } @@ -685,6 +699,13 @@ void Spatial::look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, con } +void Spatial::set_notify_local_transform(bool p_enable) { + data.notify_local_transform=p_enable; +} + +bool Spatial::is_local_transform_notification_enabled() const { + return data.notify_local_transform; +} void Spatial::_bind_methods() { @@ -725,6 +746,9 @@ void Spatial::_bind_methods() { ObjectTypeDB::bind_method(_MD("_set_visible_"), &Spatial::_set_visible_); ObjectTypeDB::bind_method(_MD("_is_visible_"), &Spatial::_is_visible_); + ObjectTypeDB::bind_method(_MD("set_notify_local_transform","enable"), &Spatial::set_notify_local_transform); + ObjectTypeDB::bind_method(_MD("is_local_transform_notification_enabled"), &Spatial::is_local_transform_notification_enabled); + void rotate(const Vector3& p_normal,float p_radians); void rotate_x(float p_radians); void rotate_y(float p_radians); @@ -783,6 +807,7 @@ Spatial::Spatial() : xform_change(this) data.gizmo_disabled=false; data.gizmo_dirty=false; #endif + data.notify_local_transform=false; data.parent=NULL; data.C=NULL; diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h index 8b40786fb8..7fa6099d7a 100644 --- a/scene/3d/spatial.h +++ b/scene/3d/spatial.h @@ -91,6 +91,7 @@ class Spatial : public Node { List<Spatial*>::Element *C; bool ignore_notification; + bool notify_local_transform; bool visible; @@ -134,6 +135,7 @@ public: NOTIFICATION_ENTER_WORLD=41, NOTIFICATION_EXIT_WORLD=42, NOTIFICATION_VISIBILITY_CHANGED=43, + NOTIFICATION_LOCAL_TRANSFORM_CHANGED=44, }; Spatial *get_parent_spatial() const; @@ -179,6 +181,9 @@ public: void look_at(const Vector3& p_target, const Vector3& p_up_normal); void look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal); + void set_notify_local_transform(bool p_enable); + bool is_local_transform_notification_enabled() const; + void orthonormalize(); void set_identity(); diff --git a/scene/3d/spatial_stream_player.cpp b/scene/3d/spatial_stream_player.cpp index 84e68bf418..b81d98e8bf 100644 --- a/scene/3d/spatial_stream_player.cpp +++ b/scene/3d/spatial_stream_player.cpp @@ -30,21 +30,79 @@ -void SpatialStreamPlayer::_notification(int p_what) { +int SpatialStreamPlayer::InternalStream::get_channel_count() const { - switch(p_what) { + return player->sp_get_channel_count(); +} +void SpatialStreamPlayer::InternalStream::set_mix_rate(int p_rate){ - case NOTIFICATION_ENTER_WORLD: { + return player->sp_set_mix_rate(p_rate); +} +bool SpatialStreamPlayer::InternalStream::mix(int32_t *p_buffer,int p_frames){ + + return player->sp_mix(p_buffer,p_frames); +} +void SpatialStreamPlayer::InternalStream::update(){ + + player->sp_update(); +} + + +int SpatialStreamPlayer::sp_get_channel_count() const { + + return playback->get_channels(); +} + +void SpatialStreamPlayer::sp_set_mix_rate(int p_rate){ + + server_mix_rate=p_rate; +} + +bool SpatialStreamPlayer::sp_mix(int32_t *p_buffer,int p_frames) { + + if (resampler.is_ready()) { + return resampler.mix(p_buffer,p_frames); + } + + return false; +} + +void SpatialStreamPlayer::sp_update() { + + _THREAD_SAFE_METHOD_ + if (!paused && resampler.is_ready() && playback.is_valid()) { + + if (!playback->is_playing()) { + //stream depleted data, but there's still audio in the ringbuffer + //check that all this audio has been flushed before stopping the stream + int to_mix = resampler.get_total() - resampler.get_todo(); + if (to_mix==0) { + stop(); + return; + } + + return; + } + + int todo =resampler.get_todo(); + int wrote = playback->mix(resampler.get_write_buffer(),todo); + resampler.write(wrote); + } +} -// set_idle_process(false); //don't annoy - } break; - case NOTIFICATION_PROCESS: { -// if (!stream.is_null()) -// stream->update(); +void SpatialStreamPlayer::_notification(int p_what) { + + switch(p_what) { + + case NOTIFICATION_ENTER_TREE: { + + //set_idle_process(false); //don't annoy + if (stream.is_valid() && autoplay && !get_tree()->is_editor_hint()) + play(); } break; - case NOTIFICATION_EXIT_WORLD: { + case NOTIFICATION_EXIT_TREE: { stop(); //wathever it may be doing, stop } break; @@ -58,12 +116,20 @@ void SpatialStreamPlayer::set_stream(const Ref<AudioStream> &p_stream) { stop(); stream=p_stream; - if (!stream.is_null()) { - stream->set_loop(loops); + if (!stream.is_null()) { + playback=stream->instance_playback(); + playback->set_loop(loops); + playback->set_loop_restart_time(loop_point); + AudioServer::get_singleton()->lock(); + resampler.setup(playback->get_channels(),playback->get_mix_rate(),server_mix_rate,buffering_ms,playback->get_minimum_buffer_size()); + AudioServer::get_singleton()->unlock(); + } else { + AudioServer::get_singleton()->lock(); + resampler.clear(); + playback.unref(); + AudioServer::get_singleton()->unlock(); } - - } Ref<AudioStream> SpatialStreamPlayer::get_stream() const { @@ -72,18 +138,25 @@ Ref<AudioStream> SpatialStreamPlayer::get_stream() const { } -void SpatialStreamPlayer::play() { +void SpatialStreamPlayer::play(float p_from_offset) { - if (!is_inside_tree()) + ERR_FAIL_COND(!is_inside_tree()); + if (playback.is_null()) return; - if (stream.is_null()) - return; - if (stream->is_playing()) + if (playback->is_playing()) stop(); - stream->play(); - SpatialSoundServer::get_singleton()->source_set_audio_stream(get_source_rid(),stream->get_audio_stream()); - //if (stream->get_update_mode()!=AudioStream::UPDATE_NONE) - // set_idle_process(true); + + _THREAD_SAFE_METHOD_ + playback->play(p_from_offset); + //feed the ringbuffer as long as no update callback is going on + sp_update(); + + SpatialSoundServer::get_singleton()->source_set_audio_stream(get_source_rid(),&internal_stream); + +// AudioServer::get_singleton()->stream_set_active(stream_rid,true); +// AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume); +// if (stream->get_update_mode()!=AudioStream::UPDATE_NONE) +// set_idle_process(true); } @@ -91,28 +164,30 @@ void SpatialStreamPlayer::stop() { if (!is_inside_tree()) return; - if (stream.is_null()) + if (playback.is_null()) return; + _THREAD_SAFE_METHOD_ + //AudioServer::get_singleton()->stream_set_active(stream_rid,false); SpatialSoundServer::get_singleton()->source_set_audio_stream(get_source_rid(),NULL); - stream->stop(); + playback->stop(); //set_idle_process(false); } bool SpatialStreamPlayer::is_playing() const { - if (stream.is_null()) + if (playback.is_null()) return false; - return stream->is_playing(); + return playback->is_playing(); } void SpatialStreamPlayer::set_loop(bool p_enable) { loops=p_enable; - if (stream.is_null()) + if (playback.is_null()) return; - stream->set_loop(loops); + playback->set_loop(loops); } bool SpatialStreamPlayer::has_loop() const { @@ -120,6 +195,46 @@ bool SpatialStreamPlayer::has_loop() const { return loops; } +void SpatialStreamPlayer::set_volume(float p_vol) { + + volume=p_vol; + if (stream_rid.is_valid()) + AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume); +} + +float SpatialStreamPlayer::get_volume() const { + + return volume; +} + +void SpatialStreamPlayer::set_loop_restart_time(float p_secs) { + + loop_point=p_secs; + if (playback.is_valid()) + playback->set_loop_restart_time(p_secs); +} + +float SpatialStreamPlayer::get_loop_restart_time() const { + + return loop_point; +} + + +void SpatialStreamPlayer::set_volume_db(float p_db) { + + if (p_db<-79) + set_volume(0); + else + set_volume(Math::db2linear(p_db)); +} + +float SpatialStreamPlayer::get_volume_db() const { + + if (volume==0) + return -80; + else + return Math::linear2db(volume); +} String SpatialStreamPlayer::get_stream_name() const { @@ -132,27 +247,85 @@ String SpatialStreamPlayer::get_stream_name() const { int SpatialStreamPlayer::get_loop_count() const { - if (stream.is_null()) + if (playback.is_null()) return 0; - return stream->get_loop_count(); + return playback->get_loop_count(); } float SpatialStreamPlayer::get_pos() const { - if (stream.is_null()) + if (playback.is_null()) return 0; - return stream->get_pos(); + return playback->get_pos(); + +} + +float SpatialStreamPlayer::get_length() const { + if (playback.is_null()) + return 0; + return playback->get_length(); } void SpatialStreamPlayer::seek_pos(float p_time) { - if (stream.is_null()) + if (playback.is_null()) return; - return stream->seek_pos(p_time); + return playback->seek_pos(p_time); + +} + +void SpatialStreamPlayer::set_autoplay(bool p_enable) { + + autoplay=p_enable; +} + +bool SpatialStreamPlayer::has_autoplay() const { + + return autoplay; +} + +void SpatialStreamPlayer::set_paused(bool p_paused) { + + paused=p_paused; + //if (stream.is_valid()) + // stream->set_paused(p_paused); +} + +bool SpatialStreamPlayer::is_paused() const { + return paused; } +void SpatialStreamPlayer::_set_play(bool p_play) { + + _play=p_play; + if (is_inside_tree()) { + if(_play) + play(); + else + stop(); + } + +} + +bool SpatialStreamPlayer::_get_play() const{ + + return _play; +} + +void SpatialStreamPlayer::set_buffering_msec(int p_msec) { + + buffering_ms=p_msec; +} + +int SpatialStreamPlayer::get_buffering_msec() const{ + + return buffering_ms; +} + + + void SpatialStreamPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_stream","stream:Stream"),&SpatialStreamPlayer::set_stream); @@ -163,28 +336,67 @@ void SpatialStreamPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_playing"),&SpatialStreamPlayer::is_playing); + ObjectTypeDB::bind_method(_MD("set_paused","paused"),&SpatialStreamPlayer::set_paused); + ObjectTypeDB::bind_method(_MD("is_paused"),&SpatialStreamPlayer::is_paused); + ObjectTypeDB::bind_method(_MD("set_loop","enabled"),&SpatialStreamPlayer::set_loop); ObjectTypeDB::bind_method(_MD("has_loop"),&SpatialStreamPlayer::has_loop); + ObjectTypeDB::bind_method(_MD("set_volume","volume"),&SpatialStreamPlayer::set_volume); + ObjectTypeDB::bind_method(_MD("get_volume"),&SpatialStreamPlayer::get_volume); + + ObjectTypeDB::bind_method(_MD("set_volume_db","db"),&SpatialStreamPlayer::set_volume_db); + ObjectTypeDB::bind_method(_MD("get_volume_db"),&SpatialStreamPlayer::get_volume_db); + + ObjectTypeDB::bind_method(_MD("set_buffering_msec","msec"),&SpatialStreamPlayer::set_buffering_msec); + ObjectTypeDB::bind_method(_MD("get_buffering_msec"),&SpatialStreamPlayer::get_buffering_msec); + + ObjectTypeDB::bind_method(_MD("set_loop_restart_time","secs"),&SpatialStreamPlayer::set_loop_restart_time); + ObjectTypeDB::bind_method(_MD("get_loop_restart_time"),&SpatialStreamPlayer::get_loop_restart_time); + ObjectTypeDB::bind_method(_MD("get_stream_name"),&SpatialStreamPlayer::get_stream_name); ObjectTypeDB::bind_method(_MD("get_loop_count"),&SpatialStreamPlayer::get_loop_count); ObjectTypeDB::bind_method(_MD("get_pos"),&SpatialStreamPlayer::get_pos); ObjectTypeDB::bind_method(_MD("seek_pos","time"),&SpatialStreamPlayer::seek_pos); - ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream/stream", PROPERTY_HINT_RESOURCE_TYPE,"AudioStream"), _SCS("set_stream"),_SCS("get_stream") ); - ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/loop"), _SCS("set_loop"),_SCS("has_loop") ); + ObjectTypeDB::bind_method(_MD("set_autoplay","enabled"),&SpatialStreamPlayer::set_autoplay); + ObjectTypeDB::bind_method(_MD("has_autoplay"),&SpatialStreamPlayer::has_autoplay); + ObjectTypeDB::bind_method(_MD("get_length"),&SpatialStreamPlayer::get_length); + + ObjectTypeDB::bind_method(_MD("_set_play","play"),&SpatialStreamPlayer::_set_play); + ObjectTypeDB::bind_method(_MD("_get_play"),&SpatialStreamPlayer::_get_play); + + ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream/stream", PROPERTY_HINT_RESOURCE_TYPE,"AudioStream"), _SCS("set_stream"), _SCS("get_stream") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/play"), _SCS("_set_play"), _SCS("_get_play") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/loop"), _SCS("set_loop"), _SCS("has_loop") ); + ADD_PROPERTY( PropertyInfo(Variant::REAL, "stream/volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), _SCS("set_volume_db"), _SCS("get_volume_db") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/autoplay"), _SCS("set_autoplay"), _SCS("has_autoplay") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/paused"), _SCS("set_paused"), _SCS("is_paused") ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/loop_restart_time"), _SCS("set_loop_restart_time"), _SCS("get_loop_restart_time") ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/buffering_ms"), _SCS("set_buffering_msec"), _SCS("get_buffering_msec") ); } SpatialStreamPlayer::SpatialStreamPlayer() { + volume=1; loops=false; + paused=false; + autoplay=false; + _play=false; + server_mix_rate=1; + internal_stream.player=this; + stream_rid=AudioServer::get_singleton()->audio_stream_create(&internal_stream); + buffering_ms=500; + loop_point=0; + } SpatialStreamPlayer::~SpatialStreamPlayer() { - -} + AudioServer::get_singleton()->free(stream_rid); + resampler.clear(); +} diff --git a/scene/3d/spatial_stream_player.h b/scene/3d/spatial_stream_player.h index 7e639a7232..f2775a4982 100644 --- a/scene/3d/spatial_stream_player.h +++ b/scene/3d/spatial_stream_player.h @@ -31,16 +31,48 @@ #include "scene/resources/audio_stream.h" #include "scene/3d/spatial_player.h" - +#include "servers/audio/audio_rb_resampler.h" class SpatialStreamPlayer : public SpatialPlayer { OBJ_TYPE(SpatialStreamPlayer,SpatialPlayer); + _THREAD_SAFE_CLASS_ + + struct InternalStream : public AudioServer::AudioStream { + SpatialStreamPlayer *player; + virtual int get_channel_count() const; + virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate + virtual bool mix(int32_t *p_buffer,int p_frames); + virtual void update(); + }; + + + InternalStream internal_stream; + Ref<AudioStreamPlayback> playback; Ref<AudioStream> stream; + + int sp_get_channel_count() const; + void sp_set_mix_rate(int p_rate); //notify the stream of the mix rate + bool sp_mix(int32_t *p_buffer,int p_frames); + void sp_update(); + + int server_mix_rate; + + RID stream_rid; + bool paused; + bool autoplay; bool loops; -protected: + float volume; + float loop_point; + int buffering_ms; + AudioRBResampler resampler; + + bool _play; + void _set_play(bool p_play); + bool _get_play() const; +protected: void _notification(int p_what); static void _bind_methods(); @@ -49,21 +81,37 @@ public: void set_stream(const Ref<AudioStream> &p_stream); Ref<AudioStream> get_stream() const; - void play(); + void play(float p_from_offset=0); void stop(); bool is_playing() const; + void set_paused(bool p_paused); + bool is_paused() const; + void set_loop(bool p_enable); bool has_loop() const; + void set_volume(float p_vol); + float get_volume() const; + + void set_loop_restart_time(float p_secs); + float get_loop_restart_time() const; + + void set_volume_db(float p_db); + float get_volume_db() const; String get_stream_name() const; - int get_loop_count() const; + int get_loop_count() const; float get_pos() const; void seek_pos(float p_time); + float get_length() const; + void set_autoplay(bool p_vol); + bool has_autoplay() const; + void set_buffering_msec(int p_msec); + int get_buffering_msec() const; SpatialStreamPlayer(); ~SpatialStreamPlayer(); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index e9da95f3fb..c7d1249a07 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -578,8 +578,8 @@ void Sprite3D::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_hframes"),&Sprite3D::get_hframes); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture")); - ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes")); - ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_vframes"),_SCS("get_vframes")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_hframes"),_SCS("get_hframes")); ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region")); ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect")); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index f8b58b5cb5..c2ea1c8bb6 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -857,6 +857,11 @@ void AnimationPlayer::clear_queue() { queued.clear(); }; +void AnimationPlayer::play_backwards(const StringName& p_name,float p_custom_blend) { + + play(p_name,p_custom_blend,-1,true); +} + void AnimationPlayer::play(const StringName& p_name, float p_custom_blend, float p_custom_scale,bool p_from_end) { //printf("animation is %ls\n", String(p_name).c_str()); @@ -1216,6 +1221,7 @@ void AnimationPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_default_blend_time"),&AnimationPlayer::get_default_blend_time); ObjectTypeDB::bind_method(_MD("play","name","custom_blend","custom_speed","from_end"),&AnimationPlayer::play,DEFVAL(""),DEFVAL(-1),DEFVAL(1.0),DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("play_backwards","name","custom_blend"),&AnimationPlayer::play_backwards,DEFVAL(""),DEFVAL(-1)); ObjectTypeDB::bind_method(_MD("stop","reset"),&AnimationPlayer::stop,DEFVAL(true)); ObjectTypeDB::bind_method(_MD("stop_all"),&AnimationPlayer::stop_all); ObjectTypeDB::bind_method(_MD("is_playing"),&AnimationPlayer::is_playing); diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 3fddc283ae..1e3c37c4d6 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -258,6 +258,7 @@ public: float get_default_blend_time() const; void play(const StringName& p_name=StringName(),float p_custom_blend=-1,float p_custom_scale=1.0,bool p_from_end=false); + void play_backwards(const StringName& p_name=StringName(),float p_custom_blend=-1); void queue(const StringName& p_name); void clear_queue(); void stop(bool p_reset=true); diff --git a/scene/audio/stream_player.cpp b/scene/audio/stream_player.cpp index a097aacf19..699d068287 100644 --- a/scene/audio/stream_player.cpp +++ b/scene/audio/stream_player.cpp @@ -28,6 +28,67 @@ /*************************************************************************/ #include "stream_player.h" +int StreamPlayer::InternalStream::get_channel_count() const { + + return player->sp_get_channel_count(); +} +void StreamPlayer::InternalStream::set_mix_rate(int p_rate){ + + return player->sp_set_mix_rate(p_rate); +} +bool StreamPlayer::InternalStream::mix(int32_t *p_buffer,int p_frames){ + + return player->sp_mix(p_buffer,p_frames); +} +void StreamPlayer::InternalStream::update(){ + + player->sp_update(); +} + + +int StreamPlayer::sp_get_channel_count() const { + + return playback->get_channels(); +} + +void StreamPlayer::sp_set_mix_rate(int p_rate){ + + server_mix_rate=p_rate; +} + +bool StreamPlayer::sp_mix(int32_t *p_buffer,int p_frames) { + + if (resampler.is_ready()) { + return resampler.mix(p_buffer,p_frames); + } + + return false; +} + +void StreamPlayer::sp_update() { + + _THREAD_SAFE_METHOD_ + if (!paused && resampler.is_ready() && playback.is_valid()) { + + if (!playback->is_playing()) { + //stream depleted data, but there's still audio in the ringbuffer + //check that all this audio has been flushed before stopping the stream + int to_mix = resampler.get_total() - resampler.get_todo(); + if (to_mix==0) { + stop(); + return; + } + + return; + } + + int todo =resampler.get_todo(); + int wrote = playback->mix(resampler.get_write_buffer(),todo); + resampler.write(wrote); + } +} + + void StreamPlayer::_notification(int p_what) { @@ -52,19 +113,21 @@ void StreamPlayer::set_stream(const Ref<AudioStream> &p_stream) { stop(); - if (stream_rid.is_valid()) - AudioServer::get_singleton()->free(stream_rid); - stream_rid=RID(); - stream=p_stream; - if (!stream.is_null()) { - stream->set_loop(loops); - stream->set_paused(paused); - stream_rid=AudioServer::get_singleton()->audio_stream_create(stream->get_audio_stream()); + if (!stream.is_null()) { + playback=stream->instance_playback(); + playback->set_loop(loops); + playback->set_loop_restart_time(loop_point); + AudioServer::get_singleton()->lock(); + resampler.setup(playback->get_channels(),playback->get_mix_rate(),server_mix_rate,buffering_ms,playback->get_minimum_buffer_size()); + AudioServer::get_singleton()->unlock(); + } else { + AudioServer::get_singleton()->lock(); + resampler.clear(); + playback.unref(); + AudioServer::get_singleton()->unlock(); } - - } Ref<AudioStream> StreamPlayer::get_stream() const { @@ -73,15 +136,18 @@ Ref<AudioStream> StreamPlayer::get_stream() const { } -void StreamPlayer::play() { +void StreamPlayer::play(float p_from_offset) { ERR_FAIL_COND(!is_inside_tree()); - if (stream.is_null()) + if (playback.is_null()) return; - if (stream->is_playing()) + if (playback->is_playing()) stop(); - stream->play(); + _THREAD_SAFE_METHOD_ + playback->play(p_from_offset); + //feed the ringbuffer as long as no update callback is going on + sp_update(); AudioServer::get_singleton()->stream_set_active(stream_rid,true); AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,volume); // if (stream->get_update_mode()!=AudioStream::UPDATE_NONE) @@ -93,28 +159,29 @@ void StreamPlayer::stop() { if (!is_inside_tree()) return; - if (stream.is_null()) + if (playback.is_null()) return; + _THREAD_SAFE_METHOD_ AudioServer::get_singleton()->stream_set_active(stream_rid,false); - stream->stop(); + playback->stop(); //set_idle_process(false); } bool StreamPlayer::is_playing() const { - if (stream.is_null()) + if (playback.is_null()) return false; - return stream->is_playing(); + return playback->is_playing(); } void StreamPlayer::set_loop(bool p_enable) { loops=p_enable; - if (stream.is_null()) + if (playback.is_null()) return; - stream->set_loop(loops); + playback->set_loop(loops); } bool StreamPlayer::has_loop() const { @@ -134,6 +201,19 @@ float StreamPlayer::get_volume() const { return volume; } +void StreamPlayer::set_loop_restart_time(float p_secs) { + + loop_point=p_secs; + if (playback.is_valid()) + playback->set_loop_restart_time(p_secs); +} + +float StreamPlayer::get_loop_restart_time() const { + + return loop_point; +} + + void StreamPlayer::set_volume_db(float p_db) { if (p_db<-79) @@ -161,31 +241,31 @@ String StreamPlayer::get_stream_name() const { int StreamPlayer::get_loop_count() const { - if (stream.is_null()) + if (playback.is_null()) return 0; - return stream->get_loop_count(); + return playback->get_loop_count(); } float StreamPlayer::get_pos() const { - if (stream.is_null()) + if (playback.is_null()) return 0; - return stream->get_pos(); + return playback->get_pos(); } float StreamPlayer::get_length() const { - if (stream.is_null()) + if (playback.is_null()) return 0; - return stream->get_length(); + return playback->get_length(); } void StreamPlayer::seek_pos(float p_time) { - if (stream.is_null()) + if (playback.is_null()) return; - return stream->seek_pos(p_time); + return playback->seek_pos(p_time); } @@ -202,8 +282,8 @@ bool StreamPlayer::has_autoplay() const { void StreamPlayer::set_paused(bool p_paused) { paused=p_paused; - if (stream.is_valid()) - stream->set_paused(p_paused); + //if (stream.is_valid()) + // stream->set_paused(p_paused); } bool StreamPlayer::is_paused() const { @@ -228,6 +308,17 @@ bool StreamPlayer::_get_play() const{ return _play; } +void StreamPlayer::set_buffering_msec(int p_msec) { + + buffering_ms=p_msec; +} + +int StreamPlayer::get_buffering_msec() const{ + + return buffering_ms; +} + + void StreamPlayer::_bind_methods() { @@ -251,6 +342,12 @@ void StreamPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_volume_db","db"),&StreamPlayer::set_volume_db); ObjectTypeDB::bind_method(_MD("get_volume_db"),&StreamPlayer::get_volume_db); + ObjectTypeDB::bind_method(_MD("set_buffering_msec","msec"),&StreamPlayer::set_buffering_msec); + ObjectTypeDB::bind_method(_MD("get_buffering_msec"),&StreamPlayer::get_buffering_msec); + + ObjectTypeDB::bind_method(_MD("set_loop_restart_time","secs"),&StreamPlayer::set_loop_restart_time); + ObjectTypeDB::bind_method(_MD("get_loop_restart_time"),&StreamPlayer::get_loop_restart_time); + ObjectTypeDB::bind_method(_MD("get_stream_name"),&StreamPlayer::get_stream_name); ObjectTypeDB::bind_method(_MD("get_loop_count"),&StreamPlayer::get_loop_count); @@ -271,6 +368,8 @@ void StreamPlayer::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::REAL, "stream/volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), _SCS("set_volume_db"), _SCS("get_volume_db") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/autoplay"), _SCS("set_autoplay"), _SCS("has_autoplay") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/paused"), _SCS("set_paused"), _SCS("is_paused") ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/loop_restart_time"), _SCS("set_loop_restart_time"), _SCS("get_loop_restart_time") ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/buffering_ms"), _SCS("set_buffering_msec"), _SCS("get_buffering_msec") ); } @@ -281,10 +380,17 @@ StreamPlayer::StreamPlayer() { paused=false; autoplay=false; _play=false; + server_mix_rate=1; + internal_stream.player=this; + stream_rid=AudioServer::get_singleton()->audio_stream_create(&internal_stream); + buffering_ms=500; + loop_point=0; + } StreamPlayer::~StreamPlayer() { - if (stream_rid.is_valid()) - AudioServer::get_singleton()->free(stream_rid); + AudioServer::get_singleton()->free(stream_rid); + resampler.clear(); + } diff --git a/scene/audio/stream_player.h b/scene/audio/stream_player.h index 21e2162188..b5aa943067 100644 --- a/scene/audio/stream_player.h +++ b/scene/audio/stream_player.h @@ -31,17 +31,43 @@ #include "scene/resources/audio_stream.h" #include "scene/main/node.h" +#include "servers/audio/audio_rb_resampler.h" class StreamPlayer : public Node { OBJ_TYPE(StreamPlayer,Node); + _THREAD_SAFE_CLASS_ + + struct InternalStream : public AudioServer::AudioStream { + StreamPlayer *player; + virtual int get_channel_count() const; + virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate + virtual bool mix(int32_t *p_buffer,int p_frames); + virtual void update(); + }; + + + InternalStream internal_stream; + Ref<AudioStreamPlayback> playback; Ref<AudioStream> stream; + + int sp_get_channel_count() const; + void sp_set_mix_rate(int p_rate); //notify the stream of the mix rate + bool sp_mix(int32_t *p_buffer,int p_frames); + void sp_update(); + + int server_mix_rate; + RID stream_rid; bool paused; bool autoplay; bool loops; float volume; + float loop_point; + int buffering_ms; + + AudioRBResampler resampler; bool _play; void _set_play(bool p_play); @@ -55,7 +81,7 @@ public: void set_stream(const Ref<AudioStream> &p_stream); Ref<AudioStream> get_stream() const; - void play(); + void play(float p_from_offset=0); void stop(); bool is_playing() const; @@ -68,6 +94,9 @@ public: void set_volume(float p_vol); float get_volume() const; + void set_loop_restart_time(float p_secs); + float get_loop_restart_time() const; + void set_volume_db(float p_db); float get_volume_db() const; @@ -81,6 +110,8 @@ public: void set_autoplay(bool p_vol); bool has_autoplay() const; + void set_buffering_msec(int p_msec); + int get_buffering_msec() const; StreamPlayer(); ~StreamPlayer(); diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 3ddf23fc4a..0c0f924f52 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -274,7 +274,7 @@ Button* AcceptDialog::add_button(const String& p_text,bool p_right,const String& } if (p_action!="") { - button->connect("pressed",this,"_custom_action",make_binds(p_action)); + button->connect("pressed",this,"_custom_action",varray(p_action)); } return button; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index c29f6625d3..b7b2f061ea 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -187,6 +187,7 @@ void ItemList::select(int p_idx,bool p_single){ } current=p_idx; + ensure_selected_visible=false; } else { if (items[p_idx].selectable) { @@ -195,6 +196,7 @@ void ItemList::select(int p_idx,bool p_single){ } update(); + } void ItemList::unselect(int p_idx){ @@ -246,12 +248,14 @@ void ItemList::remove_item(int p_idx){ update(); shape_changed=true; + } void ItemList::clear(){ items.clear(); current=-1; + ensure_selected_visible=false; update(); } @@ -602,18 +606,8 @@ void ItemList::_input_event(const InputEvent& p_event) { void ItemList::ensure_current_is_visible() { - if (current>=0 && current <=items.size()) { - - Rect2 r = items[current].rect_cache; - int from = scroll_bar->get_val(); - int to = from + scroll_bar->get_page(); - - if (r.pos.y < from) { - scroll_bar->set_val(r.pos.y); - } else if (r.pos.y+r.size.y > to) { - scroll_bar->set_val(r.pos.y+r.size.y - (to-from)); - } - } + ensure_selected_visible=true; + update(); } void ItemList::_notification(int p_what) { @@ -928,6 +922,24 @@ void ItemList::_notification(int p_what) { draw_line(Vector2(bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),Vector2(size.width-bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),guide_color); } + + if (ensure_selected_visible && current>=0 && current <=items.size()) { + + Rect2 r = items[current].rect_cache; + int from = scroll_bar->get_val(); + int to = from + scroll_bar->get_page(); + + if (r.pos.y < from) { + scroll_bar->set_val(r.pos.y); + } else if (r.pos.y+r.size.y > to) { + scroll_bar->set_val(r.pos.y+r.size.y - (to-from)); + } + + + } + + ensure_selected_visible=false; + } } @@ -1095,6 +1107,7 @@ ItemList::ItemList() { set_focus_mode(FOCUS_ALL); current_columns=1; search_time_msec=0; + ensure_selected_visible=false; } diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index 237079c428..7cf58a6426 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -41,6 +41,8 @@ private: bool shape_changed; + bool ensure_selected_visible; + Vector<Item> items; Vector<int> separators; diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 68fcb4bda8..13ff7074ea 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -124,7 +124,7 @@ void MenuButton::_set_items(const Array& p_items) { void MenuButton::_bind_methods() { - ObjectTypeDB::bind_method(_MD("get_popup"),&MenuButton::get_popup); + ObjectTypeDB::bind_method(_MD("get_popup:PopupMenu"),&MenuButton::get_popup); ObjectTypeDB::bind_method(_MD("_unhandled_key_input"),&MenuButton::_unhandled_key_input); ObjectTypeDB::bind_method(_MD("_set_items"),&MenuButton::_set_items); ObjectTypeDB::bind_method(_MD("_get_items"),&MenuButton::_get_items); diff --git a/scene/gui/patch_9_frame.cpp b/scene/gui/patch_9_frame.cpp new file mode 100644 index 0000000000..b6e261714c --- /dev/null +++ b/scene/gui/patch_9_frame.cpp @@ -0,0 +1,132 @@ +#include "patch_9_frame.h" + +#include "servers/visual_server.h" + +void Patch9Frame::_notification(int p_what) { + + if (p_what==NOTIFICATION_DRAW) { + + if (texture.is_null()) + return; + + + Size2 s=get_size(); + RID ci = get_canvas_item(); + VS::get_singleton()->canvas_item_add_style_box(ci,Rect2(Point2(),s),texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center,modulate); +// draw_texture_rect(texture,Rect2(Point2(),s),false,modulate); + +/* + Vector<Point2> points; + points.resize(4); + points[0]=Point2(0,0); + points[1]=Point2(s.x,0); + points[2]=Point2(s.x,s.y); + points[3]=Point2(0,s.y); + Vector<Point2> uvs; + uvs.resize(4); + uvs[0]=Point2(0,0); + uvs[1]=Point2(1,0); + uvs[2]=Point2(1,1); + uvs[3]=Point2(0,1); + + VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector<Color>(),uvs,texture->get_rid()); +*/ + } +} + +Size2 Patch9Frame::get_minimum_size() const { + + return Size2(margin[MARGIN_LEFT]+margin[MARGIN_RIGHT],margin[MARGIN_TOP]+margin[MARGIN_BOTTOM]); +} +void Patch9Frame::_bind_methods() { + + + ObjectTypeDB::bind_method(_MD("set_texture","texture"), & Patch9Frame::set_texture ); + ObjectTypeDB::bind_method(_MD("get_texture"), & Patch9Frame::get_texture ); + ObjectTypeDB::bind_method(_MD("set_modulate","modulate"), & Patch9Frame::set_modulate ); + ObjectTypeDB::bind_method(_MD("get_modulate"), & Patch9Frame::get_modulate ); + ObjectTypeDB::bind_method(_MD("set_patch_margin","margin","value"), & Patch9Frame::set_patch_margin ); + ObjectTypeDB::bind_method(_MD("get_patch_margin","margin"), & Patch9Frame::get_patch_margin ); + ObjectTypeDB::bind_method(_MD("set_draw_center","draw_center"), & Patch9Frame::set_draw_center ); + ObjectTypeDB::bind_method(_MD("get_draw_center"), & Patch9Frame::get_draw_center ); + + ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") ); + ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate") ); + ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "draw_center"), _SCS("set_draw_center"),_SCS("get_draw_center") ); + ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/left",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_LEFT ); + ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/top",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_TOP ); + ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/right",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_RIGHT ); + ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/bottom",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_BOTTOM ); + +} + + +void Patch9Frame::set_texture(const Ref<Texture>& p_tex) { + + texture=p_tex; + update(); + //if (texture.is_valid()) + // texture->set_flags(texture->get_flags()&(~Texture::FLAG_REPEAT)); //remove repeat from texture, it looks bad in sprites + minimum_size_changed(); +} + +Ref<Texture> Patch9Frame::get_texture() const { + + return texture; +} + +void Patch9Frame::set_modulate(const Color& p_tex) { + + modulate=p_tex; + update(); +} + +Color Patch9Frame::get_modulate() const{ + + return modulate; +} + + +void Patch9Frame::set_patch_margin(Margin p_margin,int p_size) { + + ERR_FAIL_INDEX(p_margin,4); + margin[p_margin]=p_size; + update(); + minimum_size_changed(); +} + +int Patch9Frame::get_patch_margin(Margin p_margin) const{ + + ERR_FAIL_INDEX_V(p_margin,4,0); + return margin[p_margin]; +} + +void Patch9Frame::set_draw_center(bool p_draw) { + + draw_center=p_draw; + update(); +} + +bool Patch9Frame::get_draw_center() const{ + + return draw_center; +} + +Patch9Frame::Patch9Frame() { + + + margin[MARGIN_LEFT]=0; + margin[MARGIN_RIGHT]=0; + margin[MARGIN_BOTTOM]=0; + margin[MARGIN_TOP]=0; + modulate=Color(1,1,1,1); + set_ignore_mouse(true); + draw_center=true; +} + + +Patch9Frame::~Patch9Frame() +{ +} + + diff --git a/scene/gui/patch_9_frame.h b/scene/gui/patch_9_frame.h new file mode 100644 index 0000000000..562a5b1d77 --- /dev/null +++ b/scene/gui/patch_9_frame.h @@ -0,0 +1,40 @@ +#ifndef PATCH_9_FRAME_H +#define PATCH_9_FRAME_H + +#include "scene/gui/control.h" +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ +class Patch9Frame : public Control { + + OBJ_TYPE(Patch9Frame,Control); + + bool draw_center; + int margin[4]; + Color modulate; + Ref<Texture> texture; +protected: + + void _notification(int p_what); + virtual Size2 get_minimum_size() const; + static void _bind_methods(); + +public: + + void set_texture(const Ref<Texture>& p_tex); + Ref<Texture> get_texture() const; + + void set_modulate(const Color& p_tex); + Color get_modulate() const; + + void set_patch_margin(Margin p_margin,int p_size); + int get_patch_margin(Margin p_margin) const; + + void set_draw_center(bool p_enable); + bool get_draw_center() const; + + Patch9Frame(); + ~Patch9Frame(); + +}; +#endif // PATCH_9_FRAME_H diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 41e775bbff..a48136f541 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -27,7 +27,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "spin_box.h" - +#include "os/input.h" Size2 SpinBox::get_minimum_size() const { @@ -62,6 +62,13 @@ LineEdit *SpinBox::get_line_edit() { } +void SpinBox::_line_edit_input(const InputEvent& p_event) { + + + +} + + void SpinBox::_input_event(const InputEvent& p_event) { if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed) { @@ -94,6 +101,48 @@ void SpinBox::_input_event(const InputEvent& p_event) { } break; } } + + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) { + + //set_default_cursor_shape(CURSOR_VSIZE); + Vector2 cpos = Vector2(p_event.mouse_button.x,p_event.mouse_button.y); + drag.mouse_pos=cpos; + } + + if (p_event.type==InputEvent::MOUSE_BUTTON && !p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) { + + //set_default_cursor_shape(CURSOR_ARROW); + if (drag.enabled) { + drag.enabled=false; + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + warp_mouse(drag.capture_pos); + } + } + + if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_button.button_mask&1) { + + Vector2 cpos = Vector2(p_event.mouse_motion.x,p_event.mouse_motion.y); + if (drag.enabled) { + + float diff_y = drag.mouse_pos.y - cpos.y; + diff_y=Math::pow(ABS(diff_y),1.8)*SGN(diff_y); + diff_y*=0.1; + + drag.mouse_pos=cpos; + drag.base_val=CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max()); + + set_val( drag.base_val); + + } else if (drag.mouse_pos.distance_to(cpos)>2) { + + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); + drag.enabled=true; + drag.base_val=get_val(); + drag.mouse_pos=cpos; + drag.capture_pos=cpos; + + } + } } @@ -177,6 +226,7 @@ void SpinBox::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_editable"),&SpinBox::is_editable); ObjectTypeDB::bind_method(_MD("_line_edit_focus_exit"),&SpinBox::_line_edit_focus_exit); ObjectTypeDB::bind_method(_MD("get_line_edit"),&SpinBox::get_line_edit); + ObjectTypeDB::bind_method(_MD("_line_edit_input"),&SpinBox::_line_edit_input); ADD_PROPERTY(PropertyInfo(Variant::BOOL,"editable"),_SCS("set_editable"),_SCS("is_editable")); @@ -196,4 +246,6 @@ SpinBox::SpinBox() { //connect("value_changed",this,"_value_changed"); line_edit->connect("text_entered",this,"_text_entered",Vector<Variant>(),CONNECT_DEFERRED); line_edit->connect("focus_exit",this,"_line_edit_focus_exit",Vector<Variant>(),CONNECT_DEFERRED); + line_edit->connect("input_event",this,"_line_edit_input"); + drag.enabled=false; } diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index 6ebe14631e..4c8cb8432a 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -44,6 +44,18 @@ class SpinBox : public Range { String prefix; String suffix; + void _line_edit_input(const InputEvent& p_event); + + + struct Drag { + float base_val; + bool enabled; + Vector2 from; + Vector2 mouse_pos; + Vector2 capture_pos; + } drag; + + void _line_edit_focus_exit(); protected: diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 6c15f1cae4..e639b5cb05 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -31,7 +31,7 @@ #include "os/os.h" #include "os/keyboard.h" #include "globals.h" - +#include "os/input.h" @@ -70,6 +70,7 @@ Size2 TreeItem::Cell::get_icon_size() const { else return icon_region.size; } + void TreeItem::Cell::draw_icon(const RID& p_where, const Point2& p_pos, const Size2& p_size) const{ if (icon.is_null()) @@ -728,14 +729,20 @@ TreeItem::~TreeItem() { tree->root=0; } - if (tree && tree->popup_edited_item==this) + if (tree && tree->popup_edited_item==this) { tree->popup_edited_item=NULL; + tree->pressing_for_editor=false; + + } if (tree && tree->selected_item==this) tree->selected_item=NULL; - if (tree && tree->edited_item==this) + if (tree && tree->edited_item==this) { tree->edited_item=NULL; + tree->pressing_for_editor=false; + } + } @@ -1292,7 +1299,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col } else if (select_mode==SELECT_SINGLE || select_mode==SELECT_MULTI) { - if (&selected_cell==&c) { + if (!r_in_range && &selected_cell==&c) { if (!selected_cell.selected) { @@ -1301,6 +1308,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col selected_item=p_selected; selected_col=i; + emit_signal("cell_selected"); if (select_mode==SELECT_MULTI) emit_signal("multi_selected",p_current,i,true); @@ -1317,6 +1325,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col if (r_in_range && *r_in_range) { + if (!c.selected && c.selectable) { c.selected=true; emit_signal("multi_selected",p_current,i,true); @@ -1467,7 +1476,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ if (select_mode==SELECT_MULTI && p_mod.shift && selected_item && selected_item!=p_item) { bool inrange=false; - print_line("SELECT MULTI AND SHIFT AND ALL"); + select_single_item( p_item, root, col,selected_item,&inrange ); } else { select_single_item( p_item, root, col ); @@ -1490,7 +1499,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ /* editing */ - bool bring_up_editor=c.selected && already_selected; + bool bring_up_editor=c.selected;// && already_selected; bool bring_up_value_editor=false; String editor_text=c.text; @@ -1605,31 +1614,14 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ return -1; - click_handled=true; + + click_handled=true; popup_edited_item=p_item; popup_edited_item_col=col; - text_editor->set_pos(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset ); - text_editor->set_size( Size2(col_width,item_h)); - text_editor->clear(); - text_editor->set_text( editor_text ); - text_editor->select_all(); - if (bring_up_value_editor) { - - value_editor->set_pos(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset+Point2i(0,text_editor->get_size().height) ); - value_editor->set_size( Size2(col_width,1)); - value_editor->show_modal(); - updating_value_editor=true; - value_editor->set_min( c.min ); - value_editor->set_max( c.max ); - value_editor->set_step( c.step ); - value_editor->set_val( c.val ); - value_editor->set_exp_unit_value( c.expr ); - updating_value_editor=false; - } - - text_editor->show_modal(); - text_editor->grab_focus(); + pressing_item_rect=Rect2(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset,Size2(col_width,item_h)); + pressing_for_editor_text=editor_text; + pressing_for_editor=true; return -1; //select } else { @@ -2062,6 +2054,33 @@ void Tree::_input_event(InputEvent p_event) { update(); } + if (pressing_for_editor && popup_edited_item && popup_edited_item->get_cell_mode(popup_edited_item_col)==TreeItem::CELL_MODE_RANGE) { + //range drag + + if (!range_drag_enabled) { + + Vector2 cpos = Vector2(b.x,b.y); + if (cpos.distance_to(pressing_pos)>2) { + range_drag_enabled=true; + range_drag_capture_pos=cpos; + range_drag_base=popup_edited_item->get_range(popup_edited_item_col); + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); + } + } else { + + TreeItem::Cell &c=popup_edited_item->cells[popup_edited_item_col]; + float diff_y = -b.relative_y; + diff_y=Math::pow(ABS(diff_y),1.8)*SGN(diff_y); + diff_y*=0.1; + range_drag_base=CLAMP(range_drag_base + c.step * diff_y, c.min, c.max); + + popup_edited_item->set_range(popup_edited_item_col,range_drag_base); + item_edited(popup_edited_item_col,popup_edited_item); + + } + + } + if (drag_touching && ! drag_touching_deaccel) { @@ -2084,6 +2103,31 @@ void Tree::_input_event(InputEvent p_event) { if (b.button_index==BUTTON_LEFT) { + if (pressing_for_editor) { + + if (range_drag_enabled) { + + range_drag_enabled=false; + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + warp_mouse(range_drag_capture_pos); + } else { + text_editor->set_pos(pressing_item_rect.pos); + text_editor->set_size(pressing_item_rect.size); + + text_editor->clear(); + text_editor->set_text( pressing_for_editor_text ); + text_editor->select_all(); + + text_editor->show_modal(); + text_editor->grab_focus(); + + } + pressing_for_editor=false; + + } + + + if (cache.click_type==Cache::CLICK_BUTTON) { emit_signal("button_pressed",cache.click_item,cache.click_column,cache.click_id); @@ -2145,11 +2189,15 @@ void Tree::_input_event(InputEvent p_event) { break; click_handled=false; + pressing_for_editor=false; blocked++; bool handled = propagate_mouse_event(pos+cache.offset,0,0,b.doubleclick,root,b.button_index,b.mod); blocked--; + if (pressing_for_editor) { + pressing_pos=Point2(b.x,b.y); + } if (drag_touching) { @@ -2360,6 +2408,11 @@ void Tree::_notification(int p_what) { } } + if (p_what==NOTIFICATION_VISIBILITY_CHANGED) { + + drag_touching=false; + } + if (p_what==NOTIFICATION_ENTER_TREE) { update_cache();; @@ -2610,6 +2663,8 @@ void Tree::clear() { selected_item=NULL; edited_item=NULL; popup_edited_item=NULL; + selected_item=NULL; + pressing_for_editor=false; update(); }; @@ -3184,6 +3239,8 @@ Tree::Tree() { drag_speed=0; drag_touching=false; drag_touching_deaccel=false; + pressing_for_editor=false; + range_drag_enabled=false; } diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 8ddddd0630..3fbd7c95d9 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -258,7 +258,18 @@ friend class TreeItem; TreeItem *popup_edited_item; TreeItem *selected_item; TreeItem *edited_item; + + int pressed_button; + bool pressing_for_editor; + String pressing_for_editor_text; + Vector2 pressing_pos; + Rect2 pressing_item_rect; + + float range_drag_base; + bool range_drag_enabled; + Vector2 range_drag_capture_pos; + //TreeItem *cursor_item; //int cursor_column; diff --git a/scene/io/resource_format_image.cpp b/scene/io/resource_format_image.cpp index 8527498fc2..f67d50b56c 100644 --- a/scene/io/resource_format_image.cpp +++ b/scene/io/resource_format_image.cpp @@ -31,9 +31,11 @@ #include "io/image_loader.h" #include "globals.h" #include "os/os.h" -RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_original_path) { - +RES ResourceFormatLoaderImage::load(const String &p_path, const String& p_original_path, Error *r_error) { + if (r_error) + *r_error=ERR_CANT_OPEN; + if (p_path.extension()=="cube") { // open as cubemap txture @@ -83,6 +85,8 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina memdelete(f); cubemap->set_name(p_path.get_file()); + if (r_error) + *r_error=OK; return cubemap; @@ -112,6 +116,8 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina ERR_EXPLAIN("Failed loading image: "+p_path); ERR_FAIL_COND_V(err, RES()); + if (r_error) + *r_error=ERR_FILE_CORRUPT; #ifdef DEBUG_ENABLED #ifdef TOOLS_ENABLED @@ -199,6 +205,9 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina print_line(" -make texture: "+rtos(total)); } + if (r_error) + *r_error=OK; + return RES( texture ); } diff --git a/scene/io/resource_format_image.h b/scene/io/resource_format_image.h index 1af65870f8..b5ec5a1200 100644 --- a/scene/io/resource_format_image.h +++ b/scene/io/resource_format_image.h @@ -40,7 +40,7 @@ class ResourceFormatLoaderImage : public ResourceFormatLoader { int max_texture_size; public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/scene/io/resource_format_wav.cpp b/scene/io/resource_format_wav.cpp index 7c90a4b3cd..090348c933 100644 --- a/scene/io/resource_format_wav.cpp +++ b/scene/io/resource_format_wav.cpp @@ -31,13 +31,18 @@ #include "scene/resources/sample.h" -RES ResourceFormatLoaderWAV::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatLoaderWAV::load(const String &p_path, const String& p_original_path, Error *r_error) { + if (r_error) + *r_error=ERR_FILE_CANT_OPEN; Error err; FileAccess *file=FileAccess::open(p_path, FileAccess::READ,&err); ERR_FAIL_COND_V( err!=OK, RES() ); + if (r_error) + *r_error=ERR_FILE_CORRUPT; + /* CHECK RIFF */ char riff[5]; riff[4]=0; @@ -244,6 +249,9 @@ RES ResourceFormatLoaderWAV::load(const String &p_path,const String& p_original_ file->close(); memdelete(file); + if (r_error) + *r_error=OK; + return sample; } diff --git a/scene/io/resource_format_wav.h b/scene/io/resource_format_wav.h index 081a563d03..a74da041c1 100644 --- a/scene/io/resource_format_wav.h +++ b/scene/io/resource_format_wav.h @@ -33,7 +33,7 @@ class ResourceFormatLoaderWAV : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 717ed93b16..851de4a89f 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -52,6 +52,7 @@ #include "scene/gui/option_button.h" #include "scene/gui/color_picker.h" #include "scene/gui/texture_frame.h" +#include "scene/gui/patch_9_frame.h" #include "scene/gui/menu_button.h" #include "scene/gui/check_box.h" #include "scene/gui/check_button.h" @@ -302,6 +303,7 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init ObjectTypeDB::register_type<TextureFrame>(); + ObjectTypeDB::register_type<Patch9Frame>(); ObjectTypeDB::register_type<TabContainer>(); ObjectTypeDB::register_type<Tabs>(); ObjectTypeDB::register_virtual_type<Separator>(); @@ -456,7 +458,6 @@ void register_scene_types() { /* disable types by default, only editors should enable them */ - ObjectTypeDB::set_type_enabled("CollisionShape",false); //ObjectTypeDB::set_type_enabled("BodyVolumeSphere",false); //ObjectTypeDB::set_type_enabled("BodyVolumeBox",false); //ObjectTypeDB::set_type_enabled("BodyVolumeCapsule",false); @@ -490,9 +491,12 @@ void register_scene_types() { ObjectTypeDB::register_type<OccluderPolygon2D>(); ObjectTypeDB::register_type<YSort>(); ObjectTypeDB::register_type<BackBufferCopy>(); - - ObjectTypeDB::set_type_enabled("CollisionShape2D",false); - ObjectTypeDB::set_type_enabled("CollisionPolygon2D",false); + if (bool(GLOBAL_DEF("physics/remove_collision_helpers_at_runtime",false))) { + ObjectTypeDB::set_type_enabled("CollisionShape2D",false); + ObjectTypeDB::set_type_enabled("CollisionPolygon2D",false); + ObjectTypeDB::set_type_enabled("CollisionShape",false); + ObjectTypeDB::set_type_enabled("CollisionPolygon",false); + } OS::get_singleton()->yield(); //may take time to init @@ -576,7 +580,8 @@ void register_scene_types() { ObjectTypeDB::register_type<Sample>(); ObjectTypeDB::register_type<SampleLibrary>(); ObjectTypeDB::register_virtual_type<AudioStream>(); - ObjectTypeDB::register_type<AudioStreamGibberish>(); + ObjectTypeDB::register_virtual_type<AudioStreamPlayback>(); +// ObjectTypeDB::register_type<AudioStreamGibberish>(); ObjectTypeDB::register_virtual_type<VideoStream>(); OS::get_singleton()->yield(); //may take time to init diff --git a/scene/resources/audio_stream.cpp b/scene/resources/audio_stream.cpp index 7694b8ef79..569ed8620d 100644 --- a/scene/resources/audio_stream.cpp +++ b/scene/resources/audio_stream.cpp @@ -28,76 +28,34 @@ /*************************************************************************/ #include "audio_stream.h" +////////////////////////////// -int AudioStream::InternalAudioStream::get_channel_count() const { +void AudioStreamPlayback::_bind_methods() { - return owner->get_channel_count(); + ObjectTypeDB::bind_method(_MD("play","from_pos_sec"),&AudioStreamPlayback::play,DEFVAL(0)); + ObjectTypeDB::bind_method(_MD("stop"),&AudioStreamPlayback::stop); + ObjectTypeDB::bind_method(_MD("is_playing"),&AudioStreamPlayback::is_playing); -} - -void AudioStream::InternalAudioStream::set_mix_rate(int p_rate) { - - owner->_mix_rate=p_rate; -} - -bool AudioStream::InternalAudioStream::mix(int32_t *p_buffer,int p_frames) { - - return owner->mix(p_buffer,p_frames); -} - -bool AudioStream::InternalAudioStream::can_update_mt() const { + ObjectTypeDB::bind_method(_MD("set_loop","enabled"),&AudioStreamPlayback::set_loop); + ObjectTypeDB::bind_method(_MD("has_loop"),&AudioStreamPlayback::has_loop); - return owner->get_update_mode()==UPDATE_THREAD; -} + ObjectTypeDB::bind_method(_MD("get_loop_count"),&AudioStreamPlayback::get_loop_count); -void AudioStream::InternalAudioStream::update() { + ObjectTypeDB::bind_method(_MD("seek_pos","pos"),&AudioStreamPlayback::seek_pos); + ObjectTypeDB::bind_method(_MD("get_pos"),&AudioStreamPlayback::get_pos); - owner->update(); -} + ObjectTypeDB::bind_method(_MD("get_length"),&AudioStreamPlayback::get_length); + ObjectTypeDB::bind_method(_MD("get_channels"),&AudioStreamPlayback::get_channels); + ObjectTypeDB::bind_method(_MD("get_mix_rate"),&AudioStreamPlayback::get_mix_rate); + ObjectTypeDB::bind_method(_MD("get_minimum_buffer_size"),&AudioStreamPlayback::get_minimum_buffer_size); -AudioServer::AudioStream *AudioStream::get_audio_stream() { - return internal_audio_stream; } void AudioStream::_bind_methods() { - ObjectTypeDB::bind_method(_MD("play"),&AudioStream::play); - ObjectTypeDB::bind_method(_MD("stop"),&AudioStream::stop); - ObjectTypeDB::bind_method(_MD("is_playing"),&AudioStream::is_playing); - - ObjectTypeDB::bind_method(_MD("set_loop","enabled"),&AudioStream::set_loop); - ObjectTypeDB::bind_method(_MD("has_loop"),&AudioStream::has_loop); - - ObjectTypeDB::bind_method(_MD("get_stream_name"),&AudioStream::get_stream_name); - ObjectTypeDB::bind_method(_MD("get_loop_count"),&AudioStream::get_loop_count); - - ObjectTypeDB::bind_method(_MD("seek_pos","pos"),&AudioStream::seek_pos); - ObjectTypeDB::bind_method(_MD("get_pos"),&AudioStream::get_pos); - - ObjectTypeDB::bind_method(_MD("get_length"),&AudioStream::get_length); - - ObjectTypeDB::bind_method(_MD("get_update_mode"),&AudioStream::get_update_mode); - - ObjectTypeDB::bind_method(_MD("update"),&AudioStream::update); - - BIND_CONSTANT( UPDATE_NONE ); - BIND_CONSTANT( UPDATE_IDLE ); - BIND_CONSTANT( UPDATE_THREAD ); } -AudioStream::AudioStream() { - - _mix_rate=44100; - internal_audio_stream = memnew( InternalAudioStream ); - internal_audio_stream->owner=this; -} - - -AudioStream::~AudioStream() { - - memdelete(internal_audio_stream); -} diff --git a/scene/resources/audio_stream.h b/scene/resources/audio_stream.h index df33b64a4b..b16e62b8c7 100644 --- a/scene/resources/audio_stream.h +++ b/scene/resources/audio_stream.h @@ -31,72 +31,53 @@ #include "resource.h" #include "servers/audio_server.h" -#include "scene/resources/audio_stream.h" - -class AudioStream : public Resource { - - OBJ_TYPE( AudioStream, Resource ); - OBJ_SAVE_TYPE( AudioStream ); //children are all saved as AudioStream, so they can be exchanged - - friend class InternalAudioStream; - - struct InternalAudioStream : public AudioServer::AudioStream { - - ::AudioStream *owner; - virtual int get_channel_count() const; - virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate - virtual bool mix(int32_t *p_buffer,int p_frames); - virtual bool can_update_mt() const; - virtual void update(); - }; +class AudioStreamPlayback : public Reference { - int _mix_rate; - InternalAudioStream *internal_audio_stream; + OBJ_TYPE( AudioStreamPlayback, Reference ); protected: - - _FORCE_INLINE_ int get_mix_rate() const { return _mix_rate; } - virtual int get_channel_count() const=0; - virtual bool mix(int32_t *p_buffer, int p_frames)=0; - static void _bind_methods(); public: - enum UpdateMode { - UPDATE_NONE, - UPDATE_IDLE, - UPDATE_THREAD - }; - AudioServer::AudioStream *get_audio_stream(); - - virtual void play()=0; + virtual void play(float p_from_pos=0)=0; virtual void stop()=0; virtual bool is_playing() const=0; - virtual void set_paused(bool p_paused)=0; - virtual bool is_paused(bool p_paused) const=0; - virtual void set_loop(bool p_enable)=0; virtual bool has_loop() const=0; - virtual float get_length() const=0; - - virtual String get_stream_name() const=0; + virtual void set_loop_restart_time(float p_time)=0; virtual int get_loop_count() const=0; virtual float get_pos() const=0; virtual void seek_pos(float p_time)=0; - virtual UpdateMode get_update_mode() const=0; - virtual void update()=0; + virtual int mix(int16_t* p_bufer,int p_frames)=0; + + virtual float get_length() const=0; + virtual String get_stream_name() const=0; + + virtual int get_channels() const=0; + virtual int get_mix_rate() const=0; + virtual int get_minimum_buffer_size() const=0; - AudioStream(); - ~AudioStream(); }; +class AudioStream : public Resource { + + OBJ_TYPE( AudioStream, Resource ); + OBJ_SAVE_TYPE( AudioStream ); //children are all saved as AudioStream, so they can be exchanged + +protected: + static void _bind_methods(); +public: + + virtual Ref<AudioStreamPlayback> instance_playback()=0; + + +}; -VARIANT_ENUM_CAST( AudioStream::UpdateMode ); #endif // AUDIO_STREAM_H diff --git a/scene/resources/audio_stream_resampled.cpp b/scene/resources/audio_stream_resampled.cpp index 6317780bd3..edbca60bd3 100644 --- a/scene/resources/audio_stream_resampled.cpp +++ b/scene/resources/audio_stream_resampled.cpp @@ -28,6 +28,9 @@ /*************************************************************************/ #include "audio_stream_resampled.h" #include "globals.h" + + +#if 0 int AudioStreamResampled::get_channel_count() const { if (!rb) @@ -382,3 +385,4 @@ AudioStreamResampled::~AudioStreamResampled() { } +#endif diff --git a/scene/resources/audio_stream_resampled.h b/scene/resources/audio_stream_resampled.h index 33cfb17e3f..570c311878 100644 --- a/scene/resources/audio_stream_resampled.h +++ b/scene/resources/audio_stream_resampled.h @@ -31,6 +31,7 @@ #include "scene/resources/audio_stream.h" +#if 0 class AudioStreamResampled : public AudioStream { OBJ_TYPE(AudioStreamResampled,AudioStream); @@ -160,5 +161,5 @@ public: AudioStreamResampled(); ~AudioStreamResampled(); }; - +#endif #endif // AUDIO_STREAM_RESAMPLED_H diff --git a/scene/resources/bit_mask.cpp b/scene/resources/bit_mask.cpp index ef056a6230..9a6452797a 100644 --- a/scene/resources/bit_mask.cpp +++ b/scene/resources/bit_mask.cpp @@ -205,7 +205,10 @@ BitMap::BitMap() { ////////////////////////////////////// -RES ResourceFormatLoaderBitMap::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatLoaderBitMap::load(const String &p_path, const String& p_original_path, Error *r_error) { + + if (r_error) + *r_error=ERR_FILE_CANT_OPEN; BitMap* ptr = memnew(BitMap); Ref<BitMap> bitmap( ptr ); @@ -219,6 +222,8 @@ RES ResourceFormatLoaderBitMap::load(const String &p_path,const String& p_origin ERR_FAIL_COND_V(err, RES()); bitmap->create_from_image_alpha(image); + if (r_error) + *r_error=OK; return bitmap; diff --git a/scene/resources/bit_mask.h b/scene/resources/bit_mask.h index 29b7bc66f4..a6b29bb919 100644 --- a/scene/resources/bit_mask.h +++ b/scene/resources/bit_mask.h @@ -66,7 +66,7 @@ class ResourceFormatLoaderBitMap : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index cd0e67f04d..f1e97fd626 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -297,7 +297,7 @@ void make_default_theme() { t->set_color("font_color_hover","MenuButton", control_font_color_hover ); t->set_color("font_color_disabled","MenuButton", Color(1,1,1,0.3) ); - t->set_constant("hseparation","MenuButton", 0 ); + t->set_constant("hseparation","MenuButton", 3 ); // CheckBox diff --git a/scene/resources/gibberish_stream.cpp b/scene/resources/gibberish_stream.cpp index 23b94c8f38..7af81bd992 100644 --- a/scene/resources/gibberish_stream.cpp +++ b/scene/resources/gibberish_stream.cpp @@ -29,6 +29,8 @@ #include "gibberish_stream.h" #include "servers/audio_server.h" +#if 0 + int AudioStreamGibberish::get_channel_count() const { return 1; @@ -328,3 +330,4 @@ AudioStreamGibberish::AudioStreamGibberish() { paused=false; active_voices=0; } +#endif diff --git a/scene/resources/gibberish_stream.h b/scene/resources/gibberish_stream.h index a52e629f83..77393db9f4 100644 --- a/scene/resources/gibberish_stream.h +++ b/scene/resources/gibberish_stream.h @@ -29,7 +29,7 @@ #ifndef GIBBERISH_STREAM_H #define GIBBERISH_STREAM_H - +#if 0 #include "scene/resources/audio_stream.h" #include "scene/resources/sample_library.h" class AudioStreamGibberish : public AudioStream { @@ -109,4 +109,6 @@ public: AudioStreamGibberish(); }; +#endif + #endif // GIBBERISH_STREAM_H diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 90598ee789..a9376faf62 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -219,7 +219,10 @@ Shader::~Shader() { -RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatLoaderShader::load(const String &p_path, const String& p_original_path, Error *r_error) { + + if (r_error) + *r_error=ERR_FILE_CANT_OPEN; String fragment_code; String vertex_code; @@ -235,6 +238,8 @@ RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_origin ERR_FAIL_COND_V(err,RES()); String base_path = p_path.get_base_dir(); + if (r_error) + *r_error=ERR_FILE_CORRUPT; Ref<Shader> shader;//( memnew( Shader ) ); @@ -435,6 +440,8 @@ RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_origin f->close(); memdelete(f); + if (r_error) + *r_error=OK; return shader; } diff --git a/scene/resources/shader.h b/scene/resources/shader.h index b805cbec96..61a369c408 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -126,7 +126,7 @@ public: class ResourceFormatLoaderShader : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index 3060fe41b4..651e234b49 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -601,7 +601,9 @@ Theme::~Theme() -RES ResourceFormatLoaderTheme::load(const String &p_path,const String& p_original_path) { +RES ResourceFormatLoaderTheme::load(const String &p_path, const String& p_original_path, Error *r_error) { + if (r_error) + *r_error=ERR_CANT_OPEN; Error err; FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); @@ -611,6 +613,8 @@ RES ResourceFormatLoaderTheme::load(const String &p_path,const String& p_origina String base_path = p_path.get_base_dir(); Ref<Theme> theme( memnew( Theme ) ); Map<StringName,Variant> library; + if (r_error) + *r_error=ERR_FILE_CORRUPT; bool reading_library=false; int line=0; @@ -1003,6 +1007,9 @@ RES ResourceFormatLoaderTheme::load(const String &p_path,const String& p_origina f->close(); memdelete(f); + if (r_error) + *r_error=OK; + return theme; } diff --git a/scene/resources/theme.h b/scene/resources/theme.h index 802dcb099c..cfa0762595 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -124,7 +124,7 @@ public: class ResourceFormatLoaderTheme : public ResourceFormatLoader { public: - virtual RES load(const String &p_path,const String& p_original_path=""); + virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String& p_type) const; virtual String get_resource_type(const String &p_path) const; |