summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/canvas_item.cpp9
-rw-r--r--scene/2d/canvas_item.h7
-rw-r--r--scene/2d/collision_polygon_2d.cpp84
-rw-r--r--scene/2d/collision_polygon_2d.h12
-rw-r--r--scene/2d/collision_shape_2d.cpp64
-rw-r--r--scene/2d/collision_shape_2d.h8
-rw-r--r--scene/2d/sprite.cpp4
-rw-r--r--scene/3d/area.cpp33
-rw-r--r--scene/3d/area.h10
-rw-r--r--scene/3d/body_shape.cpp75
-rw-r--r--scene/3d/body_shape.h14
-rw-r--r--scene/3d/collision_polygon.cpp106
-rw-r--r--scene/3d/collision_polygon.h12
-rw-r--r--scene/3d/physics_body.cpp55
-rw-r--r--scene/3d/physics_body.h14
-rw-r--r--scene/3d/spatial.cpp25
-rw-r--r--scene/3d/spatial.h5
-rw-r--r--scene/3d/spatial_stream_player.cpp288
-rw-r--r--scene/3d/spatial_stream_player.h56
-rw-r--r--scene/3d/sprite_3d.cpp4
-rw-r--r--scene/animation/animation_player.cpp6
-rw-r--r--scene/animation/animation_player.h1
-rw-r--r--scene/audio/stream_player.cpp170
-rw-r--r--scene/audio/stream_player.h33
-rw-r--r--scene/gui/dialogs.cpp2
-rw-r--r--scene/gui/item_list.cpp37
-rw-r--r--scene/gui/item_list.h2
-rw-r--r--scene/gui/menu_button.cpp2
-rw-r--r--scene/gui/patch_9_frame.cpp132
-rw-r--r--scene/gui/patch_9_frame.h40
-rw-r--r--scene/gui/spin_box.cpp54
-rw-r--r--scene/gui/spin_box.h12
-rw-r--r--scene/gui/tree.cpp113
-rw-r--r--scene/gui/tree.h11
-rw-r--r--scene/io/resource_format_image.cpp13
-rw-r--r--scene/io/resource_format_image.h2
-rw-r--r--scene/io/resource_format_wav.cpp10
-rw-r--r--scene/io/resource_format_wav.h2
-rw-r--r--scene/register_scene_types.cpp15
-rw-r--r--scene/resources/audio_stream.cpp70
-rw-r--r--scene/resources/audio_stream.h69
-rw-r--r--scene/resources/audio_stream_resampled.cpp4
-rw-r--r--scene/resources/audio_stream_resampled.h3
-rw-r--r--scene/resources/bit_mask.cpp7
-rw-r--r--scene/resources/bit_mask.h2
-rw-r--r--scene/resources/default_theme/default_theme.cpp2
-rw-r--r--scene/resources/gibberish_stream.cpp3
-rw-r--r--scene/resources/gibberish_stream.h4
-rw-r--r--scene/resources/shader.cpp9
-rw-r--r--scene/resources/shader.h2
-rw-r--r--scene/resources/theme.cpp9
-rw-r--r--scene/resources/theme.h2
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;