From 473c7222f512488bfea3674358e15cac83d41ffb Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 19 Mar 2015 14:10:07 +0000 Subject: [PATCH 01/49] Calculate gravity based on distance from body to gravity point --- scene/3d/area.cpp | 17 ++++++++++++++++- scene/3d/area.h | 4 ++++ servers/physics/area_sw.cpp | 3 +++ servers/physics/area_sw.h | 4 ++++ servers/physics/body_sw.cpp | 9 ++++++--- servers/physics_server.cpp | 1 + servers/physics_server.h | 1 + 7 files changed, 35 insertions(+), 4 deletions(-) diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index d49ffff729b..bcc58c700a3 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -42,7 +42,6 @@ Area::SpaceOverride Area::get_space_override_mode() const{ } void Area::set_gravity_is_point(bool p_enabled){ - gravity_is_point=p_enabled; PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT,p_enabled); @@ -52,6 +51,17 @@ bool Area::is_gravity_a_point() const{ return gravity_is_point; } +void Area::set_gravity_distance_scale(real_t p_scale){ + + gravity_distance_scale=p_scale; + PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE,p_scale); + +} + +real_t Area::get_gravity_distance_scale() const{ + return gravity_distance_scale; +} + void Area::set_gravity_vector(const Vector3& p_vec){ gravity_vec=p_vec; @@ -302,6 +312,9 @@ void Area::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_gravity_is_point","enable"),&Area::set_gravity_is_point); ObjectTypeDB::bind_method(_MD("is_gravity_a_point"),&Area::is_gravity_a_point); + ObjectTypeDB::bind_method(_MD("set_gravity_distance_scale","distance_scale"),&Area::set_gravity_distance_scale); + ObjectTypeDB::bind_method(_MD("get_gravity_distance_scale"),&Area::get_gravity_distance_scale); + ObjectTypeDB::bind_method(_MD("set_gravity_vector","vector"),&Area::set_gravity_vector); ObjectTypeDB::bind_method(_MD("get_gravity_vector"),&Area::get_gravity_vector); @@ -330,6 +343,7 @@ void Area::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::INT,"space_override",PROPERTY_HINT_ENUM,"Disabled,Combine,Replace"),_SCS("set_space_override_mode"),_SCS("get_space_override_mode")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gravity_point"),_SCS("set_gravity_is_point"),_SCS("is_gravity_a_point")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_distance_scale", PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_gravity_distance_scale"),_SCS("get_gravity_distance_scale")); 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")); @@ -345,6 +359,7 @@ Area::Area() : CollisionObject(PhysicsServer::get_singleton()->area_create(),tru locked=false; set_gravity_vector(Vector3(0,-1,0)); gravity_is_point=false; + gravity_distance_scale=0; density=0.1; priority=0; monitoring=false; diff --git a/scene/3d/area.h b/scene/3d/area.h index 493c71c5955..fb853092f36 100644 --- a/scene/3d/area.h +++ b/scene/3d/area.h @@ -49,6 +49,7 @@ private: Vector3 gravity_vec; real_t gravity; bool gravity_is_point; + real_t gravity_distance_scale; real_t density; int priority; bool monitoring; @@ -98,6 +99,9 @@ public: void set_gravity_is_point(bool p_enabled); bool is_gravity_a_point() const; + void set_gravity_distance_scale(real_t p_scale); + real_t get_gravity_distance_scale() const; + void set_gravity_vector(const Vector3& p_vec); Vector3 get_gravity_vector() const; diff --git a/servers/physics/area_sw.cpp b/servers/physics/area_sw.cpp index de241c948b2..aa1c530221b 100644 --- a/servers/physics/area_sw.cpp +++ b/servers/physics/area_sw.cpp @@ -98,6 +98,7 @@ void AreaSW::set_param(PhysicsServer::AreaParameter p_param, const Variant& p_va case PhysicsServer::AREA_PARAM_GRAVITY: gravity=p_value; ; break; case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector=p_value; ; break; case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; ; break; + case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; ; break; case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; ; break; case PhysicsServer::AREA_PARAM_DENSITY: density=p_value; ; break; case PhysicsServer::AREA_PARAM_PRIORITY: priority=p_value; ; break; @@ -113,6 +114,7 @@ Variant AreaSW::get_param(PhysicsServer::AreaParameter p_param) const { case PhysicsServer::AREA_PARAM_GRAVITY: return gravity; case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: return gravity_vector; case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; + case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return gravity_distance_scale; case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; case PhysicsServer::AREA_PARAM_DENSITY: return density; case PhysicsServer::AREA_PARAM_PRIORITY: return priority; @@ -177,6 +179,7 @@ AreaSW::AreaSW() : CollisionObjectSW(TYPE_AREA), monitor_query_list(this), move gravity=9.80665; gravity_vector=Vector3(0,-1,0); gravity_is_point=false; + gravity_distance_scale=0; point_attenuation=1; density=0.1; priority=0; diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h index 87843b93c92..a875472f6ba 100644 --- a/servers/physics/area_sw.h +++ b/servers/physics/area_sw.h @@ -45,6 +45,7 @@ class AreaSW : public CollisionObjectSW{ float gravity; Vector3 gravity_vector; bool gravity_is_point; + float gravity_distance_scale; float point_attenuation; float density; int priority; @@ -125,6 +126,9 @@ public: _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point=p_enable; } _FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; } + _FORCE_INLINE_ void set_gravity_distance_scale(float scale) { gravity_distance_scale=scale; } + _FORCE_INLINE_ float get_gravity_distance_scale() const { return gravity_distance_scale; } + _FORCE_INLINE_ void set_point_attenuation(float p_point_attenuation) { point_attenuation=p_point_attenuation; } _FORCE_INLINE_ float get_point_attenuation() const { return point_attenuation; } diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index 1cc0b763a44..5a528ecf94d 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -362,9 +362,12 @@ void BodySW::set_space(SpaceSW *p_space){ void BodySW::_compute_area_gravity(const AreaSW *p_area) { if (p_area->is_gravity_point()) { - - gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity(); - + if(p_area->get_gravity_distance_scale() > 0) { + Vector3 v = p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin(); + gravity += v.normalized() * (p_area->get_gravity() / Math::pow(v.length() * p_area->get_gravity_distance_scale()+1, 2) ); + } else { + gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity(); + } } else { gravity += p_area->get_gravity_vector() * p_area->get_gravity(); } diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index 4feb1b5269d..e02601af416 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -681,6 +681,7 @@ void PhysicsServer::_bind_methods() { BIND_CONSTANT( AREA_PARAM_GRAVITY ); BIND_CONSTANT( AREA_PARAM_GRAVITY_VECTOR ); BIND_CONSTANT( AREA_PARAM_GRAVITY_IS_POINT ); + BIND_CONSTANT( AREA_PARAM_GRAVITY_DISTANCE_SCALE ); BIND_CONSTANT( AREA_PARAM_GRAVITY_POINT_ATTENUATION ); BIND_CONSTANT( AREA_PARAM_DENSITY ); BIND_CONSTANT( AREA_PARAM_PRIORITY ); diff --git a/servers/physics_server.h b/servers/physics_server.h index ffb462af22a..05b64da8048 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -298,6 +298,7 @@ public: AREA_PARAM_GRAVITY, AREA_PARAM_GRAVITY_VECTOR, AREA_PARAM_GRAVITY_IS_POINT, + AREA_PARAM_GRAVITY_DISTANCE_SCALE, AREA_PARAM_GRAVITY_POINT_ATTENUATION, AREA_PARAM_DENSITY, AREA_PARAM_PRIORITY From 590afbcac461f87b05391996ca85d32627c81a75 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Wed, 29 Apr 2015 16:06:25 +0000 Subject: [PATCH 02/49] Calculate gravity based on distance from body to gravity point (2D) --- scene/2d/area_2d.cpp | 16 ++++++++++++++++ scene/2d/area_2d.h | 4 ++++ scene/3d/area.cpp | 1 + servers/physics_2d/area_2d_sw.cpp | 3 +++ servers/physics_2d/area_2d_sw.h | 4 ++++ servers/physics_2d/body_2d_sw.cpp | 9 ++++++--- servers/physics_2d_server.cpp | 1 + servers/physics_2d_server.h | 1 + 8 files changed, 36 insertions(+), 3 deletions(-) diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 827256c2fa5..e16cf85a5b8 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -52,6 +52,17 @@ bool Area2D::is_gravity_a_point() const{ return gravity_is_point; } +void Area2D::set_gravity_distance_scale(real_t p_scale){ + + gravity_distance_scale=p_scale; + Physics2DServer::get_singleton()->area_set_param(get_rid(),Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE,p_scale); + +} + +real_t Area2D::get_gravity_distance_scale() const{ + return gravity_distance_scale; +} + void Area2D::set_gravity_vector(const Vector2& p_vec){ gravity_vec=p_vec; @@ -550,6 +561,9 @@ void Area2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_gravity_is_point","enable"),&Area2D::set_gravity_is_point); ObjectTypeDB::bind_method(_MD("is_gravity_a_point"),&Area2D::is_gravity_a_point); + ObjectTypeDB::bind_method(_MD("set_gravity_distance_scale","distance_scale"),&Area2D::set_gravity_distance_scale); + ObjectTypeDB::bind_method(_MD("get_gravity_distance_scale"),&Area2D::get_gravity_distance_scale); + ObjectTypeDB::bind_method(_MD("set_gravity_vector","vector"),&Area2D::set_gravity_vector); ObjectTypeDB::bind_method(_MD("get_gravity_vector"),&Area2D::get_gravity_vector); @@ -600,6 +614,7 @@ void Area2D::_bind_methods() { ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"space_override",PROPERTY_HINT_ENUM,"Disabled,Combine,Replace"),_SCS("set_space_override_mode"),_SCS("get_space_override_mode")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gravity_point"),_SCS("set_gravity_is_point"),_SCS("is_gravity_a_point")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_distance_scale", PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_gravity_distance_scale"),_SCS("get_gravity_distance_scale")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"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,"linear_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_linear_damp"),_SCS("get_linear_damp")); @@ -618,6 +633,7 @@ Area2D::Area2D() : CollisionObject2D(Physics2DServer::get_singleton()->area_crea set_gravity(98);; set_gravity_vector(Vector2(0,1)); gravity_is_point=false; + gravity_distance_scale=0; linear_damp=0.1; angular_damp=1; locked=false; diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index 0c064f54cd7..704ad0a5921 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -49,6 +49,7 @@ private: Vector2 gravity_vec; real_t gravity; bool gravity_is_point; + real_t gravity_distance_scale; real_t linear_damp; real_t angular_damp; uint32_t collision_mask; @@ -132,6 +133,9 @@ public: void set_gravity_is_point(bool p_enabled); bool is_gravity_a_point() const; + void set_gravity_distance_scale(real_t p_scale); + real_t get_gravity_distance_scale() const; + void set_gravity_vector(const Vector2& p_vec); Vector2 get_gravity_vector() const; diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index bcc58c700a3..76527c72e65 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -42,6 +42,7 @@ Area::SpaceOverride Area::get_space_override_mode() const{ } void Area::set_gravity_is_point(bool p_enabled){ + gravity_is_point=p_enabled; PhysicsServer::get_singleton()->area_set_param(get_rid(),PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT,p_enabled); diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp index dad1891b77f..1a41cda4829 100644 --- a/servers/physics_2d/area_2d_sw.cpp +++ b/servers/physics_2d/area_2d_sw.cpp @@ -120,6 +120,7 @@ void Area2DSW::set_param(Physics2DServer::AreaParameter p_param, const Variant& case Physics2DServer::AREA_PARAM_GRAVITY: gravity=p_value; ; break; case Physics2DServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector=p_value; ; break; case Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; ; break; + case Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; ; break; case Physics2DServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; ; break; case Physics2DServer::AREA_PARAM_LINEAR_DAMP: linear_damp=p_value; ; break; case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: angular_damp=p_value; ; break; @@ -136,6 +137,7 @@ Variant Area2DSW::get_param(Physics2DServer::AreaParameter p_param) const { case Physics2DServer::AREA_PARAM_GRAVITY: return gravity; case Physics2DServer::AREA_PARAM_GRAVITY_VECTOR: return gravity_vector; case Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; + case Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return gravity_distance_scale; case Physics2DServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; case Physics2DServer::AREA_PARAM_LINEAR_DAMP: return linear_damp; case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: return angular_damp; @@ -248,6 +250,7 @@ Area2DSW::Area2DSW() : CollisionObject2DSW(TYPE_AREA), monitor_query_list(this), gravity=9.80665; gravity_vector=Vector2(0,-1); gravity_is_point=false; + gravity_distance_scale=0; point_attenuation=1; angular_damp=1.0; diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h index 4a54a337ed3..6d99764c680 100644 --- a/servers/physics_2d/area_2d_sw.h +++ b/servers/physics_2d/area_2d_sw.h @@ -46,6 +46,7 @@ class Area2DSW : public CollisionObject2DSW{ float gravity; Vector2 gravity_vector; bool gravity_is_point; + float gravity_distance_scale; float point_attenuation; float linear_damp; float angular_damp; @@ -139,6 +140,9 @@ public: _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point=p_enable; } _FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; } + _FORCE_INLINE_ void set_gravity_distance_scale(float scale) { gravity_distance_scale=scale; } + _FORCE_INLINE_ float get_gravity_distance_scale() const { return gravity_distance_scale; } + _FORCE_INLINE_ void set_point_attenuation(float p_point_attenuation) { point_attenuation=p_point_attenuation; } _FORCE_INLINE_ float get_point_attenuation() const { return point_attenuation; } diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index ccce058f136..38835c9a82e 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -383,9 +383,12 @@ void Body2DSW::set_space(Space2DSW *p_space){ void Body2DSW::_compute_area_gravity(const Area2DSW *p_area) { if (p_area->is_gravity_point()) { - - gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity(); - + if(p_area->get_gravity_distance_scale() > 0) { + Vector2 v = p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin(); + gravity += v.normalized() * (p_area->get_gravity() / Math::pow(v.length() * p_area->get_gravity_distance_scale()+1, 2) ); + } else { + gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity(); + } } else { gravity += p_area->get_gravity_vector() * p_area->get_gravity(); } diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index 279ad0d7421..8db7ae11617 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -657,6 +657,7 @@ void Physics2DServer::_bind_methods() { BIND_CONSTANT( AREA_PARAM_GRAVITY ); BIND_CONSTANT( AREA_PARAM_GRAVITY_VECTOR ); BIND_CONSTANT( AREA_PARAM_GRAVITY_IS_POINT ); + BIND_CONSTANT( AREA_PARAM_GRAVITY_DISTANCE_SCALE ); BIND_CONSTANT( AREA_PARAM_GRAVITY_POINT_ATTENUATION ); BIND_CONSTANT( AREA_PARAM_LINEAR_DAMP); BIND_CONSTANT( AREA_PARAM_ANGULAR_DAMP); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 5411228c0fd..e7694aa2fd0 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -306,6 +306,7 @@ public: AREA_PARAM_GRAVITY, AREA_PARAM_GRAVITY_VECTOR, AREA_PARAM_GRAVITY_IS_POINT, + AREA_PARAM_GRAVITY_DISTANCE_SCALE, AREA_PARAM_GRAVITY_POINT_ATTENUATION, AREA_PARAM_LINEAR_DAMP, AREA_PARAM_ANGULAR_DAMP, From 93e797f1649cfbdd5748956feb245ee27c75c996 Mon Sep 17 00:00:00 2001 From: romulox_x Date: Sat, 23 May 2015 03:17:52 -0700 Subject: [PATCH 03/49] Fixed null pointer bug in ios store. added functions to game center to reset the user's achievements, request all the achievements they've made progress on, request descriptions of all possible achievements, and show the built in game center overlay. Upgraded all (I think) deprecated functions to ios 6 versions. as per discussion with reduz on IRC, ios 6 is now the official lowest supported iOS version. compatibility could be added, but it's so obsolete, it's tough to argue for continuing to support it. some naming of functions and dictionary parameters might need to change. I just named them whatever made sense to me :) --- platform/iphone/game_center.h | 4 + platform/iphone/game_center.mm | 212 ++++++++++++++++++++++++++--- platform/iphone/in_app_store.mm | 2 +- platform/iphone/view_controller.h | 3 +- platform/iphone/view_controller.mm | 6 +- 5 files changed, 208 insertions(+), 19 deletions(-) diff --git a/platform/iphone/game_center.h b/platform/iphone/game_center.h index 1f4820a3c28..4fe13db8fcc 100644 --- a/platform/iphone/game_center.h +++ b/platform/iphone/game_center.h @@ -51,6 +51,10 @@ public: Error post_score(Variant p_score); Error award_achievement(Variant p_params); + void reset_achievements(); + void request_achievements(); + void request_achievement_descriptions(); + Error show_game_center(Variant p_params); int get_pending_event_count(); Variant pop_pending_event(); diff --git a/platform/iphone/game_center.mm b/platform/iphone/game_center.mm index fd1e5f3be77..a0585366852 100644 --- a/platform/iphone/game_center.mm +++ b/platform/iphone/game_center.mm @@ -32,6 +32,7 @@ extern "C" { #import +#import "app_delegate.h" }; GameCenter* GameCenter::instance = NULL; @@ -42,6 +43,10 @@ void GameCenter::_bind_methods() { ObjectTypeDB::bind_method(_MD("post_score"),&GameCenter::post_score); ObjectTypeDB::bind_method(_MD("award_achievement"),&GameCenter::award_achievement); + ObjectTypeDB::bind_method(_MD("reset_achievements"),&GameCenter::reset_achievements); + ObjectTypeDB::bind_method(_MD("request_achievements"),&GameCenter::request_achievements); + ObjectTypeDB::bind_method(_MD("request_achievement_descriptions"),&GameCenter::request_achievement_descriptions); + ObjectTypeDB::bind_method(_MD("show_game_center"),&GameCenter::show_game_center); ObjectTypeDB::bind_method(_MD("get_pending_event_count"),&GameCenter::get_pending_event_count); ObjectTypeDB::bind_method(_MD("pop_pending_event"),&GameCenter::pop_pending_event); @@ -50,23 +55,41 @@ void GameCenter::_bind_methods() { Error GameCenter::connect() { + //if this class isn't available, game center isn't implemented + if ((NSClassFromString(@"GKLocalPlayer")) == nil) { + GameCenter::get_singleton()->connected = false; + return ERR_UNAVAILABLE; + } + GKLocalPlayer* player = [GKLocalPlayer localPlayer]; - [player authenticateWithCompletionHandler:^(NSError* error) { + ERR_FAIL_COND_V(![player respondsToSelector:@selector(authenticateHandler)], ERR_UNAVAILABLE); - Dictionary ret; - ret["type"] = "authentication"; - if (player.isAuthenticated) { - ret["result"] = "ok"; - GameCenter::get_singleton()->connected = true; - } else { - ret["result"] = "error"; - ret["error_code"] = error.code; - ret["error_description"] = [error.localizedDescription UTF8String]; - GameCenter::get_singleton()->connected = false; - }; + ViewController *root_controller=(ViewController *)((AppDelegate *)[[UIApplication sharedApplication] delegate]).window.rootViewController; + ERR_FAIL_COND_V(!root_controller, FAILED); + + //this handler is called serveral times. first when the view needs to be shown, then again after the view is cancelled or the user logs in. or if the user's already logged in, it's called just once to confirm they're authenticated. This is why no result needs to be specified in the presentViewController phase. in this case, more calls to this function will follow. + player.authenticateHandler = (^(UIViewController *controller, NSError *error) { + if (controller) { + [root_controller presentViewController:controller animated:YES completion:nil]; + } + else { + Dictionary ret; + ret["type"] = "authentication"; + if (player.isAuthenticated) { + ret["result"] = "ok"; + GameCenter::get_singleton()->connected = true; + } else { + ret["result"] = "error"; + ret["error_code"] = error.code; + ret["error_description"] = [error.localizedDescription UTF8String]; + GameCenter::get_singleton()->connected = false; + }; + + pending_events.push_back(ret); + }; + + }); - pending_events.push_back(ret); - }]; return OK; }; @@ -85,7 +108,9 @@ Error GameCenter::post_score(Variant p_score) { GKScore* reporter = [[[GKScore alloc] initWithCategory:cat_str] autorelease]; reporter.value = score; - [reporter reportScoreWithCompletionHandler:^(NSError* error) { + ERR_FAIL_COND_V([GKScore respondsToSelector:@selector(reportScores)], ERR_UNAVAILABLE); + + [GKScore reportScores:@[reporter] withCompletionHandler:^(NSError* error) { Dictionary ret; ret["type"] = "post_score"; @@ -114,8 +139,15 @@ Error GameCenter::award_achievement(Variant p_params) { GKAchievement* achievement = [[[GKAchievement alloc] initWithIdentifier: name_str] autorelease]; ERR_FAIL_COND_V(!achievement, FAILED); + ERR_FAIL_COND_V([GKAchievement respondsToSelector:@selector(reportAchievements)], ERR_UNAVAILABLE); + achievement.percentComplete = progress; - [achievement reportAchievementWithCompletionHandler:^(NSError* error) { + achievement.showsCompletionBanner = NO; + if (params.has("show_completion_banner")) { + achievement.showsCompletionBanner = params["show_completion_banner"] ? YES : NO; + } + + [GKAchievement reportAchievements:@[achievement] withCompletionHandler:^(NSError *error) { Dictionary ret; ret["type"] = "award_achievement"; @@ -132,6 +164,154 @@ Error GameCenter::award_achievement(Variant p_params) { return OK; }; +void GameCenter::request_achievement_descriptions() { + + [GKAchievementDescription loadAchievementDescriptionsWithCompletionHandler:^(NSArray *descriptions, NSError *error) { + + Dictionary ret; + ret["type"] = "achievement_descriptions"; + if (error == nil) { + ret["result"] = "ok"; + StringArray names; + StringArray titles; + StringArray unachieved_descriptions; + StringArray achieved_descriptions; + IntArray maximum_points; + IntArray hidden; + IntArray replayable; + + for (int i=0; i<[descriptions count]; i++) { + + GKAchievementDescription* description = [descriptions objectAtIndex:i]; + + const char* str = [description.identifier UTF8String]; + names.push_back(String::utf8(str != NULL ? str : "")); + + str = [description.title UTF8String]; + titles.push_back(String::utf8(str != NULL ? str : "")); + + str = [description.unachievedDescription UTF8String]; + unachieved_descriptions.push_back(String::utf8(str != NULL ? str : "")); + + str = [description.achievedDescription UTF8String]; + achieved_descriptions.push_back(String::utf8(str != NULL ? str : "")); + + maximum_points.push_back(description.maximumPoints); + + hidden.push_back(description.hidden == YES ? 1 : 0); + + replayable.push_back(description.replayable == YES ? 1 : 0); + } + + ret["names"] = names; + + } else { + ret["result"] = "error"; + ret["error_code"] = error.code; + }; + + pending_events.push_back(ret); + }]; +}; + + +void GameCenter::request_achievements() { + + [GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements, NSError *error) { + + Dictionary ret; + ret["type"] = "achievements"; + if (error == nil) { + ret["result"] = "ok"; + StringArray names; + RealArray percentages; + + for (int i=0; i<[achievements count]; i++) { + + GKAchievement* achievement = [achievements objectAtIndex:i]; + const char* str = [achievement.identifier UTF8String]; + names.push_back(String::utf8(str != NULL ? str : "")); + + percentages.push_back(achievement.percentComplete); + } + + ret["names"] = names; + ret["progresses"] = percentages; + + } else { + ret["result"] = "error"; + ret["error_code"] = error.code; + }; + + pending_events.push_back(ret); + }]; +}; + +void GameCenter::reset_achievements() { + + [GKAchievement resetAchievementsWithCompletionHandler:^(NSError *error) + { + Dictionary ret; + ret["type"] = "reset_achievements"; + if (error == nil) { + ret["result"] = "ok"; + } else { + ret["result"] = "error"; + ret["error_code"] = error.code; + }; + + pending_events.push_back(ret); + }]; +}; + +Error GameCenter::show_game_center(Variant p_params) { + + ERR_FAIL_COND_V(!NSProtocolFromString(@"GKGameCenterControllerDelegate"), FAILED); + + Dictionary params = p_params; + + GKGameCenterViewControllerState view_state = GKGameCenterViewControllerStateDefault; + if (params.has("view")) { + String view_name = params["view"]; + if (view_name == "default") { + view_state = GKGameCenterViewControllerStateDefault; + } + else if (view_name == "leaderboards") { + view_state = GKGameCenterViewControllerStateLeaderboards; + } + else if (view_name == "achievements") { + view_state = GKGameCenterViewControllerStateAchievements; + } + else if (view_name == "challenges") { + view_state = GKGameCenterViewControllerStateChallenges; + } + else { + return ERR_INVALID_PARAMETER; + } + } + + GKGameCenterViewController *controller = [[GKGameCenterViewController alloc] init]; + ERR_FAIL_COND_V(!controller, FAILED); + + ViewController *root_controller=(ViewController *)((AppDelegate *)[[UIApplication sharedApplication] delegate]).window.rootViewController; + ERR_FAIL_COND_V(!root_controller, FAILED); + + controller.gameCenterDelegate = root_controller; + controller.viewState = view_state; + if (view_state == GKGameCenterViewControllerStateLeaderboards) { + controller.leaderboardIdentifier = nil; + if (params.has("leaderboard_name")) { + String name = params["leaderboard_name"]; + NSString* name_str = [[[NSString alloc] initWithUTF8String:name.utf8().get_data()] autorelease]; + controller.leaderboardIdentifier = name_str; + } + } + + [root_controller presentViewController: controller animated: YES completion:nil]; + + return OK; +}; + int GameCenter::get_pending_event_count() { return pending_events.size(); diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm index 1d40b1762ec..e3ba6bbd73c 100644 --- a/platform/iphone/in_app_store.mm +++ b/platform/iphone/in_app_store.mm @@ -210,7 +210,7 @@ Error InAppStore::request_product_info(Variant p_params) { receipt_to_send = [receipt description]; } Dictionary receipt_ret; - receipt_ret["receipt"] = String::utf8([receipt_to_send UTF8String]); + receipt_ret["receipt"] = String::utf8(receipt_to_send != nil ? [receipt_to_send UTF8String] : ""); receipt_ret["sdk"] = sdk_version; ret["receipt"] = receipt_ret; diff --git a/platform/iphone/view_controller.h b/platform/iphone/view_controller.h index 9432aebd97a..0cee2f6fbf5 100644 --- a/platform/iphone/view_controller.h +++ b/platform/iphone/view_controller.h @@ -27,8 +27,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #import +#import -@interface ViewController : UIViewController { +@interface ViewController : UIViewController { }; diff --git a/platform/iphone/view_controller.mm b/platform/iphone/view_controller.mm index a5ca689e616..f04264cfd93 100644 --- a/platform/iphone/view_controller.mm +++ b/platform/iphone/view_controller.mm @@ -124,10 +124,14 @@ int add_cmdline(int p_argc, char** p_args) { } }; - - (BOOL)prefersStatusBarHidden { return YES; } +- (void) gameCenterViewControllerDidFinish:(GKGameCenterViewController*) gameCenterViewController { + printf("in finish"); + [gameCenterViewController dismissViewControllerAnimated:YES completion:nil]; +} + @end From 94638e7bfeec8feac553ecd80cd7e4efff04f2a5 Mon Sep 17 00:00:00 2001 From: romulox_x Date: Sat, 23 May 2015 19:04:02 -0700 Subject: [PATCH 04/49] added data to descriptions dictionary that was missing. Made the elements that sound weird as plurals consistently singular. changed int arrays to bool arrays in descriptions --- platform/iphone/game_center.mm | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/platform/iphone/game_center.mm b/platform/iphone/game_center.mm index a0585366852..9b4018a4ba6 100644 --- a/platform/iphone/game_center.mm +++ b/platform/iphone/game_center.mm @@ -177,8 +177,8 @@ void GameCenter::request_achievement_descriptions() { StringArray unachieved_descriptions; StringArray achieved_descriptions; IntArray maximum_points; - IntArray hidden; - IntArray replayable; + Array hidden; + Array replayable; for (int i=0; i<[descriptions count]; i++) { @@ -198,12 +198,18 @@ void GameCenter::request_achievement_descriptions() { maximum_points.push_back(description.maximumPoints); - hidden.push_back(description.hidden == YES ? 1 : 0); + hidden.push_back(description.hidden == YES); - replayable.push_back(description.replayable == YES ? 1 : 0); + replayable.push_back(description.replayable == YES); } ret["names"] = names; + ret["titles"] = titles; + ret["unachieved_descriptions"] = unachieved_descriptions; + ret["achieved_descriptions"] = achieved_descriptions; + ret["maximum_points"] = maximum_points; + ret["hidden"] = hidden; + ret["replayable"] = replayable; } else { ret["result"] = "error"; @@ -236,7 +242,7 @@ void GameCenter::request_achievements() { } ret["names"] = names; - ret["progresses"] = percentages; + ret["progress"] = percentages; } else { ret["result"] = "error"; From 95cd9b1ad54f799d9513911e4cebc5bafc135d97 Mon Sep 17 00:00:00 2001 From: romulox_x Date: Sat, 23 May 2015 23:22:20 -0700 Subject: [PATCH 05/49] added response event for game center overlay closing --- platform/iphone/game_center.h | 2 ++ platform/iphone/game_center.mm | 10 +++++++++- platform/iphone/view_controller.mm | 3 ++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/platform/iphone/game_center.h b/platform/iphone/game_center.h index 4fe13db8fcc..8f180d16383 100644 --- a/platform/iphone/game_center.h +++ b/platform/iphone/game_center.h @@ -56,6 +56,8 @@ public: void request_achievement_descriptions(); Error show_game_center(Variant p_params); + void game_center_closed(); + int get_pending_event_count(); Variant pop_pending_event(); diff --git a/platform/iphone/game_center.mm b/platform/iphone/game_center.mm index 9b4018a4ba6..79c056776d5 100644 --- a/platform/iphone/game_center.mm +++ b/platform/iphone/game_center.mm @@ -314,10 +314,18 @@ Error GameCenter::show_game_center(Variant p_params) { } [root_controller presentViewController: controller animated: YES completion:nil]; - + return OK; }; +void GameCenter::game_center_closed() { + + Dictionary ret; + ret["type"] = "show_game_center"; + ret["result"] = "ok"; + pending_events.push_back(ret); +} + int GameCenter::get_pending_event_count() { return pending_events.size(); diff --git a/platform/iphone/view_controller.mm b/platform/iphone/view_controller.mm index f04264cfd93..bc9950979ef 100644 --- a/platform/iphone/view_controller.mm +++ b/platform/iphone/view_controller.mm @@ -130,7 +130,8 @@ int add_cmdline(int p_argc, char** p_args) { } - (void) gameCenterViewControllerDidFinish:(GKGameCenterViewController*) gameCenterViewController { - printf("in finish"); + //[gameCenterViewController dismissViewControllerAnimated:YES completion:^{GameCenter::get_singleton()->game_center_closed();}];//version for signaling when overlay is completely gone + GameCenter::get_singleton()->game_center_closed(); [gameCenterViewController dismissViewControllerAnimated:YES completion:nil]; } From df9d48d9b552c30b9b42940a964ccc4271e6905b Mon Sep 17 00:00:00 2001 From: Biliogadafr Date: Sun, 24 May 2015 21:18:52 +0300 Subject: [PATCH 06/49] Replace color phases with color ramp for Particles2D. --- scene/2d/particles_2d.cpp | 178 ++++++--- scene/2d/particles_2d.h | 15 +- scene/gui/color_ramp_edit.cpp | 368 ++++++++++++++++++ scene/gui/color_ramp_edit.h | 52 +++ scene/register_scene_types.cpp | 2 + scene/resources/color_ramp.cpp | 111 ++++++ scene/resources/color_ramp.h | 52 +++ scene/resources/default_theme/checker_bg.png | Bin 0 -> 180 bytes scene/resources/default_theme/theme_data.h | 5 + tools/editor/editor_node.cpp | 2 + tools/editor/icons/icon_color_ramp.png | Bin 0 -> 290 bytes .../plugins/color_ramp_editor_plugin.cpp | 83 ++++ .../editor/plugins/color_ramp_editor_plugin.h | 37 ++ 13 files changed, 836 insertions(+), 69 deletions(-) create mode 100644 scene/gui/color_ramp_edit.cpp create mode 100644 scene/gui/color_ramp_edit.h create mode 100644 scene/resources/color_ramp.cpp create mode 100644 scene/resources/color_ramp.h create mode 100644 scene/resources/default_theme/checker_bg.png create mode 100644 tools/editor/icons/icon_color_ramp.png create mode 100644 tools/editor/plugins/color_ramp_editor_plugin.cpp create mode 100644 tools/editor/plugins/color_ramp_editor_plugin.h diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index 39d747c436c..6effd4f31dc 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -503,19 +503,6 @@ void Particles2D::_notification(int p_what) { if (!local_space) invxform=get_global_transform().affine_inverse(); - int col_count=0; - float last=-1; - ColorPhase cphase[MAX_COLOR_PHASES]; - - for(int i=0;i ptime) - break; - cpos++; - } - - cpos--; - Color color; - //could be faster.. - if (cpos==-1) - color=Color(1,1,1,1); - else { - if (cpos==col_count-1) - color=cphase[cpos].color; - else { - float diff = (cphase[cpos+1].pos-cphase[cpos].pos); - if (diff>0) - color=cphase[cpos].color.linear_interpolate(cphase[cpos+1].color, (ptime - cphase[cpos].pos) / diff ); - else - color=cphase[cpos+1].color; + + if(color_ramp.is_valid()) + { + Vector& color_points = color_ramp->get_points(); + + int cpos=0; + + while(cpos ptime) + break; + cpos++; } + + cpos--; + //could be faster.. + if (cpos==-1) + if(color_points.size()) + color=color_points[0].color;//Extend color to the beginning + else + color=Color(1,1,1,1);//If no points just use white. + else { + if (cpos==color_points.size()-1) + color=color_points[cpos].color; + else { + float diff = (color_points[cpos+1].offset-color_points[cpos].offset); + if (diff>0) + color=color_points[cpos].color.linear_interpolate(color_points[cpos+1].color, (ptime - color_points[cpos].offset) / diff ); + else + color=color_points[cpos+1].color; + } + } + } else + { + color = default_color; } @@ -813,6 +810,27 @@ Ref Particles2D::get_texture() const { return texture; } +void Particles2D::set_color(const Color& p_color) { + + default_color = p_color; +} + +Color Particles2D::get_color() const { + + return default_color; +} + + +void Particles2D::set_color_ramp(const Ref& p_color_ramp) { + + color_ramp=p_color_ramp; +} + +Ref Particles2D::get_color_ramp() const { + + return color_ramp; +} + void Particles2D::set_emissor_offset(const Point2& p_offset) { emissor_offset=p_offset; @@ -834,40 +852,76 @@ bool Particles2D::is_using_local_space() const { return local_space; } - +//Deprecated. Converts color phases to color ramp void Particles2D::set_color_phases(int p_phases) { - ERR_FAIL_INDEX(p_phases,MAX_COLOR_PHASES+1); - color_phase_count=p_phases; + //Create color ramp if we have 2 or more phases. + //Otherwise first phase phase will be assigned to default color. + if(p_phases > 1 && color_ramp.is_null()) + { + color_ramp = Ref(memnew (ColorRamp())); + } + if(color_ramp.is_valid()) + { + color_ramp->get_points().resize(p_phases); + } } +//Deprecated. int Particles2D::get_color_phases() const { - return color_phase_count; + if(color_ramp.is_valid()) + { + return color_ramp->get_points_count(); + } + return 0; } +//Deprecated. Converts color phases to color ramp void Particles2D::set_color_phase_color(int p_phase,const Color& p_color) { ERR_FAIL_INDEX(p_phase,MAX_COLOR_PHASES); - color_phases[p_phase].color=p_color; - + if(color_ramp.is_valid()) + { + if(color_ramp->get_points_count() > p_phase) + color_ramp->set_color(p_phase, p_color); + } else + { + if(p_phase == 0) + default_color = p_color; + } } + +//Deprecated. Color Particles2D::get_color_phase_color(int p_phase) const { ERR_FAIL_INDEX_V(p_phase,MAX_COLOR_PHASES,Color()); - return color_phases[p_phase].color; + if(color_ramp.is_valid()) + { + return color_ramp->get_color(p_phase); + } + return Color(0,0,0,1); } +//Deprecated. Converts color phases to color ramp void Particles2D::set_color_phase_pos(int p_phase,float p_pos) { ERR_FAIL_INDEX(p_phase,MAX_COLOR_PHASES); ERR_FAIL_COND(p_pos<0.0 || p_pos>1.0); - color_phases[p_phase].pos=p_pos; - + if(color_ramp.is_valid() && color_ramp->get_points_count() > p_phase) + { + return color_ramp->set_offset(p_phase, p_pos); + } } + +//Deprecated. float Particles2D::get_color_phase_pos(int p_phase) const { ERR_FAIL_INDEX_V(p_phase,MAX_COLOR_PHASES,0); - return color_phases[p_phase].pos; + if(color_ramp.is_valid()) + { + return color_ramp->get_offset(p_phase); + } + return 0; } void Particles2D::set_emission_half_extents(const Vector2& p_extents) { @@ -997,6 +1051,12 @@ void Particles2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_texture:Texture","texture"),&Particles2D::set_texture); ObjectTypeDB::bind_method(_MD("get_texture:Texture"),&Particles2D::get_texture); + ObjectTypeDB::bind_method(_MD("set_color","color"),&Particles2D::set_color); + ObjectTypeDB::bind_method(_MD("get_color"),&Particles2D::get_color); + + ObjectTypeDB::bind_method(_MD("set_color_ramp:ColorRamp","color_ramp"),&Particles2D::set_color_ramp); + ObjectTypeDB::bind_method(_MD("get_color_ramp:ColorRamp"),&Particles2D::get_color_ramp); + ObjectTypeDB::bind_method(_MD("set_emissor_offset","offset"),&Particles2D::set_emissor_offset); ObjectTypeDB::bind_method(_MD("get_emissor_offset"),&Particles2D::get_emissor_offset); @@ -1055,7 +1115,6 @@ void Particles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT,"config/v_frames",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_v_frames"),_SCS("get_v_frames")); - for(int i=0;i particles; - int color_phase_count; - struct ColorPhase { - Color color; - float pos; - } color_phases[MAX_COLOR_PHASES]; struct AttractorCache { @@ -161,6 +157,9 @@ private: Ref texture; + //If no color ramp is set then default color is used. Created as simple alternative to color_ramp. + Color default_color; + Ref color_ramp; void testee(int a, int b, int c, int d, int e); void _process_particles(float p_delta); @@ -230,6 +229,12 @@ public: void set_texture(const Ref& p_texture); Ref get_texture() const; + void set_color(const Color& p_color); + Color get_color() const; + + void set_color_ramp(const Ref& p_texture); + Ref get_color_ramp() const; + void set_emissor_offset(const Point2& p_offset); Point2 get_emissor_offset() const; diff --git a/scene/gui/color_ramp_edit.cpp b/scene/gui/color_ramp_edit.cpp new file mode 100644 index 00000000000..382c0dc1031 --- /dev/null +++ b/scene/gui/color_ramp_edit.cpp @@ -0,0 +1,368 @@ +#include "color_ramp_edit.h" +#include "os/keyboard.h" + +ColorRampEdit::ColorRampEdit(){ + grabbed=-1; + grabbing=false; + set_focus_mode(FOCUS_ALL); + + popup = memnew( PopupPanel ); + picker = memnew( ColorPicker ); + popup->add_child(picker); + popup->set_child_rect(picker); + add_child(popup); + + checker = Ref(memnew( ImageTexture )); + checker->create_from_image( Image(checker_bg_png),ImageTexture::FLAG_REPEAT ); +} + +int ColorRampEdit::_get_point_from_pos(int x) { + int result = -1; + int total_w = get_size().width-get_size().height-3; + for(int i=0;iget_combined_minimum_size().height+10); + picker->set_color(points[grabbed].color); + popup->set_pos(get_global_pos()-Vector2(ms.width-get_size().width,ms.height)); + popup->set_size(ms); + popup->popup(); +} + +ColorRampEdit::~ColorRampEdit() { + +} + +void ColorRampEdit::_input_event(const InputEvent& p_event) { + + if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) { + + points.remove(grabbed); + grabbed=-1; + update(); + emit_signal("ramp_changed"); + accept_event(); + } + + //Show color picker on double click. + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.doubleclick && p_event.mouse_button.pressed) { + grabbed=_get_point_from_pos(p_event.mouse_button.x); + _show_color_picker(); + accept_event(); + } + + //Delete point on right click + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==2 && p_event.mouse_button.pressed) { + grabbed=_get_point_from_pos(p_event.mouse_button.x); + if(grabbed != -1) + { + points.remove(grabbed); + grabbed=-1; + update(); + emit_signal("ramp_changed"); + accept_event(); + } + } + + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) { + + update(); + int x = p_event.mouse_button.x; + int total_w = get_size().width-get_size().height-3; + + //Check if color selector was clicked. + if (x>total_w+3) { + _show_color_picker(); + return; + } + + grabbing=true; + + grabbed=_get_point_from_pos(x); + //grab or select + if (grabbed!=-1) { + return; + } + + //insert + ColorRamp::Point newPoint; + newPoint.offset=CLAMP(x/float(total_w),0,1); + + ColorRamp::Point prev; + ColorRamp::Point next; + + int pos=-1; + for(int i=0;iconnect("color_changed",this,"_color_changed"); + } + if (p_what==NOTIFICATION_DRAW) { + + int w = get_size().x; + int h = get_size().y; + + if (w == 0 || h == 0) + return; //Safety check. We have division by 'h'. And in any case there is nothing to draw with such size + + int total_w = get_size().width-get_size().height-3; + + //Draw checker pattern for ramp + _draw_checker(0,0, total_w, h); + + //Draw color ramp + ColorRamp::Point prev; + prev.offset=0; + if(points.size() == 0) + prev.color=Color(0,0,0); //Draw black rectangle if we have no points + else + prev.color = points[0].color; //Extend color of first point to the beginning. + + for(int i=-1;i points; + Vector colors; + points.push_back(Vector2(prev.offset*total_w,h)); + points.push_back(Vector2(prev.offset*total_w,0)); + points.push_back(Vector2(next.offset*total_w,0)); + points.push_back(Vector2(next.offset*total_w,h)); + colors.push_back(prev.color); + colors.push_back(prev.color); + colors.push_back(next.color); + colors.push_back(next.color); + draw_primitive(points,colors,Vector()); + prev=next; + } + + //Draw point markers + for(int i=0;i backPoints; + backPoints.push_back(Vector2(x, y)); + backPoints.push_back(Vector2(x, y+h)); + backPoints.push_back(Vector2(x+w, y+h)); + backPoints.push_back(Vector2(x+w, y)); + Vector colorPoints; + colorPoints.push_back(Color(1, 1, 1, 1)); + colorPoints.push_back(Color(1, 1, 1, 1)); + colorPoints.push_back(Color(1, 1, 1, 1)); + colorPoints.push_back(Color(1, 1, 1, 1)); + Vector uvPoints; + //Draw checker pattern pixel-perfect and scale it by 2. + uvPoints.push_back(Vector2(x, y)); + uvPoints.push_back(Vector2(x, y+h*.5f/checker->get_height())); + uvPoints.push_back(Vector2(x+w*.5f/checker->get_width(), y+h*.5f/checker->get_height())); + uvPoints.push_back(Vector2(x+w*.5f/checker->get_width(), y)); + draw_polygon(backPoints, colorPoints, uvPoints, checker); +} + +Size2 ColorRampEdit::get_minimum_size() const { + + return Vector2(0,16); +} + +void ColorRampEdit::_color_changed(const Color& p_color) { + + if (grabbed==-1) + return; + points[grabbed].color=p_color; + update(); + emit_signal("ramp_changed"); + +} + +void ColorRampEdit::set_ramp(const Vector& p_offsets,const Vector& p_colors) { + + ERR_FAIL_COND(p_offsets.size()!=p_colors.size()); + points.clear(); + for(int i=0;i ColorRampEdit::get_offsets() const { + Vector ret; + for(int i=0;i ColorRampEdit::get_colors() const { + Vector ret; + for(int i=0;i& p_points) { + if(points.size() != p_points.size()) + grabbed = -1; + points.clear(); + points = p_points; +} + +Vector& ColorRampEdit::get_points() { + return points; +} + +void ColorRampEdit::_bind_methods() { + ObjectTypeDB::bind_method(_MD("_input_event"),&ColorRampEdit::_input_event); + ObjectTypeDB::bind_method(_MD("_color_changed"),&ColorRampEdit::_color_changed); + ADD_SIGNAL(MethodInfo("ramp_changed")); +} diff --git a/scene/gui/color_ramp_edit.h b/scene/gui/color_ramp_edit.h new file mode 100644 index 00000000000..91292eed0db --- /dev/null +++ b/scene/gui/color_ramp_edit.h @@ -0,0 +1,52 @@ +#ifndef SCENE_GUI_COLOR_RAMP_EDIT_H_ +#define SCENE_GUI_COLOR_RAMP_EDIT_H_ + +#include "scene/gui/popup.h" +#include "scene/gui/color_picker.h" +#include "scene/resources/color_ramp.h" +#include "scene/resources/default_theme/theme_data.h" + +#define POINT_WIDTH 8 + +class ColorRampEdit : public Control { + + OBJ_TYPE(ColorRampEdit,Control); + + PopupPanel *popup; + ColorPicker *picker; + + Ref checker; + + bool grabbing; + int grabbed; + Vector points; + + void _draw_checker(int x, int y, int w, int h); + void _color_changed(const Color& p_color); + int _get_point_from_pos(int x); + void _show_color_picker(); + +protected: + void _input_event(const InputEvent& p_event); + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_ramp(const Vector& p_offsets,const Vector& p_colors); + Vector get_offsets() const; + Vector get_colors() const; + void set_points(Vector& p_points); + Vector& get_points(); + virtual Size2 get_minimum_size() const; + + ColorRampEdit(); + virtual ~ColorRampEdit(); +}; + +/*class ColorRampEditPanel : public Panel +{ + OBJ_TYPE(ColorRampEditPanel, Panel ); +};*/ + + +#endif /* SCENE_GUI_COLOR_RAMP_EDIT_H_ */ diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 687410d1926..d3446ca62d8 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -170,6 +170,7 @@ #include "scene/resources/audio_stream.h" #include "scene/resources/gibberish_stream.h" #include "scene/resources/bit_mask.h" +#include "scene/resources/color_ramp.h" #include "scene/scene_string_names.h" @@ -565,6 +566,7 @@ void register_scene_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); OS::get_singleton()->yield(); //may take time to init diff --git a/scene/resources/color_ramp.cpp b/scene/resources/color_ramp.cpp new file mode 100644 index 00000000000..ef32ccb6a77 --- /dev/null +++ b/scene/resources/color_ramp.cpp @@ -0,0 +1,111 @@ +/* + * color_ramp.h + */ + +#include "color_ramp.h" + +//setter and getter names for property serialization +#define COLOR_RAMP_GET_OFFSETS "get_offsets" +#define COLOR_RAMP_GET_COLORS "get_colors" +#define COLOR_RAMP_SET_OFFSETS "set_offsets" +#define COLOR_RAMP_SET_COLORS "set_colors" + +ColorRamp::ColorRamp() { + //Set initial color ramp transition from black to white + points.resize(2); + points[0].color = Color(0,0,0,1); + points[0].offset = 0; + points[1].color = Color(1,1,1,1); + points[1].offset = 1; +} + +ColorRamp::~ColorRamp() { + +} + +void ColorRamp::_bind_methods() { + + //ObjectTypeDB::bind_method(_MD("set_offset", "pos", "offset"),&ColorRamp::set_offset); + //ObjectTypeDB::bind_method(_MD(COLOR_RAMP_GET_OFFSETS),&ColorRamp::get_offset); + + ObjectTypeDB::bind_method(_MD(COLOR_RAMP_SET_OFFSETS,"offsets"),&ColorRamp::set_offsets); + ObjectTypeDB::bind_method(_MD(COLOR_RAMP_GET_OFFSETS),&ColorRamp::get_offsets); + + ObjectTypeDB::bind_method(_MD(COLOR_RAMP_SET_COLORS,"colors"),&ColorRamp::set_colors); + ObjectTypeDB::bind_method(_MD(COLOR_RAMP_GET_COLORS),&ColorRamp::get_colors); + + ADD_PROPERTY( PropertyInfo(Variant::REAL,"offsets"),_SCS(COLOR_RAMP_SET_OFFSETS),_SCS(COLOR_RAMP_GET_OFFSETS) ); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"colors"),_SCS(COLOR_RAMP_SET_COLORS),_SCS(COLOR_RAMP_GET_COLORS) ); +} + +Vector ColorRamp::get_offsets() const { + Vector offsets; + offsets.resize(points.size()); + for(int i = 0; i < points.size(); i++) + { + offsets[i] = points[i].offset; + } + return offsets; +} + +Vector ColorRamp::get_colors() const { + Vector colors; + colors.resize(points.size()); + for(int i = 0; i < points.size(); i++) + { + colors[i] = points[i].color; + } + return colors; +} + +void ColorRamp::set_offsets(const Vector& offsets) { + points.resize(offsets.size()); + for(int i = 0; i < points.size(); i++) + { + points[i].offset = offsets[i]; + } +} + +void ColorRamp::set_colors(const Vector& colors) { + points.resize(colors.size()); + for(int i = 0; i < points.size(); i++) + { + points[i].color = colors[i]; + } +} + +Vector& ColorRamp::get_points() { + return points; +} + +void ColorRamp::set_points(Vector& p_points) { + points = p_points; +} + +void ColorRamp::set_offset(int pos, const float offset) { + if(points.size() <= pos) + points.resize(pos + 1); + points[pos].offset = offset; +} + +float ColorRamp::get_offset(int pos) const { + if(points.size() > pos) + return points[pos].offset; + return 0; //TODO: Maybe throw some error instead? +} + +void ColorRamp::set_color(int pos, const Color& color) { + if(points.size() <= pos) + points.resize(pos + 1); + points[pos].color = color; +} + +Color ColorRamp::get_color(int pos) const { + if(points.size() > pos) + return points[pos].color; + return Color(0,0,0,1); //TODO: Maybe throw some error instead? +} + +int ColorRamp::get_points_count() const { + return points.size(); +} diff --git a/scene/resources/color_ramp.h b/scene/resources/color_ramp.h new file mode 100644 index 00000000000..e2f1ac5ed4f --- /dev/null +++ b/scene/resources/color_ramp.h @@ -0,0 +1,52 @@ +/* + * color_ramp.h + */ + +#ifndef SCENE_RESOURCES_COLOR_RAMP_H_ +#define SCENE_RESOURCES_COLOR_RAMP_H_ + +#include "resource.h" + +class ColorRamp: public Resource { + OBJ_TYPE( ColorRamp, Resource ); + OBJ_SAVE_TYPE( ColorRamp ); + +public: + struct Point { + + float offset; + Color color; + bool operator<(const Point& p_ponit) const { + return offset points; + +protected: + static void _bind_methods(); + +public: + ColorRamp(); + virtual ~ColorRamp(); + + void set_points(Vector& points); + Vector& get_points(); + + void set_offset(int pos, const float offset); + float get_offset(int pos) const; + + void set_color(int pos, const Color& color); + Color get_color(int pos) const; + + void set_offsets(const Vector& offsets); + Vector get_offsets() const; + + void set_colors(const Vector& colors); + Vector get_colors() const; + + int get_points_count() const; +}; + +#endif /* SCENE_RESOURCES_COLOR_RAMP_H_ */ diff --git a/scene/resources/default_theme/checker_bg.png b/scene/resources/default_theme/checker_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..0674f9da260107061e07992d2bf7219f6b78f868 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sDEfH31!Z9ZwBAX}2Ry9>jA5L~c#`DCC7dx@v7EBif85ndVT zAjhI5Kp_=R7sn8d;N(C2EIb|y7A|Bw)x@Bt(JLIVu3_W8eRTFVdQ&MBb@0G{126#xJL literal 0 HcmV?d00001 diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index 78e210239df..8bd0a66271a 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -49,6 +49,11 @@ static const unsigned char checked_png[]={ }; +static const unsigned char checker_bg_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b,0xe,0x1b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0x9,0x14,0xd,0x1c,0x1b,0x52,0x41,0x72,0xa4,0x0,0x0,0x0,0x24,0x49,0x44,0x41,0x54,0x28,0x53,0x63,0xfc,0xf,0x4,0xc,0x48,0xa0,0xa1,0xa1,0x1,0xca,0x82,0x0,0x26,0x28,0x8d,0x13,0x50,0xae,0x80,0xb1,0xbe,0xbe,0x7e,0x60,0xdd,0xc0,0xc0,0x0,0x0,0x78,0x11,0x9,0x87,0x2b,0xa,0xe1,0x69,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + static const unsigned char close_png[]={ 0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x73,0x0,0x29,0x0,0x7c,0x29,0x1e,0x61,0x18,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x19,0x1,0x14,0x3,0xf4,0x10,0x33,0xed,0x0,0x0,0x1,0x53,0x49,0x44,0x41,0x54,0x38,0xcb,0xcd,0x92,0xbd,0x4e,0x5b,0x41,0x10,0x85,0xbf,0xd9,0x9d,0xfd,0xb9,0xd7,0xb2,0xb9,0x81,0x8e,0x26,0xf4,0x69,0x53,0x50,0x44,0xa2,0x74,0x3,0xd,0xd,0x48,0x48,0xf4,0x3c,0x16,0x8f,0xc1,0x23,0xf0,0x0,0xf4,0x8e,0x90,0x11,0x96,0x25,0xa2,0x10,0x45,0x4a,0x9c,0x6b,0x4f,0xa,0xf6,0x4a,0xe6,0xc6,0x4e,0xb,0x47,0x5a,0xed,0xee,0x9c,0xd9,0xd1,0x99,0xb3,0x3,0x6f,0xd,0xd9,0x70,0xd7,0x72,0xfe,0xd3,0xe3,0x42,0xd9,0x5b,0xc0,0xba,0xa0,0xef,0x3d,0xfe,0xe0,0x9c,0x3b,0x35,0xb3,0x21,0xf0,0x1d,0xf8,0x5d,0xe2,0xd,0xf0,0xd9,0x39,0xf7,0xc5,0xcc,0xee,0x81,0x5f,0x9b,0xd4,0x4,0xe7,0xdc,0x65,0xd3,0x34,0x3f,0x53,0x4a,0x73,0xe0,0x18,0xd8,0x2b,0xeb,0x78,0x38,0x1c,0x3e,0xe5,0x9c,0x7f,0x38,0xe7,0x2e,0xd7,0xd4,0xfc,0x23,0xf1,0x30,0xc6,0x38,0x4b,0x29,0x59,0x8,0xe1,0x1e,0xb8,0x0,0x2e,0xea,0xba,0x7e,0xa8,0xaa,0xca,0x42,0x8,0x33,0xe0,0x70,0x5b,0x1,0x80,0x1d,0x60,0xac,0xaa,0x93,0x9c,0xb3,0xa9,0xea,0x63,0x8c,0x71,0x36,0x18,0xc,0x4c,0x55,0x27,0xc0,0xb8,0xe4,0xfc,0xd7,0xd4,0x5d,0xe0,0x5c,0x55,0xa7,0x39,0x67,0xcb,0x39,0x9b,0xf7,0x7e,0xa,0x9c,0x17,0xee,0x95,0xf1,0xba,0xa5,0x90,0x17,0x11,0x6f,0xf6,0x62,0xb6,0x88,0xb8,0x9e,0xe1,0x5b,0xd1,0x0,0x27,0x75,0x5d,0x3f,0x14,0xd9,0xd3,0x4e,0x49,0xf1,0xe4,0xa4,0xe4,0x6c,0x44,0x10,0x91,0xa3,0xd1,0x68,0xf4,0x54,0x55,0x55,0xd7,0xf3,0x19,0x70,0xa6,0xaa,0x93,0x94,0x92,0xc5,0x18,0xe7,0x22,0x72,0xb4,0x6e,0xe2,0xab,0x16,0xbc,0xf7,0x7,0x8b,0xc5,0x42,0x97,0xcb,0xe5,0xbc,0x6d,0xdb,0x2b,0xe0,0x16,0xa0,0x6d,0xdb,0x67,0xe7,0xdc,0xb5,0x88,0x24,0x11,0xd9,0xef,0x5a,0xeb,0x4f,0x62,0x37,0x48,0xe3,0xd5,0x6a,0xf5,0x15,0xb8,0x3,0x9e,0xb,0x37,0x2,0x3e,0x89,0xc8,0x47,0x33,0xbb,0x1,0xbe,0xad,0x4f,0x63,0xff,0x17,0xc2,0x16,0x73,0xb5,0x70,0xc2,0xbb,0xc2,0x5f,0x47,0xa5,0x56,0x8a,0x30,0xdd,0x7d,0xae,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 56b813344ab..d623cee2c8d 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -91,6 +91,7 @@ #include "plugins/polygon_2d_editor_plugin.h" #include "plugins/navigation_polygon_editor_plugin.h" #include "plugins/light_occluder_2d_editor_plugin.h" +#include "plugins/color_ramp_editor_plugin.h" // end #include "tools/editor/io_plugins/editor_texture_import_plugin.h" #include "tools/editor/io_plugins/editor_scene_import_plugin.h" @@ -4157,6 +4158,7 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( Polygon2DEditorPlugin(this) ) ); add_editor_plugin( memnew( LightOccluder2DEditorPlugin(this) ) ); add_editor_plugin( memnew( NavigationPolygonEditorPlugin(this) ) ); + add_editor_plugin( memnew( ColorRampEditorPlugin(this) ) ); for(int i=0;i@chBAf*t zk;M!Q+`=Ht$S`Y;1W=H@#M9T6{XV0Rps|dolhZMv(0Wf7#}JM4S0^46JY>Mb^8Js$ z6SIh`@)u|AD+%Hb;wpbiZQfX%H2C9aEM>c9?_`}H?@w4xE@oRW#Yyw&Vt0n=$FFK8 zM4d6XZgnq})kxz*t)b|g@z z()C8OQ`%{@kjvJM{1Xl@cG?=H!tE;hKzfD6u8vzevplYBwaU1){L9BJ2jjk%m)hp+ i+I_!j^IzS1<$D_!6d0bWFN*>?ox#)9&t;ucLK6VNy=dtG literal 0 HcmV?d00001 diff --git a/tools/editor/plugins/color_ramp_editor_plugin.cpp b/tools/editor/plugins/color_ramp_editor_plugin.cpp new file mode 100644 index 00000000000..df505354020 --- /dev/null +++ b/tools/editor/plugins/color_ramp_editor_plugin.cpp @@ -0,0 +1,83 @@ +/* + * color_ramp_editor_plugin.cpp + */ + +#include "color_ramp_editor_plugin.h" + +ColorRampEditorPlugin::ColorRampEditorPlugin(EditorNode *p_node) { + + editor=p_node; + ramp_editor = memnew( ColorRampEdit ); + + add_custom_control(CONTAINER_CANVAS_EDITOR_BOTTOM,ramp_editor); + //add_custom_control(CONTAINER_SPATIAL_EDITOR_BOTTOM,ramp_editor); + ramp_editor->set_custom_minimum_size(Size2(100, 48)); + ramp_editor->hide(); + ramp_editor->connect("ramp_changed", this, "ramp_changed"); +} + +void ColorRampEditorPlugin::edit(Object *p_object) { + + ColorRamp* color_ramp = p_object->cast_to(); + if (!color_ramp) + return; + color_ramp_ref = Ref(color_ramp); + ramp_editor->set_points(color_ramp_ref->get_points()); +} + +bool ColorRampEditorPlugin::handles(Object *p_object) const { + + return p_object->is_type("ColorRamp"); +} + +void ColorRampEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + ramp_editor->show(); + } else { + ramp_editor->hide(); + } + +} + +void ColorRampEditorPlugin::_ramp_changed() { + + if(color_ramp_ref.is_valid()) + { + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + + //Not sure if I should convert this data to DVector + Vector new_offsets=ramp_editor->get_offsets(); + Vector new_colors=ramp_editor->get_colors(); + Vector old_offsets=color_ramp_ref->get_offsets(); + Vector old_colors=color_ramp_ref->get_colors(); + + if (old_offsets.size()!=new_offsets.size()) + ur->create_action("Add/Remove Color Ramp Point"); + else + ur->create_action("Modify Color Ramp",true); + ur->add_do_method(this,"undo_redo_color_ramp",new_offsets,new_colors); + ur->add_undo_method(this,"undo_redo_color_ramp",old_offsets,old_colors); + ur->commit_action(); + + //color_ramp_ref->set_points(ramp_editor->get_points()); + } +} + +void ColorRampEditorPlugin::_undo_redo_color_ramp(const Vector& offsets, + const Vector& colors) { + + color_ramp_ref->set_offsets(offsets); + color_ramp_ref->set_colors(colors); + ramp_editor->set_points(color_ramp_ref->get_points()); + ramp_editor->update(); +} + +ColorRampEditorPlugin::~ColorRampEditorPlugin(){ +} + +void ColorRampEditorPlugin::_bind_methods() { + ObjectTypeDB::bind_method(_MD("ramp_changed"),&ColorRampEditorPlugin::_ramp_changed); + ObjectTypeDB::bind_method(_MD("undo_redo_color_ramp","offsets","colors"),&ColorRampEditorPlugin::_undo_redo_color_ramp); +} diff --git a/tools/editor/plugins/color_ramp_editor_plugin.h b/tools/editor/plugins/color_ramp_editor_plugin.h new file mode 100644 index 00000000000..e39a5d65fe5 --- /dev/null +++ b/tools/editor/plugins/color_ramp_editor_plugin.h @@ -0,0 +1,37 @@ +/* + * color_ramp_editor_plugin.h + */ + +#ifndef TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_ +#define TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_ + +#include "tools/editor/editor_plugin.h" +#include "tools/editor/editor_node.h" +#include "scene/gui/color_ramp_edit.h" + +class ColorRampEditorPlugin : public EditorPlugin { + + OBJ_TYPE( ColorRampEditorPlugin, EditorPlugin ); + + Ref color_ramp_ref; + ColorRampEdit *ramp_editor; + EditorNode *editor; + +protected: + static void _bind_methods(); + void _ramp_changed(); + void _undo_redo_color_ramp(const Vector& offsets, const Vector& colors); + +public: + virtual String get_name() const { return "ColorRamp"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_node); + virtual bool handles(Object *p_node) const; + virtual void make_visible(bool p_visible); + + ColorRampEditorPlugin(EditorNode *p_node); + ~ColorRampEditorPlugin(); + +}; + +#endif /* TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_ */ From b210f52f4a090ba9a6bf60138b4e5222678ba98e Mon Sep 17 00:00:00 2001 From: choikwa Date: Sun, 24 May 2015 19:07:26 -0400 Subject: [PATCH 07/49] fix typo error in Color::invert --- core/color.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/color.cpp b/core/color.cpp index ba4751dc2f3..32f3df6d4bc 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -161,7 +161,7 @@ void Color::invert() { r=1.0-r; g=1.0-g; - g=1.0-b; + b=1.0-b; } void Color::contrast() { From f36e7dcb405ead38c33d808f732fd7b4e23d19e5 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Mon, 25 May 2015 01:46:45 -0300 Subject: [PATCH 08/49] improved animation editor -same-value link keys -new layout -forward, backwards playback -integrated curve/property editor -auto increment sprite frame after insert -copy & paste animation resoucres --- core/object.cpp | 33 ++ core/object.h | 2 + core/os/main_loop.cpp | 27 +- scene/2d/animated_sprite.cpp | 2 +- scene/2d/sprite.cpp | 2 +- scene/3d/sprite_3d.cpp | 4 +- scene/animation/animation_player.cpp | 10 +- scene/animation/animation_player.h | 2 +- tools/editor/animation_editor.cpp | 525 ++++++++++++++++-- tools/editor/animation_editor.h | 29 +- tools/editor/editor_file_system.cpp | 1 + tools/editor/editor_node.cpp | 4 +- tools/editor/editor_node.h | 2 +- tools/editor/icons/icon_curve_constant.png | Bin 0 -> 222 bytes tools/editor/icons/icon_curve_in.png | Bin 0 -> 319 bytes tools/editor/icons/icon_curve_in_out.png | Bin 0 -> 326 bytes tools/editor/icons/icon_curve_linear.png | Bin 0 -> 275 bytes tools/editor/icons/icon_curve_out.png | Bin 0 -> 319 bytes tools/editor/icons/icon_curve_out_in.png | Bin 0 -> 318 bytes tools/editor/icons/icon_key_next.png | Bin 0 -> 499 bytes tools/editor/icons/icon_pause.png | Bin 367 -> 228 bytes tools/editor/icons/icon_play.png | Bin 256 -> 260 bytes tools/editor/icons/icon_play_backwards.png | Bin 0 -> 256 bytes tools/editor/icons/icon_play_start.png | Bin 0 -> 282 bytes .../icons/icon_play_start_backwards.png | Bin 0 -> 289 bytes tools/editor/icons/icon_stop.png | Bin 138 -> 236 bytes .../animation_player_editor_plugin.cpp | 259 ++++++++- .../plugins/animation_player_editor_plugin.h | 15 + tools/editor/property_editor.cpp | 28 +- tools/editor/property_editor.h | 1 + 30 files changed, 840 insertions(+), 106 deletions(-) create mode 100644 tools/editor/icons/icon_curve_constant.png create mode 100644 tools/editor/icons/icon_curve_in.png create mode 100644 tools/editor/icons/icon_curve_in_out.png create mode 100644 tools/editor/icons/icon_curve_linear.png create mode 100644 tools/editor/icons/icon_curve_out.png create mode 100644 tools/editor/icons/icon_curve_out_in.png create mode 100644 tools/editor/icons/icon_key_next.png create mode 100644 tools/editor/icons/icon_play_backwards.png create mode 100644 tools/editor/icons/icon_play_start.png create mode 100644 tools/editor/icons/icon_play_start_backwards.png diff --git a/core/object.cpp b/core/object.cpp index 1a51e79a9f2..84786df8d4d 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -995,12 +995,44 @@ Variant Object::get_meta(const String& p_name) const { return metadata[p_name]; } + Array Object::_get_property_list_bind() const { List lpi; get_property_list(&lpi); return convert_property_list(&lpi); } + +Array Object::_get_method_list_bind() const { + + List ml; + get_method_list(&ml); + Array ret; + + for(List::Element *E=ml.front();E;E=E->next()) { + + Dictionary d; + d["name"]=E->get().name; + d["args"]=convert_property_list(&E->get().arguments); + Array da; + for(int i=0;iget().default_arguments.size();i++) + da.push_back(E->get().default_arguments[i]); + d["default_args"]=da; + d["flags"]=E->get().flags; + d["id"]=E->get().id; + Dictionary r; + r["type"]=E->get().return_val.type; + r["hint"]=E->get().return_val.hint; + r["hint_string"]=E->get().return_val.hint_string; + d["return_type"]=r; + //va.push_back(d); + ret.push_back(d); + } + + return ret; + +} + DVector Object::_get_meta_list_bind() const { DVector _metaret; @@ -1439,6 +1471,7 @@ void Object::_bind_methods() { ObjectTypeDB::bind_method(_MD("set","property","value"),&Object::_set_bind); ObjectTypeDB::bind_method(_MD("get","property"),&Object::_get_bind); ObjectTypeDB::bind_method(_MD("get_property_list"),&Object::_get_property_list_bind); + ObjectTypeDB::bind_method(_MD("get_method_list"),&Object::_get_method_list_bind); ObjectTypeDB::bind_method(_MD("notification","what"),&Object::notification,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("get_instance_ID"),&Object::get_instance_ID); diff --git a/core/object.h b/core/object.h index fc64b91412c..8d1f8ebc5a5 100644 --- a/core/object.h +++ b/core/object.h @@ -54,6 +54,7 @@ enum PropertyHint { PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc" PROPERTY_HINT_EXP_EASING, /// exponential easing funciton (Math::ease) PROPERTY_HINT_LENGTH, ///< hint_text= "length" (as integer) + PROPERTY_HINT_SPRITE_FRAME, PROPERTY_HINT_KEY_ACCEL, ///< hint_text= "length" (as integer) PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags) PROPERTY_HINT_ALL_FLAGS, @@ -448,6 +449,7 @@ protected: DVector _get_meta_list_bind() const; Array _get_property_list_bind() const; + Array _get_method_list_bind() const; public: //should be protected, but bug in clang++ static void initialize_type(); diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp index 83d3155b036..b4c02ddbced 100644 --- a/core/os/main_loop.cpp +++ b/core/os/main_loop.cpp @@ -31,7 +31,20 @@ void MainLoop::_bind_methods() { - ObjectTypeDB::bind_method("input_event",&MainLoop::input_event); + ObjectTypeDB::bind_method(_MD("input_event","ev"),&MainLoop::input_event); + ObjectTypeDB::bind_method(_MD("input_text","text"),&MainLoop::input_text); + ObjectTypeDB::bind_method(_MD("init"),&MainLoop::init); + ObjectTypeDB::bind_method(_MD("iteration","delta"),&MainLoop::iteration); + ObjectTypeDB::bind_method(_MD("idle","delta"),&MainLoop::idle); + ObjectTypeDB::bind_method(_MD("finish"),&MainLoop::finish); + + BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"ev")) ); + BIND_VMETHOD( MethodInfo("_input_text",PropertyInfo(Variant::STRING,"text")) ); + BIND_VMETHOD( MethodInfo("_initialize") ); + BIND_VMETHOD( MethodInfo("_iteration",PropertyInfo(Variant::REAL,"delta")) ); + BIND_VMETHOD( MethodInfo("_idle",PropertyInfo(Variant::REAL,"delta")) ); + BIND_VMETHOD( MethodInfo("_finalize") ); + BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN); BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT); @@ -58,13 +71,15 @@ MainLoop::~MainLoop() void MainLoop::input_text( const String& p_text ) { + if (get_script_instance()) + get_script_instance()->call("_input_text",p_text); } void MainLoop::input_event( const InputEvent& p_event ) { if (get_script_instance()) - get_script_instance()->call("input_event",p_event); + get_script_instance()->call("_input_event",p_event); } @@ -74,13 +89,13 @@ void MainLoop::init() { set_script(init_script.get_ref_ptr()); if (get_script_instance()) - get_script_instance()->call("init"); + get_script_instance()->call("_initialize"); } bool MainLoop::iteration(float p_time) { if (get_script_instance()) - return get_script_instance()->call("iteration",p_time); + return get_script_instance()->call("_iteration",p_time); return false; @@ -88,14 +103,14 @@ bool MainLoop::iteration(float p_time) { bool MainLoop::idle(float p_time) { if (get_script_instance()) - return get_script_instance()->call("idle",p_time); + return get_script_instance()->call("_idle",p_time); return false; } void MainLoop::finish() { if (get_script_instance()) { - get_script_instance()->call("finish"); + get_script_instance()->call("_finalize"); set_script(RefPtr()); //clear script } diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index 312b04d4141..b49426f7e24 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -329,7 +329,7 @@ void AnimatedSprite::_bind_methods() { ADD_SIGNAL(MethodInfo("frame_changed")); ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "frames",PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames")); - ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame")); + ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered")); ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h")); diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index 0c0a0d78229..067b4794b44 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -320,7 +320,7 @@ void Sprite::_bind_methods() { ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v")); 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, "frame"), _SCS("set_frame"),_SCS("get_frame")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate")); 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/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 4952f742df6..e9da95f3fb6 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -580,7 +580,7 @@ void Sprite3D::_bind_methods() { 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, "frame"), _SCS("set_frame"),_SCS("get_frame")); + 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")); @@ -727,7 +727,7 @@ void AnimatedSprite3D::_bind_methods(){ ObjectTypeDB::bind_method(_MD("get_frame"),&AnimatedSprite3D::get_frame); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames")); - ADD_PROPERTY( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); ADD_SIGNAL(MethodInfo("frame_changed")); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 4949b33c475..6676f709815 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -967,14 +967,16 @@ String AnimationPlayer::get_current_animation() const { } -void AnimationPlayer::stop() { +void AnimationPlayer::stop(bool p_reset) { Playback &c=playback; c.blend.clear(); - c.current.from=NULL; + if (p_reset) { + c.current.from=NULL; + } _set_process(false); queued.clear(); - playing = false; + playing = false; } void AnimationPlayer::stop_all() { @@ -1211,7 +1213,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("stop"),&AnimationPlayer::stop); + 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); ObjectTypeDB::bind_method(_MD("set_current_animation","anim"),&AnimationPlayer::set_current_animation); diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 8d7d6d04e06..3fddc283ae0 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -260,7 +260,7 @@ public: void play(const StringName& p_name=StringName(),float p_custom_blend=-1,float p_custom_scale=1.0,bool p_from_end=false); void queue(const StringName& p_name); void clear_queue(); - void stop(); + void stop(bool p_reset=true); bool is_playing() const; String get_current_animation() const; void set_current_animation(const String& p_anim); diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp index 63ab186a38b..36fb6fb5f82 100644 --- a/tools/editor/animation_editor.cpp +++ b/tools/editor/animation_editor.cpp @@ -44,11 +44,207 @@ */ +class AnimationCurveEdit : public Control { + OBJ_TYPE( AnimationCurveEdit, Control ); +public: + enum Mode { + MODE_DISABLED, + MODE_SINGLE, + MODE_MULTIPLE + }; +private: + + Set multiples; + float transition; + Mode mode; + + void _notification(int p_what) { + + if (p_what==NOTIFICATION_DRAW) { + + + RID ci = get_canvas_item(); + + Size2 s = get_size(); + Rect2 r(Point2(),s); + + //r=r.grow(3); + Ref sb = get_stylebox("normal","LineEdit"); + sb->draw(ci,r); + r.size-=sb->get_minimum_size(); + r.pos+=sb->get_offset(); + //VisualServer::get_singleton()->canvas_item_add + + Ref f = get_font("font","Label"); + r=r.grow(-2); + Color color = get_color("font_color","Label"); + + int points = 48; + if (mode==MODE_MULTIPLE) { + + int max_draw = 16; + Color mcolor=color; + mcolor.a*=0.3; + + Set::Element *E=multiples.front(); + for(int j=0;j<16;j++) { + + if (!E) + break; + + float prev=1.0; + float exp=E->get(); + bool flip=false;//hint_text=="attenuation"; + + + for(int i=1;i<=points;i++) { + + float ifl = i/float(points); + float iflp = (i-1)/float(points); + + float h = 1.0-Math::ease(ifl,exp); + + if (flip) { + ifl=1.0-ifl; + iflp=1.0-iflp; + } + + VisualServer::get_singleton()->canvas_item_add_line(ci,r.pos+Point2(iflp*r.size.width,prev*r.size.height),r.pos+Point2(ifl*r.size.width,h*r.size.height),mcolor); + prev=h; + } + + E=E->next(); + } + } + + float exp=transition; + if (mode!=MODE_DISABLED) { + + + float prev=1.0; + + bool flip=false;//hint_text=="attenuation"; + + + for(int i=1;i<=points;i++) { + + float ifl = i/float(points); + float iflp = (i-1)/float(points); + + float h = 1.0-Math::ease(ifl,exp); + + if (flip) { + ifl=1.0-ifl; + iflp=1.0-iflp; + } + + VisualServer::get_singleton()->canvas_item_add_line(ci,r.pos+Point2(iflp*r.size.width,prev*r.size.height),r.pos+Point2(ifl*r.size.width,h*r.size.height),color); + prev=h; + } + } + + String txt=String::num(exp,2); + if (mode==MODE_DISABLED) { + txt="Disabled"; + } else if (mode==MODE_MULTIPLE) { + txt+=" - All Selection"; + } + + f->draw(ci,Point2(10,10+f->get_ascent()),txt,color); + + } + } + + void _input_event(const InputEvent& p_ev) { + if (p_ev.type==InputEvent::MOUSE_MOTION && p_ev.mouse_motion.button_mask&BUTTON_MASK_LEFT) { + + if (mode==MODE_DISABLED) + return; + + float rel = p_ev.mouse_motion.relative_x; + if (rel==0) + return; + + bool flip=false; + + if (flip) + rel=-rel; + + float val = transition; + if (val==0) + return; + bool sg = val < 0; + val = Math::absf(val); + + val = Math::log(val)/Math::log(2); + //logspace + val+=rel*0.05; + // + + val = Math::pow(2,val); + if (sg) + val=-val; + + transition=val; + update(); + //emit_signal("variant_changed"); + emit_signal("transition_changed",transition); + } + } + +public: + + static void _bind_methods() { + + // ObjectTypeDB::bind_method("_update_obj",&AnimationKeyEdit::_update_obj); + ObjectTypeDB::bind_method("_input_event",&AnimationCurveEdit::_input_event); + ADD_SIGNAL(MethodInfo("transition_changed")); + } + + void set_mode(Mode p_mode) { + + mode=p_mode; + update(); + } + + void clear_multiples() { multiples.clear(); update();} + void set_multiple(float p_transition) { + + multiples.insert(p_transition); + } + + void set_transition(float p_transition) { + transition=p_transition; + update(); + } + + float get_transition() const { + return transition; + } + + void force_transition(float p_value) { + if (mode==MODE_DISABLED) + return; + transition=p_value; + emit_signal("transition_changed",p_value); + update(); + } + + AnimationCurveEdit() { + + transition=1.0; + set_default_cursor_shape(CURSOR_HSPLIT); + mode=MODE_DISABLED; + } + +}; + class AnimationKeyEdit : public Object { OBJ_TYPE(AnimationKeyEdit,Object); public: bool setting; + bool hidden; static void _bind_methods() { @@ -56,12 +252,12 @@ public: ObjectTypeDB::bind_method("_key_ofs_changed",&AnimationKeyEdit::_key_ofs_changed); } - PopupDialog *ke_dialog; + //PopupDialog *ke_dialog; void _update_obj(const Ref &p_anim) { if (setting) return; - if (!ke_dialog->is_visible()) + if (hidden) return; if (!(animation==p_anim)) return; @@ -69,7 +265,7 @@ public: } void _key_ofs_changed(const Ref &p_anim,float from, float to) { - if (!ke_dialog->is_visible()) + if (hidden) return; if (!(animation==p_anim)) return; @@ -408,8 +604,8 @@ public: } break; } - if (animation->track_get_type(track)!=Animation::TYPE_METHOD) - p_list->push_back( PropertyInfo( Variant::REAL, "easing", PROPERTY_HINT_EXP_EASING)); + //if (animation->track_get_type(track)!=Animation::TYPE_METHOD) + // p_list->push_back( PropertyInfo( Variant::REAL, "easing", PROPERTY_HINT_EXP_EASING)); } UndoRedo *undo_redo; @@ -425,7 +621,7 @@ public: _change_notify(); } - AnimationKeyEdit() { key_ofs=0; track=-1; setting=false; } + AnimationKeyEdit() { hidden=true; key_ofs=0; track=-1; setting=false; } }; @@ -610,6 +806,8 @@ void AnimationKeyEditor::_menu_track(int p_type) { selection=new_selection; track_editor->update(); + _edit_if_single_selection(); + } @@ -689,8 +887,31 @@ void AnimationKeyEditor::_menu_track(int p_type) { optimize_dialog->popup_centered(Size2(250,180)); } break; + case CURVE_SET_LINEAR: { + curve_edit->force_transition(1.0); + } break; + case CURVE_SET_IN: { + curve_edit->force_transition(4.0); + + } break; + case CURVE_SET_OUT: { + + curve_edit->force_transition(0.25); + } break; + case CURVE_SET_INOUT: { + curve_edit->force_transition(-4); + + } break; + case CURVE_SET_OUTIN: { + + curve_edit->force_transition(-0.25); + } break; + case CURVE_SET_CONSTANT: { + + curve_edit->force_transition(0); + } break; } @@ -774,6 +995,7 @@ void AnimationKeyEditor::_track_editor_draw() { h_scroll->hide(); menu_track->set_disabled(true); edit_button->set_disabled(true); + key_editor_tab->hide(); move_up_button->set_disabled(true); move_down_button->set_disabled(true); remove_button->set_disabled(true); @@ -785,6 +1007,8 @@ void AnimationKeyEditor::_track_editor_draw() { move_up_button->set_disabled(false); move_down_button->set_disabled(false); remove_button->set_disabled(false); + if (edit_button->is_pressed()) + key_editor_tab->show(); te_drawing=true; @@ -1000,8 +1224,13 @@ void AnimationKeyEditor::_track_editor_draw() { } } + Color sep_color=color; + color.a*=0.5; + for(int i=0;iget_val() + i; if (idx>=animation->get_track_count()) break; @@ -1090,6 +1319,7 @@ void AnimationKeyEditor::_track_editor_draw() { float key_hofs = -Math::floor(type_icon[tt]->get_height()/2); int kc=animation->track_get_key_count(idx); + bool first=true; for(int i=0;itrack_get_key_value(idx,i); + if (first && i>0 && value==animation->track_get_key_value(idx,i-1)) { + + te->draw_line(ofs+Vector2(name_limit,y+h/2),ofs+Point2(x,y+h/2),color); + } + + if (itrack_get_key_value(idx,i+1)) { + float x_n = key_hofs + name_limit + (animation->track_get_key_time(idx,i+1)-keys_from)*zoom_scale; + + x_n = MIN( x_n, settings_limit); + te->draw_line(ofs+Point2(x_n,y+h/2),ofs+Point2(x,y+h/2),color); + + } + te->draw_texture(tex,ofs+Point2(x,y+key_vofs).floor()); + first=false; } } @@ -1226,7 +1471,9 @@ void AnimationKeyEditor::_clear_selection_for_anim(const Ref& p_anim) if (!(animation==p_anim)) return; - selection.clear(); + //selection.clear(); + _clear_selection(); + } void AnimationKeyEditor::_select_at_anim(const Ref& p_anim,int p_track,float p_pos){ @@ -1244,6 +1491,7 @@ void AnimationKeyEditor::_select_at_anim(const Ref& p_anim,int p_trac ki.pos=p_pos; selection.insert(sk,ki); + } @@ -1283,6 +1531,83 @@ PropertyInfo AnimationKeyEditor::_find_hint_for_track(int p_idx) { } +void AnimationKeyEditor::_curve_transition_changed(float p_what) { + + if (selection.size()==0) + return; + if (selection.size()==1) + undo_redo->create_action("Edit Node Curve",true); + else + undo_redo->create_action("Edit Selection Curve",true); + + for(Map::Element *E=selection.front();E;E=E->next()) { + + int track = E->key().track; + int key = E->key().key; + float prev_val = animation->track_get_key_transition(track,key); + undo_redo->add_do_method(animation.ptr(),"track_set_key_transition",track,key,p_what); + undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",track,key,prev_val); + } + + undo_redo->commit_action(); + +} + +void AnimationKeyEditor::_toggle_edit_curves() { + + if (edit_button->is_pressed()) + key_editor_tab->show(); + else + key_editor_tab->hide(); +} + + +bool AnimationKeyEditor::_edit_if_single_selection() { + + if (selection.size()!=1) { + + if (selection.size()==0) { + curve_edit->set_mode(AnimationCurveEdit::MODE_DISABLED); + print_line("disable"); + } else { + + curve_edit->set_mode(AnimationCurveEdit::MODE_MULTIPLE); + curve_edit->set_transition(1.0); + curve_edit->clear_multiples(); + //add all + for(Map::Element *E=selection.front();E;E=E->next()) { + + curve_edit->set_multiple(animation->track_get_key_transition(E->key().track,E->key().key)); + } + print_line("multiple"); + + } + return false; + } + curve_edit->set_mode(AnimationCurveEdit::MODE_SINGLE); + print_line("regular"); + + int idx = selection.front()->key().track; + int key = selection.front()->key().key; + { + + key_edit->animation=animation; + key_edit->track=idx; + key_edit->key_ofs=animation->track_get_key_time(idx,key); + key_edit->hint=_find_hint_for_track(idx); + key_edit->notify_change(); + + curve_edit->set_transition(animation->track_get_key_transition(idx,key)); + + /*key_edit_dialog->set_size( Size2( 200,200) ); + key_edit_dialog->set_pos( track_editor->get_global_pos() + ofs + mpos +Point2(-100,20)); + key_edit_dialog->popup();*/ + + } + + return true; + +} void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { @@ -1364,9 +1689,12 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { undo_redo->add_undo_method(animation.ptr(),"track_insert_key",E->key().track,E->get().pos,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key)); } + undo_redo->add_do_method(this,"_clear_selection_for_anim",animation); + undo_redo->add_undo_method(this,"_clear_selection_for_anim",animation); undo_redo->commit_action(); - selection.clear(); + //selection.clear(); accept_event(); + _edit_if_single_selection(); } } else if (animation.is_valid() && animation->get_track_count()>0) { @@ -1552,20 +1880,7 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { } - if (mb.mod.command || edit_button->is_pressed()) { - key_edit->animation=animation; - key_edit->track=idx; - key_edit->key_ofs=animation->track_get_key_time(idx,key); - key_edit->hint=_find_hint_for_track(idx); - - key_edit->notify_change(); - - key_edit_dialog->set_size( Size2( 200,200) ); - key_edit_dialog->set_pos( track_editor->get_global_pos() + ofs + mpos +Point2(-100,20)); - key_edit_dialog->popup(); - - } SelectedKey sk; sk.track=idx; @@ -1577,7 +1892,7 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { if (!mb.mod.shift && !selection.has(sk)) - selection.clear(); + _clear_selection(); selection.insert(sk,ki); @@ -1588,7 +1903,10 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { selected_track=idx; track_editor->update(); - + if (_edit_if_single_selection() && mb.mod.command) { + edit_button->set_pressed(true); + key_editor_tab->show(); + } } else { //button column int ofsx = size.width - mpos.x; @@ -1824,7 +2142,8 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { if (from_track>to_track) { if (!click.shift) - selection.clear(); + _clear_selection(); + _edit_if_single_selection(); break; } @@ -1842,12 +2161,13 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { if (from_track > tracks_to || to_track < tracks_from) { if (!click.shift) - selection.clear(); + _clear_selection(); + _edit_if_single_selection(); break; } if (!click.shift) - selection.clear(); + _clear_selection(); int higher_track=0x7FFFFFFF; @@ -1880,6 +2200,8 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { } + _edit_if_single_selection(); + } break; case ClickOver::CLICK_MOVE_KEYS: { @@ -1891,8 +2213,9 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { if (!click.shift) { KeyInfo ki=selection[click.selk]; - selection.clear(); + _clear_selection(); selection[click.selk]=ki; + _edit_if_single_selection(); } break; @@ -2007,6 +2330,7 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { } undo_redo->commit_action(); + _edit_if_single_selection(); } break; default: {} @@ -2348,20 +2672,33 @@ void AnimationKeyEditor::_notification(int p_what) { optimize_dialog->connect("confirmed",this,"_animation_optimize"); menu_track->get_popup()->add_child(tpp); - menu_track->get_popup()->add_submenu_item("Set Transitions..","Transitions"); - menu_track->get_popup()->add_separator(); + //menu_track->get_popup()->add_submenu_item("Set Transitions..","Transitions"); + //menu_track->get_popup()->add_separator(); menu_track->get_popup()->add_item("Optimize Animation",TRACK_MENU_OPTIMIZE); + curve_linear->set_icon(get_icon("CurveLinear","EditorIcons")); + curve_in->set_icon(get_icon("CurveIn","EditorIcons")); + curve_out->set_icon(get_icon("CurveOut","EditorIcons")); + curve_inout->set_icon(get_icon("CurveInOut","EditorIcons")); + curve_outin->set_icon(get_icon("CurveOutIn","EditorIcons")); + curve_constant->set_icon(get_icon("CurveConstant","EditorIcons")); - + curve_linear->connect("pressed",this,"_menu_track",varray(CURVE_SET_LINEAR)); + curve_in->connect("pressed",this,"_menu_track",varray(CURVE_SET_IN)); + curve_out->connect("pressed",this,"_menu_track",varray(CURVE_SET_OUT)); + curve_inout->connect("pressed",this,"_menu_track",varray(CURVE_SET_INOUT)); + curve_outin->connect("pressed",this,"_menu_track",varray(CURVE_SET_OUTIN)); + curve_constant->connect("pressed",this,"_menu_track",varray(CURVE_SET_CONSTANT)); move_up_button->set_icon(get_icon("MoveUp","EditorIcons")); move_down_button->set_icon(get_icon("MoveDown","EditorIcons")); remove_button->set_icon(get_icon("Remove","EditorIcons")); edit_button->set_icon(get_icon("EditKey","EditorIcons")); + edit_button->connect("pressed",this,"_toggle_edit_curves"); loop->set_icon(get_icon("Loop","EditorIcons")); + curve_edit->connect("transition_changed",this,"_curve_transition_changed"); //edit_button->add_color_override("font_color",get_color("font_color","Tree")); //edit_button->add_color_override("font_color_hover",get_color("font_color","Tree")); @@ -2456,6 +2793,17 @@ void AnimationKeyEditor::_update_menu() { updating=false; } +void AnimationKeyEditor::_clear_selection() { + + selection.clear(); + key_edit->animation=Ref(); + key_edit->track=0; + key_edit->key_ofs=0; + key_edit->hint=PropertyInfo(); + key_edit->notify_change(); + +} + void AnimationKeyEditor::set_animation(const Ref& p_anim) { @@ -2466,11 +2814,12 @@ void AnimationKeyEditor::set_animation(const Ref& p_anim) { animation->connect("changed",this,"_update_paths"); timeline_pos=0; - selection.clear(); + _clear_selection(); _update_paths(); _update_menu(); selected_track=-1; + _edit_if_single_selection(); } void AnimationKeyEditor::set_root(Node *p_root) { @@ -2591,6 +2940,7 @@ void AnimationKeyEditor::insert_transform_key(Spatial *p_node,const String& p_su id.value=p_xform; id.type=Animation::TYPE_TRANSFORM; id.query="node '"+p_node->get_name()+"'"; + id.advance=false; //dialog insert @@ -2643,6 +2993,7 @@ void AnimationKeyEditor::insert_node_value_key(Node* p_node, const String& p_pro id.value=p_value; id.type=Animation::TYPE_VALUE; id.query="property '"+p_property+"'"; + id.advance=false; //dialog insert _query_insert(id); @@ -2650,7 +3001,7 @@ void AnimationKeyEditor::insert_node_value_key(Node* p_node, const String& p_pro } -void AnimationKeyEditor::insert_value_key(const String& p_property,const Variant& p_value) { +void AnimationKeyEditor::insert_value_key(const String& p_property,const Variant& p_value,bool p_advance) { ERR_FAIL_COND(!root); //let's build a node path @@ -2696,6 +3047,7 @@ void AnimationKeyEditor::insert_value_key(const String& p_property,const Variant id.value=p_value; id.type=Animation::TYPE_VALUE; id.query="property '"+p_property+"'"; + id.advance=p_advance; //dialog insert _query_insert(id); @@ -2928,13 +3280,31 @@ void AnimationKeyEditor::_insert_delay() { undo_redo->create_action("Anim Insert"); int last_track = animation->get_track_count(); + bool advance=false; while(insert_data.size()) { + if (insert_data.front()->get().advance) + advance=true; last_track=_confirm_insert(insert_data.front()->get(),last_track); insert_data.pop_front(); } undo_redo->commit_action(); + + if (advance) { + float step = animation->get_step(); + if (step==0) + step=1; + + float pos=timeline_pos; + + pos=Math::stepify(pos+step,step); + if (pos>animation->get_length()) + pos=animation->get_length(); + timeline_pos=pos; + track_pos->update(); + emit_signal("timeline_changed",pos); + } insert_queue=false; } @@ -3122,12 +3492,15 @@ void AnimationKeyEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_animation"),&AnimationKeyEditor::set_animation); ObjectTypeDB::bind_method(_MD("_animation_optimize"),&AnimationKeyEditor::_animation_optimize); + ObjectTypeDB::bind_method(_MD("_curve_transition_changed"),&AnimationKeyEditor::_curve_transition_changed); + ObjectTypeDB::bind_method(_MD("_toggle_edit_curves"),&AnimationKeyEditor::_toggle_edit_curves); ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) ); ADD_SIGNAL( MethodInfo("keying_changed" ) ); ADD_SIGNAL( MethodInfo("timeline_changed", PropertyInfo(Variant::REAL,"pos") ) ); ADD_SIGNAL( MethodInfo("animation_len_changed", PropertyInfo(Variant::REAL,"len") ) ); + ADD_SIGNAL( MethodInfo("key_edited", PropertyInfo(Variant::INT,"track"), PropertyInfo(Variant::INT,"key") ) ); } @@ -3219,12 +3592,6 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h hb->add_child( memnew( VSeparator ) ); - edit_button = memnew( ToolButton ); - edit_button->set_toggle_mode(true); - edit_button->set_focus_mode(FOCUS_NONE); - edit_button->set_disabled(true); - hb->add_child(edit_button); - edit_button->set_tooltip("Enable editing of individual keys by clicking them."); move_up_button = memnew( ToolButton ); hb->add_child(move_up_button); @@ -3247,6 +3614,15 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h remove_button->set_disabled(true); remove_button->set_tooltip("Remove selected track."); + hb->add_child(memnew( VSeparator )); + + edit_button = memnew( ToolButton ); + edit_button->set_toggle_mode(true); + edit_button->set_focus_mode(FOCUS_NONE); + edit_button->set_disabled(true); + + hb->add_child(edit_button); + edit_button->set_tooltip("Enable editing of individual keys by clicking them."); optimize_dialog = memnew( ConfirmationDialog ); add_child(optimize_dialog); @@ -3297,7 +3673,7 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h // menu->get_popup()->connect("item_pressed",this,"_menu_callback"); ec = memnew (Control); - ec->set_custom_minimum_size(Size2(0,50)); + ec->set_custom_minimum_size(Size2(0,150)); add_child(ec); ec->set_v_size_flags(SIZE_EXPAND_FILL); @@ -3313,6 +3689,7 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h track_editor->set_focus_mode(Control::FOCUS_ALL); track_editor->set_h_size_flags(SIZE_EXPAND_FILL); + track_pos = memnew( Control ); track_pos->set_area_as_parent_rect(); track_pos->set_ignore_mouse(true); @@ -3325,6 +3702,56 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h v_scroll->connect("value_changed",this,"_scroll_changed"); v_scroll->set_val(0); + key_editor_tab = memnew(TabContainer); + hb->add_child(key_editor_tab); + key_editor_tab->set_custom_minimum_size(Size2(200,0)); + + key_editor = memnew( PropertyEditor ); + key_editor->set_area_as_parent_rect(); + key_editor->hide_top_label(); + key_editor->set_name("Key"); + key_editor_tab->add_child(key_editor); + + key_edit = memnew( AnimationKeyEdit ); + key_edit->undo_redo=undo_redo; + //key_edit->ke_dialog=key_edit_dialog; + key_editor->edit(key_edit); + type_menu = memnew( PopupMenu ); + add_child(type_menu); + for(int i=0;iadd_item(Variant::get_type_name(Variant::Type(i)),i); + type_menu->connect("item_pressed",this,"_create_value_item"); + + VBoxContainer *curve_vb = memnew( VBoxContainer ); + curve_vb->set_name("Transition"); + HBoxContainer *curve_hb = memnew( HBoxContainer ); + curve_vb->add_child(curve_hb); + + curve_linear = memnew( ToolButton ); + curve_linear->set_focus_mode(FOCUS_NONE); + curve_hb->add_child(curve_linear); + curve_in = memnew( ToolButton ); + curve_in->set_focus_mode(FOCUS_NONE); + curve_hb->add_child(curve_in); + curve_out = memnew( ToolButton ); + curve_out->set_focus_mode(FOCUS_NONE); + curve_hb->add_child(curve_out); + curve_inout = memnew( ToolButton ); + curve_inout->set_focus_mode(FOCUS_NONE); + curve_hb->add_child(curve_inout); + curve_outin = memnew( ToolButton ); + curve_outin->set_focus_mode(FOCUS_NONE); + curve_hb->add_child(curve_outin); + curve_constant = memnew( ToolButton ); + curve_constant->set_focus_mode(FOCUS_NONE); + curve_hb->add_child(curve_constant); + + + curve_edit = memnew( AnimationCurveEdit ); + curve_vb->add_child(curve_edit); + curve_edit->set_v_size_flags(SIZE_EXPAND_FILL); + key_editor_tab->add_child(curve_vb); + h_scroll = memnew( HScrollBar ); h_scroll->connect("value_changed",this,"_scroll_changed"); add_child(h_scroll); @@ -3340,7 +3767,7 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h add_child(track_menu); track_menu->connect("item_pressed",this,"_track_menu_selected"); - + key_editor_tab->hide(); last_idx =1; @@ -3359,24 +3786,6 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h timeline_pos=0; - key_edit_dialog = memnew( PopupDialog ); - key_editor = memnew( PropertyEditor ); - add_child(key_edit_dialog); - key_editor->set_area_as_parent_rect(); - key_editor->hide_top_label(); - for(int i=0;i<4;i++) - key_editor->set_margin(Margin(i),5); - key_edit_dialog->add_child(key_editor); - - key_edit = memnew( AnimationKeyEdit ); - key_edit->undo_redo=undo_redo; - key_edit->ke_dialog=key_edit_dialog; - key_editor->edit(key_edit); - type_menu = memnew( PopupMenu ); - add_child(type_menu); - for(int i=0;iadd_item(Variant::get_type_name(Variant::Type(i)),i); - type_menu->connect("item_pressed",this,"_create_value_item"); keying=false; insert_frame=0; insert_query=false; diff --git a/tools/editor/animation_editor.h b/tools/editor/animation_editor.h index 885d46cf6c5..35053fb6a34 100644 --- a/tools/editor/animation_editor.h +++ b/tools/editor/animation_editor.h @@ -37,6 +37,7 @@ #include "scene/gui/scroll_bar.h" #include "scene/gui/tool_button.h" #include "scene/gui/file_dialog.h" +#include "scene/gui/tab_container.h" #include "scene/resources/animation.h" #include "scene/animation/animation_cache.h" @@ -46,6 +47,7 @@ class AnimationKeyEdit; +class AnimationCurveEdit; class AnimationKeyEditor : public VBoxContainer { @@ -86,7 +88,13 @@ class AnimationKeyEditor : public VBoxContainer { TRACK_MENU_SET_ALL_TRANS_OUTIN, TRACK_MENU_NEXT_STEP, TRACK_MENU_PREV_STEP, - TRACK_MENU_OPTIMIZE + TRACK_MENU_OPTIMIZE, + CURVE_SET_LINEAR, + CURVE_SET_IN, + CURVE_SET_OUT, + CURVE_SET_INOUT, + CURVE_SET_OUTIN, + CURVE_SET_CONSTANT }; struct MouseOver { @@ -169,6 +177,14 @@ class AnimationKeyEditor : public VBoxContainer { ToolButton *move_down_button; ToolButton *remove_button; + ToolButton *curve_linear; + ToolButton *curve_in; + ToolButton *curve_out; + ToolButton *curve_inout; + ToolButton *curve_outin; + ToolButton *curve_constant; + + ConfirmationDialog *optimize_dialog; SpinBox *optimize_linear_error; SpinBox *optimize_angular_error; @@ -183,11 +199,11 @@ class AnimationKeyEditor : public VBoxContainer { Control *track_editor; Control *track_pos; + TabContainer *key_editor_tab; ConfirmationDialog *scale_dialog; SpinBox *scale; - PopupDialog *key_edit_dialog; PropertyEditor *key_editor; Ref animation; @@ -203,6 +219,7 @@ class AnimationKeyEditor : public VBoxContainer { AnimationKeyEdit *key_edit; + AnimationCurveEdit *curve_edit; bool inserting; @@ -220,6 +237,7 @@ class AnimationKeyEditor : public VBoxContainer { int track_idx; Variant value; String query; + bool advance; };/* insert_data;*/ bool insert_query; @@ -254,7 +272,7 @@ class AnimationKeyEditor : public VBoxContainer { void _scale(); - + void _clear_selection(); //void _browse_path(); @@ -270,12 +288,15 @@ class AnimationKeyEditor : public VBoxContainer { void _clear_selection_for_anim(const Ref& p_anim); void _select_at_anim(const Ref& p_anim,int p_track,float p_pos); + void _curve_transition_changed(float p_what); PropertyInfo _find_hint_for_track(int p_idx); void _create_value_item(int p_type); void _pane_drag(const Point2& p_delta); + bool _edit_if_single_selection(); + void _toggle_edit_curves(); void _animation_len_update(); void _root_removed(); @@ -296,7 +317,7 @@ public: void set_anim_pos(float p_pos); void insert_node_value_key(Node* p_node, const String& p_property,const Variant& p_value,bool p_only_if_exists=false); - void insert_value_key(const String& p_property,const Variant& p_value); + void insert_value_key(const String& p_property, const Variant& p_value, bool p_advance); void insert_transform_key(Spatial *p_node,const String& p_sub,const Transform& p_xform); AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_history, EditorSelection *p_selection); diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp index 8e96123c36d..ae083db0ff3 100644 --- a/tools/editor/editor_file_system.cpp +++ b/tools/editor/editor_file_system.cpp @@ -989,6 +989,7 @@ EditorFileSystemDirectory *EditorFileSystem::get_path(const String& p_path) { void EditorFileSystem::_resource_saved(const String& p_path){ + print_line("resource saved: "+p_path); EditorFileSystem::get_singleton()->update_file(p_path); } diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 56b813344ab..7157dbda965 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -2838,9 +2838,9 @@ void EditorNode::_instance_request(const String& p_path){ request_instance_scene(p_path); } -void EditorNode::_property_keyed(const String& p_keyed,const Variant& p_value) { +void EditorNode::_property_keyed(const String& p_keyed,const Variant& p_value,bool p_advance) { - animation_editor->insert_value_key(p_keyed,p_value); + animation_editor->insert_value_key(p_keyed,p_value,p_advance); } void EditorNode::_transform_keyed(Object *sp,const String& p_sub,const Transform& p_key) { diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index 76e82b5a6b6..614cec5bcc1 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -348,7 +348,7 @@ class EditorNode : public Node { void _instance_request(const String& p_path); - void _property_keyed(const String& p_keyed,const Variant& p_value); + void _property_keyed(const String& p_keyed, const Variant& p_value, bool p_advance); void _transform_keyed(Object *sp,const String& p_sub,const Transform& p_key); void _update_keying(); diff --git a/tools/editor/icons/icon_curve_constant.png b/tools/editor/icons/icon_curve_constant.png new file mode 100644 index 0000000000000000000000000000000000000000..cdeac1785e74233036678fcdf2b102c63e67a7a9 GIT binary patch literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&kwj^(N7a$D;Kb?2i11Zh|kH}&M z25un`X1sK_?hjCqy~NYkmHj@eB!eKs%qbi6fkN4yE{-7@=g(eH#kd7jch!oEhff&+V%I&p0D;)6)Ze3=W6l6((4L6Goo5pberr& zKczq3BC54?&$UNCUvD_tRNL2~oF{SZW!;AZlHWxHW&J9`YF^$CYLJMWI_n|Gc?_Pe KelF{r5}E)^J5B!p literal 0 HcmV?d00001 diff --git a/tools/editor/icons/icon_curve_in.png b/tools/editor/icons/icon_curve_in.png new file mode 100644 index 0000000000000000000000000000000000000000..2db202632e0edcb7d825fa5f07a89fb1a4386b4a GIT binary patch literal 319 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&kwj^(N7a$D;Kb?2i11Zh|kH}&M z25un`X1sK_?hjCqy~NYkmHj@eB!eJ7r}o-?K%q09E{-7@=X)m^<{fenaGigaiK$bm zROyTMsx1WqD_-pM@SA8R#Jh6M90eyCW!Jii)(VkE7kYFH64RGneB<#u{a#J3+wqOO z4JtYI%%88QPAG|g*D(Leb=eb2agDYA`Z=8+sJhfwp6A=SMCb<7{lfPmKFZ+}H|u@d zwJt~f_T#FB?e2*WJ%TcSGsvj!b^ortZFWZDo}2%27B880ox%AwYr(`V8*Ld@9ZSA# zoWQxJf%OARjmNJ|wi8R%ZB(6j=&@-56W0UtAI6@~f4^reU_NstYeL3yp$R~LF?hQA KxvX literal 0 HcmV?d00001 diff --git a/tools/editor/icons/icon_curve_linear.png b/tools/editor/icons/icon_curve_linear.png new file mode 100644 index 0000000000000000000000000000000000000000..9467dc97a378566c47ea34e750d6634eeb9cc185 GIT binary patch literal 275 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&kwj^(N7a$D;Kb?2i11Zh|kH}&M z25un`X1sK_?hjCqy~NYkmHj@eB!dvQYPMAhP-uati(`n!`QC|!Tug=nuJJ_;TVrxm z9yGNcGOOm#f0gU<<{u|Z_mUFbIUW(4E}G1oX=B&lxwue8(CNfi2AjW9GZH=L_Ua#4 z$t7NzUOr_Ddx0+RYvBvbf)zhSdwb939mx3bhc_!j=2W?-{L(Hrma+rPGd|n2G_23K z(|9srdh@9RLVlC_!geoxS7hxOH2(^f1JYaex8FUHI`<*a Otqh*7elF{r5}E*{He|K{ literal 0 HcmV?d00001 diff --git a/tools/editor/icons/icon_curve_out.png b/tools/editor/icons/icon_curve_out.png new file mode 100644 index 0000000000000000000000000000000000000000..c91ade6f4a731ad1124797a72e2a1040530c7765 GIT binary patch literal 319 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&kwj^(N7a$D;Kb?2i11Zh|kH}&M z25un`X1sK_?hjCqy~NYkmHj@eB!i&odG!*IF=sqo978nD*G|$cVsaE{-LDuuJL$Z@ z$0BAGwI<;L)|@WsBL!V^6demVbT(@6_&?ATF`Rw$Ou%8GXER^EdiOmzR=8sWZ-Yt> zyXV}uQWdOj2c$npUfQ(8MaIkO_B-= z+L?*FPd<*Dn!7yX{kHwdvFV?!FKvE%s%-Y{`#Py-m)twHePM&6&3&049eeNBPZd^7 zo68WtE!(qRwVkVi(dq$1iRxDuiQ~p%Q;QGDMSS0XTsel}l}$-Oyj7w;&|eImu6{1- HoD!M<8Blc3 literal 0 HcmV?d00001 diff --git a/tools/editor/icons/icon_curve_out_in.png b/tools/editor/icons/icon_curve_out_in.png new file mode 100644 index 0000000000000000000000000000000000000000..6499fa753ea4f29e71cf8d7301393489760b9120 GIT binary patch literal 318 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&kwj^(N7a$D;Kb?2i11Zh|kH}&M z25un`X1sK_?hjCqy~NYkmHj@eB!dvk)+_2?fkLM}T^vI+&i76<^kQ`saJm2He|FM> zMh-WzjI4L6HZ7eSXD(=5k?^gUKS6(O1uVjoAsT0clDl2PUMfIA;Ao;bd#n zG3UI{eSz{<9QUr;%6eea%Ux`JSBxLXRCoog+M)6@NHc4C%G!I(%MWmWnDb=uzaNpa zH%7YjepsP5d*Sb$w->xymH+DA`b8Ii`CYlbf1RzF%&O^sgzvk~n;Pr7{TRrn44$rj JF6*2Ung9+0goFS9 literal 0 HcmV?d00001 diff --git a/tools/editor/icons/icon_key_next.png b/tools/editor/icons/icon_key_next.png new file mode 100644 index 0000000000000000000000000000000000000000..759008d064930406522ce842b4e2438db690cdad GIT binary patch literal 499 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE%y{W;-5;PJdx@v7EBk#`NhW=bcL~>z0fl5ULn2C?^K)}k^GbkR1_tM%)Wnk1 z6ovB4k_-iRPv3wPy;ODv2F7qt7sn8b(^Dtedmj!EIeNZU|6oH&VYV`-tkugKu8s?v zC$Ek_<~{58_vF8SSeMXx z$e?8FwXG(;%;!JzXsI0K_MGXXHrK>={gfcHhQ@2Z?v>u1Zq%R^m$o^w_lf06;YsJc zR^C#y(k*vEK7aN;_{XF?9mORm5F z{&s7F0S~{ppdG^tozr?ALI)Py%{#uDA*^nO-*VmLGrSGTYfH^NCxr`UPB8IWnHb5! z&CsM^(Xr@7n2VpM9n+5-v)S)e+?6JU)-GmcP`ad8$@AdkwzunE?|OJ>ea=5ti@whe zMH0t9-m9@I7Yi0-sJZ`tvv#T-!-DItS0*LK?Rg{mw|>ggWik8Sdw%y{W;-5;PJdx@v7EBk#`2|+b$*#qISK%qiU7sn8b({Cpm@--;%xXK@U@JzDG z&D{UN3sKAF**ZHCE-^H5b~n$xb^Xcm+`5IvJ$iGBg$3Tt>zHH8XQ0+3U2vp^Z5rEo zHI9bXyg9tf)$WVjNAVx48p4-le!AjOope*|JWJSL6a9+%7)MJb$@gpd R<^nBe@O1TaS?83{1OWa%OB(v7D?beqU2`yd~RW+)r?-{(r7~^xR^4_ltG@iBW*{e@& z?Qgr8r|2-fNKgshwQgBv)+&i*^;3O*+`7|~xPFC{y>`CQy1WUK9@drUXB(M4n=t9o zzv`rWk8bR+JSk!?HFNvVMb@6i@wzk4a9D|`rTHAwm?61)Z{oA|=6u7Gkt`D!PG9cZ z{8{+dzNJDlkOW*elF{r G5}E)Dp^|6- diff --git a/tools/editor/icons/icon_play.png b/tools/editor/icons/icon_play.png index 08cce495a94591dec78f50b2bf22dcd1abc24593..d2bd9d310c13863102e45f0773c3b4aa8572103c 100644 GIT binary patch delta 212 zcmV;_04x810)zsPBo78+OGiWi000000Qp0^e~}>=e+P6)O+^Ra1sD-17$GDJ;Q#;t zkx4{BR5;76lQ9ayKoCV=CIP`*Vh*B*v9;DSSZJNr%XpA~iKJ4rSwWV_&XW9QXBOUL z7#LV9l3GcdTF$;Oum>)w@2dnr3+#Y{q&IMmitMNEfNiQzQIY-m@1r6sOjs0Ia96qL zSSz4*ItO{i^xoXP0fwj`2d@C`K9&SUa8B?9rYM*TUcdvmN5R#OX>mRy{YAe;p`--> O0000MO|b$)>3p9kv%hKRzVVP z$Or%zLg@26KU7t9VP;pBrF_~z03d|W7e&$5b=^AWdH{Hq*91yLcS~_iK&ra+-d`=n eB;UO9?|A^8By;FWK>W!70000%y{W;-5;PJdx@v7EBk#`2|;xsx6FSAK%rhw7sn8b(|acy@*OhZag|SW$kKn< zd>}Dm=4nZZgtVtdGEd?c-CeawB}mmLWV_J3KkeTqSs4A%y{W;-5;PJdx@v7EBk#`2|*3+rL(;3fkMkYT^vI!PVb%U%XP?s$8G*hr}Yz^ zMY;kC*I)mbC3j$|$Pwe3^n%!~*&JKDU-ln$P-yuncT%NM*C%LFh+B-8SMk=}6*Ua! zChlg^FR%A9Dt}+hz$|ouVfqI)3(u@ZtyP<37#2u8>H5HxvE0EdP&Qa$_DBE73Az&3 zBud!(zP;wsVXQg!lOe18KC^kW;u_^+cdMhdWwu}7ZHcW2+i_E?UiR{X1w#KfnLlBT V*Jghi=?Zi*gQu&X%Q~loCIF7cVOanG literal 0 HcmV?d00001 diff --git a/tools/editor/icons/icon_play_start_backwards.png b/tools/editor/icons/icon_play_start_backwards.png new file mode 100644 index 0000000000000000000000000000000000000000..09afac637c41be20e5c006935db62e1cc3ab9a5e GIT binary patch literal 289 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE%y{W;-5;PJdx@v7EBk#`2|;z$e^;XIfkNv%T^vI!PVb$3m-CQ=K#RS8`i_S}Ddzbzoe!>(_tv&iGsSMp5 zi3XefE^$RLMa#=J7XS0)m@?_xfrIYW@%aZ-_Xt--d#!4e(rCQ1+MQ28sfB+}ddp5H zx0c=|*{ddmJeqRwhYGEK8qE2 c6MspSyT!(x+3{963FvYLPgg&ebxsLQ0OY!4&j0`b literal 0 HcmV?d00001 diff --git a/tools/editor/icons/icon_stop.png b/tools/editor/icons/icon_stop.png index fd568b61a8fc395e8a18e17827a1f25c1e881ddb..0fd43b403a11dc93e772b7d44586e64d42cf70db 100644 GIT binary patch delta 188 zcmeBTe8V_Fg`X|S+uel$41PNAuAitVQO{oD>FdgVpH)IoLx*9){}7;LrKgKyh{fr* zlQ(iT81T5nyOz8*e#9Bn%QU4; zu|FC9Y8Eg~`nX~hXUDSD{6603KW={cs@vm(-h#*-k3{cYcK^e?Pin&KODV^X oYb#xmdKI;Vst0J6SJBLDyZ delta 109 zcmaFE*u^+OC5^MdBeIx*fm;ZK886+f`@_J%VB_iH7-G?zoFFmf!QbECeU7Y3b-8rp z-^a(t<&R_p1q3v_cHZ{Ve&aSJ=0$U@vJM0oHV7`)3S!jstbD-8&@9cn>0w>+KA<@a Mp00i_>zopr03|#tKmY&$ diff --git a/tools/editor/plugins/animation_player_editor_plugin.cpp b/tools/editor/plugins/animation_player_editor_plugin.cpp index fee2f4f977a..9a93eed9694 100644 --- a/tools/editor/plugins/animation_player_editor_plugin.cpp +++ b/tools/editor/plugins/animation_player_editor_plugin.cpp @@ -28,7 +28,8 @@ /*************************************************************************/ #include "animation_player_editor_plugin.h" #include "io/resource_loader.h" - +#include "os/keyboard.h" +#include "tools/editor/editor_settings.h" void AnimationPlayerEditor::_node_removed(Node *p_node) { @@ -100,12 +101,18 @@ void AnimationPlayerEditor::_notification(int p_what) { remove_anim->set_icon( get_icon("Del","EditorIcons") ); edit_anim->set_icon( get_icon("Edit","EditorIcons") ); blend_anim->set_icon( get_icon("Blend","EditorIcons") ); - play->set_icon( get_icon("Play","EditorIcons") ); + play->set_icon( get_icon("PlayStart","EditorIcons") ); + play_from->set_icon( get_icon("Play","EditorIcons") ); + play_bw->set_icon( get_icon("PlayStartBackwards","EditorIcons") ); + play_bw_from->set_icon( get_icon("PlayBackwards","EditorIcons") ); + autoplay_icon=get_icon("AutoPlay","EditorIcons"); stop->set_icon( get_icon("Stop","EditorIcons") ); resource_edit_anim->set_icon( get_icon("EditResource","EditorIcons") ); pin->set_normal_texture(get_icon("Pin","EditorIcons") ); pin->set_pressed_texture( get_icon("PinPressed","EditorIcons") ); + tool_anim->set_icon(get_icon("Tools","EditorIcons")); + tool_anim->get_popup()->connect("item_pressed",this,"_animation_tool_menu"); blend_editor.next->connect("text_changed",this,"_blend_editor_next_changed"); @@ -180,9 +187,82 @@ void AnimationPlayerEditor::_play_pressed() { //unpause //pause->set_pressed(false); } + +void AnimationPlayerEditor::_play_from_pressed() { + + String current; + if (animation->get_selected()>=0 && animation->get_selected()get_item_count()) { + + current = animation->get_item_text( animation->get_selected() ); + } + + if (current!="") { + + float time = player->get_current_animation_pos(); + + if (current==player->get_current_animation() && player->is_playing()) { + + player->stop(); //so it wont blend with itself + } + + player->play( current ); + player->seek(time); + } + + //unstop + stop->set_pressed(false); + //unpause + //pause->set_pressed(false); +} + + +void AnimationPlayerEditor::_play_bw_pressed() { + + String current; + if (animation->get_selected()>=0 && animation->get_selected()get_item_count()) { + + current = animation->get_item_text( animation->get_selected() ); + } + + if (current!="") { + + if (current==player->get_current_animation()) + player->stop(); //so it wont blend with itself + player->play(current,-1,-1,true); + } + + //unstop + stop->set_pressed(false); + //unpause + //pause->set_pressed(false); +} + +void AnimationPlayerEditor::_play_bw_from_pressed() { + + String current; + if (animation->get_selected()>=0 && animation->get_selected()get_item_count()) { + + current = animation->get_item_text( animation->get_selected() ); + } + + if (current!="") { + + float time = player->get_current_animation_pos(); + if (current==player->get_current_animation()) + player->stop(); //so it wont blend with itself + + player->play(current,-1,-1,true); + player->seek(time); + } + + //unstop + stop->set_pressed(false); + //unpause + //pause->set_pressed(false); +} void AnimationPlayerEditor::_stop_pressed() { - player->stop(); + player->stop(false); play->set_pressed(false); stop->set_pressed(true); //pause->set_pressed(false); @@ -598,6 +678,9 @@ void AnimationPlayerEditor::_update_player() { stop->set_disabled(animlist.size()==0); play->set_disabled(animlist.size()==0); + play_bw->set_disabled(animlist.size()==0); + play_bw_from->set_disabled(animlist.size()==0); + play_from->set_disabled(animlist.size()==0); autoplay->set_disabled(animlist.size()==0); duplicate_anim->set_disabled(animlist.size()==0); rename_anim->set_disabled(animlist.size()==0); @@ -877,11 +960,108 @@ void AnimationPlayerEditor::_hide_anim_editors() { } } + +void AnimationPlayerEditor::_animation_tool_menu(int p_option) { + + switch(p_option) { + + case TOOL_COPY_ANIM: { + + if (!animation->get_item_count()) { + error_dialog->set_text("ERROR: No animation to copy!"); + error_dialog->popup_centered_minsize(); + return; + } + + String current = animation->get_item_text(animation->get_selected()); + Ref anim = player->get_animation(current); + //editor->edit_resource(anim); + EditorSettings::get_singleton()->set_resource_clipboard(anim); + + } break; + case TOOL_PASTE_ANIM: { + + Ref anim = EditorSettings::get_singleton()->get_resource_clipboard(); + if (!anim.is_valid()) { + error_dialog->set_text("ERROR: No animation resource on clipboard!"); + error_dialog->popup_centered_minsize(); + return; + } + + String name = anim->get_name(); + if (name=="") { + name="Pasted Animation"; + } + + int idx=1; + String base = name; + while (player->has_animation(name)) { + + idx++; + name=base+" "+itos(idx); + } + + undo_redo->create_action("Paste Animation"); + undo_redo->add_do_method(player,"add_animation",name,anim); + undo_redo->add_undo_method(player,"remove_animation",name); + undo_redo->add_do_method(this,"_animation_player_changed",player); + undo_redo->add_undo_method(this,"_animation_player_changed",player); + undo_redo->commit_action(); + + _select_anim_by_name(name); + + + } break; + case TOOL_EDIT_RESOURCE: { + + if (!animation->get_item_count()) { + error_dialog->set_text("ERROR: No animation to edit!"); + error_dialog->popup_centered_minsize(); + return; + } + + String current = animation->get_item_text(animation->get_selected()); + Ref anim = player->get_animation(current); + editor->edit_resource(anim); + + } break; + + } +} + +void AnimationPlayerEditor::_unhandled_key_input(const InputEvent& p_ev) { + + if (is_visible() && p_ev.type==InputEvent::KEY && p_ev.key.pressed && !p_ev.key.echo && !p_ev.key.mod.alt && !p_ev.key.mod.control && !p_ev.key.mod.meta) { + + switch(p_ev.key.scancode) { + + case KEY_A: { + if (!p_ev.key.mod.shift) + _play_bw_from_pressed(); + else + _play_bw_pressed(); + } break; + case KEY_S: { + _stop_pressed(); + } break; + case KEY_D: { + if (!p_ev.key.mod.shift) + _play_from_pressed(); + else + _play_pressed(); + } break; + } + } +} + void AnimationPlayerEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_input_event"),&AnimationPlayerEditor::_input_event); ObjectTypeDB::bind_method(_MD("_node_removed"),&AnimationPlayerEditor::_node_removed); ObjectTypeDB::bind_method(_MD("_play_pressed"),&AnimationPlayerEditor::_play_pressed); + ObjectTypeDB::bind_method(_MD("_play_from_pressed"),&AnimationPlayerEditor::_play_from_pressed); + ObjectTypeDB::bind_method(_MD("_play_bw_pressed"),&AnimationPlayerEditor::_play_bw_pressed); + ObjectTypeDB::bind_method(_MD("_play_bw_from_pressed"),&AnimationPlayerEditor::_play_bw_from_pressed); ObjectTypeDB::bind_method(_MD("_stop_pressed"),&AnimationPlayerEditor::_stop_pressed); ObjectTypeDB::bind_method(_MD("_autoplay_pressed"),&AnimationPlayerEditor::_autoplay_pressed); ObjectTypeDB::bind_method(_MD("_pause_pressed"),&AnimationPlayerEditor::_pause_pressed); @@ -908,6 +1088,8 @@ void AnimationPlayerEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_hide_anim_editors"),&AnimationPlayerEditor::_hide_anim_editors); ObjectTypeDB::bind_method(_MD("_animation_duplicate"),&AnimationPlayerEditor::_animation_duplicate); ObjectTypeDB::bind_method(_MD("_blend_editor_next_changed"),&AnimationPlayerEditor::_blend_editor_next_changed); + ObjectTypeDB::bind_method(_MD("_unhandled_key_input"),&AnimationPlayerEditor::_unhandled_key_input); + ObjectTypeDB::bind_method(_MD("_animation_tool_menu"),&AnimationPlayerEditor::_animation_tool_menu); @@ -935,47 +1117,56 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { add_child(hb); - add_anim = memnew( Button ); + add_anim = memnew( ToolButton ); add_anim->set_tooltip("Create new animation in player."); hb->add_child(add_anim); - - load_anim = memnew( Button ); + load_anim = memnew( ToolButton ); load_anim->set_tooltip("Load an animation from disk."); hb->add_child(load_anim); - duplicate_anim = memnew( Button ); + duplicate_anim = memnew( ToolButton ); hb->add_child(duplicate_anim); duplicate_anim->set_tooltip("Duplicate Animation"); + rename_anim = memnew( ToolButton ); + hb->add_child(rename_anim); + rename_anim->set_tooltip("Rename Animation"); + + remove_anim = memnew( ToolButton ); + + hb->add_child(remove_anim); + remove_anim->set_tooltip("Remove Animation"); + + animation = memnew( OptionButton ); hb->add_child(animation); animation->set_h_size_flags(SIZE_EXPAND_FILL); animation->set_tooltip("Display list of animations in player."); - autoplay = memnew( Button ); + autoplay = memnew( ToolButton ); hb->add_child(autoplay); autoplay->set_tooltip("Autoplay On Load"); - rename_anim = memnew( Button ); - hb->add_child(rename_anim); - rename_anim->set_tooltip("Rename Animation"); - remove_anim = memnew( Button ); - - hb->add_child(remove_anim); - remove_anim->set_tooltip("Remove Animation"); - - blend_anim = memnew( Button ); + blend_anim = memnew( ToolButton ); hb->add_child(blend_anim); blend_anim->set_tooltip("Edit Target Blend Times"); + tool_anim = memnew( MenuButton); + //tool_anim->set_flat(false); + tool_anim->set_tooltip("Animation Tools"); + tool_anim->get_popup()->add_item("Copy Animation",TOOL_COPY_ANIM); + tool_anim->get_popup()->add_item("Paste Animation",TOOL_PASTE_ANIM); + //tool_anim->get_popup()->add_separator(); + //tool_anim->get_popup()->add_item("Edit Anim Resource",TOOL_PASTE_ANIM); + hb->add_child(tool_anim); - edit_anim = memnew( Button ); + edit_anim = memnew( ToolButton ); edit_anim->set_toggle_mode(true); hb->add_child(edit_anim); edit_anim->set_tooltip("Open animation editor.\nProperty editor will displays all editable keys too."); @@ -984,15 +1175,29 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { hb = memnew (HBoxContainer); add_child(hb); - play = memnew( Button ); - play->set_tooltip("Play selected animation."); + play_bw_from = memnew( ToolButton ); + play_bw_from->set_tooltip("Play backwards selected animation from current pos. (A)"); + hb->add_child(play_bw_from); - hb->add_child(play); + play_bw = memnew( ToolButton ); + play_bw->set_tooltip("Play backwards selected animation from end. (Shift+A)"); + hb->add_child(play_bw); - stop = memnew( Button ); + stop = memnew( ToolButton ); stop->set_toggle_mode(true); hb->add_child(stop); - play->set_tooltip("Stop animation playback."); + stop->set_tooltip("Stop animation playback. (S)"); + + play = memnew( ToolButton ); + play->set_tooltip("Play selected animation from start. (Shift+D)"); + hb->add_child(play); + + + play_from = memnew( ToolButton ); + play_from->set_tooltip("Play selected animation from current pos. (D)"); + hb->add_child(play_from); + + //pause = memnew( Button ); //pause->set_toggle_mode(true); @@ -1024,6 +1229,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { resource_edit_anim= memnew( Button ); hb->add_child(resource_edit_anim); + resource_edit_anim->hide(); file = memnew(FileDialog); @@ -1074,7 +1280,10 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { autoplay->connect("pressed", this,"_autoplay_pressed"); autoplay->set_toggle_mode(true); - play->connect("pressed", this,"_play_pressed"); + play->connect("pressed", this,"_play_pressed"); + play_from->connect("pressed", this,"_play_from_pressed"); + play_bw->connect("pressed", this,"_play_bw_pressed"); + play_bw_from->connect("pressed", this,"_play_bw_from_pressed"); stop->connect("pressed", this,"_stop_pressed"); //pause->connect("pressed", this,"_pause_pressed"); add_anim->connect("pressed", this,"_animation_new"); @@ -1104,6 +1313,8 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { renaming=false; last_active=false; + + set_process_unhandled_key_input(true); } diff --git a/tools/editor/plugins/animation_player_editor_plugin.h b/tools/editor/plugins/animation_player_editor_plugin.h index 380dfd19036..5c9dc6cab84 100644 --- a/tools/editor/plugins/animation_player_editor_plugin.h +++ b/tools/editor/plugins/animation_player_editor_plugin.h @@ -49,10 +49,19 @@ class AnimationPlayerEditor : public VBoxContainer { EditorNode *editor; AnimationPlayer *player; + enum { + TOOL_COPY_ANIM, + TOOL_PASTE_ANIM, + TOOL_EDIT_RESOURCE + }; OptionButton *animation; Button *stop; Button *play; + Button *play_from; + Button *play_bw; + Button *play_bw_from; + // Button *pause; Button *add_anim; Button *autoplay; @@ -63,6 +72,7 @@ class AnimationPlayerEditor : public VBoxContainer { Button *load_anim; Button *blend_anim; Button *remove_anim; + MenuButton *tool_anim; TextureButton *pin; Label *nodename; SpinBox *frame; @@ -95,6 +105,9 @@ class AnimationPlayerEditor : public VBoxContainer { void _select_anim_by_name(const String& p_anim); void _play_pressed(); + void _play_from_pressed(); + void _play_bw_pressed(); + void _play_bw_from_pressed(); void _autoplay_pressed(); void _stop_pressed(); void _pause_pressed(); @@ -126,6 +139,8 @@ class AnimationPlayerEditor : public VBoxContainer { void _animation_key_editor_seek(float p_pos); void _animation_key_editor_anim_len_changed(float p_new); + void _unhandled_key_input(const InputEvent& p_ev); + void _animation_tool_menu(int p_option); AnimationPlayerEditor(); protected: diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 1c6e57beaab..559267dc073 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -2629,7 +2629,12 @@ void PropertyEditor::update_tree() { if (keying) { - item->add_button(1,get_icon("Key","EditorIcons"),2); + if (p.hint==PROPERTY_HINT_SPRITE_FRAME) { + + item->add_button(1,get_icon("KeyNext","EditorIcons"),5); + } else { + item->add_button(1,get_icon("Key","EditorIcons"),2); + } } if (get_instanced_node()) { @@ -2904,6 +2909,16 @@ void PropertyEditor::edit(Object* p_object) { } +void PropertyEditor::_set_range_def(Object *p_item, String prop,float p_frame) { + + TreeItem *ti = p_item->cast_to(); + ERR_FAIL_COND(!ti); + + ti->call_deferred("set_range",1, p_frame); + obj->call_deferred("set",prop,p_frame); + +} + void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) { TreeItem *ti = p_item->cast_to(); ERR_FAIL_COND(!ti); @@ -2915,7 +2930,15 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) { if (!d.has("name")) return; String prop=d["name"]; - emit_signal("property_keyed",prop,obj->get(prop)); + emit_signal("property_keyed",prop,obj->get(prop),false); + } else if (p_button==5) { + print_line("PB5"); + if (!d.has("name")) + return; + String prop=d["name"]; + emit_signal("property_keyed",prop,obj->get(prop),true); + //set_range(p_column, ti->get_range(p_column)+1.0 ); + call_deferred("_set_range_def",ti,prop,ti->get_range(p_column)+1.0); } else if (p_button==3) { if (!get_instanced_node()) @@ -3046,6 +3069,7 @@ void PropertyEditor::_bind_methods() { ObjectTypeDB::bind_method( "_edit_button",&PropertyEditor::_edit_button); ObjectTypeDB::bind_method( "_changed_callback",&PropertyEditor::_changed_callbacks); ObjectTypeDB::bind_method( "_draw_flags",&PropertyEditor::_draw_flags); + ObjectTypeDB::bind_method( "_set_range_def",&PropertyEditor::_set_range_def); ADD_SIGNAL( MethodInfo("property_toggled",PropertyInfo( Variant::STRING, "property"),PropertyInfo( Variant::BOOL, "value"))); ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) ); diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h index 7a7354c88e6..164643afaa6 100644 --- a/tools/editor/property_editor.h +++ b/tools/editor/property_editor.h @@ -187,6 +187,7 @@ class PropertyEditor : public Control { Node *get_instanced_node(); void _refresh_item(TreeItem *p_item); + void _set_range_def(Object *p_item, String prop, float p_frame); UndoRedo *undo_redo; protected: From c85a526a21effb3efa0e64766d098e3729b0a432 Mon Sep 17 00:00:00 2001 From: Ariel Manzur Date: Mon, 25 May 2015 22:35:00 -0300 Subject: [PATCH 09/49] fixed support for zip packages --- core/io/file_access_zip.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp index 7a1b6454bd1..ab2eb3b3f2b 100644 --- a/core/io/file_access_zip.cpp +++ b/core/io/file_access_zip.cpp @@ -31,6 +31,7 @@ #include "file_access_zip.h" #include "core/os/file_access.h" +#include "core/os/copymem.h" ZipArchive* ZipArchive::instance = NULL; @@ -103,9 +104,17 @@ static int godot_testerror(voidpf opaque, voidpf stream) { return f->get_error()!=OK?1:0; }; +static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) { + return memalloc(items * size); }; +static void godot_free(voidpf opaque, voidpf address) { + + memfree(address); +}; + +}; // extern "C" void ZipArchive::close_handle(unzFile p_file) const { @@ -125,6 +134,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const { ERR_FAIL_COND_V(!f, NULL); zlib_filefunc_def io; + zeromem(&io, sizeof(io)); io.opaque = f; io.zopen_file = godot_open; @@ -136,9 +146,13 @@ unzFile ZipArchive::get_file_handle(String p_file) const { io.zclose_file = godot_close; io.zerror_file = godot_testerror; + io.alloc_mem = godot_alloc; + io.free_mem = godot_free; + unzFile pkg = unzOpen2(packages[file.package].filename.utf8().get_data(), &io); ERR_FAIL_COND_V(!pkg, NULL); - unzGoToFilePos(pkg, &file.file_pos); + int unz_err = unzGoToFilePos(pkg, &file.file_pos); + ERR_FAIL_COND_V(unz_err != UNZ_OK, NULL); if (unzOpenCurrentFile(pkg) != UNZ_OK) { unzClose(pkg); @@ -150,7 +164,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const { bool ZipArchive::try_open_pack(const String& p_name) { - //printf("opening pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz")); + //printf("opening zip pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz")); if (p_name.extension().nocasecmp_to("zip") != 0 && p_name.extension().nocasecmp_to("pcz") != 0) return false; @@ -198,7 +212,8 @@ bool ZipArchive::try_open_pack(const String& p_name) { files[fname] = f; uint8_t md5[16]={0,0,0,0,0,0,0,0 , 0,0,0,0,0,0,0,0}; - PackedData::get_singleton()->add_path(p_name, fname, 0, 0, md5, this); + PackedData::get_singleton()->add_path(p_name, fname, 1, 0, md5, this); + //printf("packed data add path %ls, %ls\n", p_name.c_str(), fname.c_str()); if ((i+1) Date: Mon, 25 May 2015 22:42:54 -0300 Subject: [PATCH 10/49] opening data.pcz --- core/globals.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/globals.cpp b/core/globals.cpp index 23d8c16ace0..55ba9c5f502 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -339,7 +339,7 @@ Error Globals::setup(const String& p_path,const String & p_main_pack) { //try to load settings in ascending through dirs shape! //tries to open pack, but only first time - if (first_time && _load_resource_pack(current_dir+"/data.pck")) { + if (first_time && (_load_resource_pack(current_dir+"/data.pck") || _load_resource_pack(current_dir+"/data.pcz") )) { if (_load_settings("res://engine.cfg")==OK || _load_settings_binary("res://engine.cfb")==OK) { _load_settings("res://override.cfg"); From 9df77d276593ef7082e3971d1c180b8f74b0cb2e Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 26 May 2015 01:05:08 -0300 Subject: [PATCH 11/49] ability to run 2D physics in a thread also, 2D physics is now thread safe too. see physics_2d/thread_model --- core/globals.cpp | 1 + demos/2d/platformer/engine.cfg | 1 + main/main.cpp | 2 + platform/android/os_android.cpp | 3 +- platform/android/os_android.h | 1 + platform/iphone/os_iphone.cpp | 3 +- platform/iphone/os_iphone.h | 1 + platform/osx/os_osx.h | 1 + platform/osx/os_osx.mm | 3 +- platform/windows/os_windows.cpp | 7 +- platform/windows/os_windows.h | 1 + platform/x11/os_x11.cpp | 4 +- platform/x11/os_x11.h | 1 + scene/io/resource_format_wav.cpp | 4 +- servers/audio/sample_manager_sw.cpp | 2 +- servers/physics_2d/physics_2d_server_sw.cpp | 18 +- servers/physics_2d/physics_2d_server_sw.h | 9 +- .../physics_2d/physics_2d_server_wrap_mt.cpp | 161 ++++ .../physics_2d/physics_2d_server_wrap_mt.h | 295 ++++++++ servers/physics_2d_server.h | 5 +- servers/server_wrap_mt_common.h | 700 ++++++++++++++++++ servers/visual/visual_server_wrap_mt.cpp | 4 +- servers/visual/visual_server_wrap_mt.h | 560 +------------- tools/pck/pck_packer.h | 6 +- 24 files changed, 1220 insertions(+), 573 deletions(-) create mode 100644 servers/physics_2d/physics_2d_server_wrap_mt.cpp create mode 100644 servers/physics_2d/physics_2d_server_wrap_mt.h create mode 100644 servers/server_wrap_mt_common.h diff --git a/core/globals.cpp b/core/globals.cpp index 55ba9c5f502..0315ff0c24c 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -1460,6 +1460,7 @@ Globals::Globals() { custom_prop_info["display/orientation"]=PropertyInfo(Variant::STRING,"display/orientation",PROPERTY_HINT_ENUM,"landscape,portrait,reverse_landscape,reverse_portrait,sensor_landscape,sensor_portrait,sensor"); custom_prop_info["render/mipmap_policy"]=PropertyInfo(Variant::INT,"render/mipmap_policy",PROPERTY_HINT_ENUM,"Allow,Allow For Po2,Disallow"); custom_prop_info["render/thread_model"]=PropertyInfo(Variant::INT,"render/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded"); + custom_prop_info["physics_2d/thread_model"]=PropertyInfo(Variant::INT,"physics_2d/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded"); set("display/emulate_touchscreen",false); using_datapack=false; diff --git a/demos/2d/platformer/engine.cfg b/demos/2d/platformer/engine.cfg index 50b6b862e97..5461cbddcbc 100644 --- a/demos/2d/platformer/engine.cfg +++ b/demos/2d/platformer/engine.cfg @@ -28,6 +28,7 @@ spawn=[key(F1), jbutton(0, 11)] [physics_2d] default_gravity=700 +thread_model=1 [rasterizer] diff --git a/main/main.cpp b/main/main.cpp index f826b362124..531d7cfbdc4 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1356,6 +1356,8 @@ bool Main::iteration() { message_queue->flush(); PhysicsServer::get_singleton()->step(frame_slice*time_scale); + + Physics2DServer::get_singleton()->end_sync(); Physics2DServer::get_singleton()->step(frame_slice*time_scale); time_accum-=frame_slice; diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 80953df85f6..612148418b1 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -163,7 +163,8 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_ // physics_server = memnew( PhysicsServerSW ); physics_server->init(); - physics_2d_server = memnew( Physics2DServerSW ); + //physics_2d_server = memnew( Physics2DServerSW ); + physics_2d_server = Physics2DServerWrapMT::init_server(); physics_2d_server->init(); input = memnew( InputDefault ); diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 41892d23b42..7a5a55653f1 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -37,6 +37,7 @@ #include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h" #include "servers/audio/audio_server_sw.h" #include "servers/physics_2d/physics_2d_server_sw.h" +#include "servers/physics_2d/physics_2d_server_wrap_mt.h" #include "servers/visual/rasterizer.h" diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index bf85ecc9dd9..ade1c292a43 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -136,7 +136,8 @@ void OSIPhone::initialize(const VideoMode& p_desired,int p_video_driver,int p_au // physics_server = memnew( PhysicsServerSW ); physics_server->init(); - physics_2d_server = memnew( Physics2DServerSW ); + //physics_2d_server = memnew( Physics2DServerSW ); + physics_2d_server = Physics2DServerWrapMT::init_server(); physics_2d_server->init(); input = memnew( InputDefault ); diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 721db36f411..844f0675529 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -38,6 +38,7 @@ #include "servers/visual/rasterizer.h" #include "servers/physics/physics_server_sw.h" #include "servers/physics_2d/physics_2d_server_sw.h" +#include "servers/physics_2d/physics_2d_server_wrap_mt.h" #include "servers/audio/audio_server_sw.h" #include "servers/audio/sample_manager_sw.h" #include "servers/spatial_sound/spatial_sound_server_sw.h" diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 1e9a7e89e80..144037b1cbe 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -44,6 +44,7 @@ #include "drivers/rtaudio/audio_driver_rtaudio.h" #include "drivers/alsa/audio_driver_alsa.h" #include "servers/physics_2d/physics_2d_server_sw.h" +#include "servers/physics_2d/physics_2d_server_wrap_mt.h" #include "platform/osx/audio_driver_osx.h" #include diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index eb2a12cdefa..e2ff8d11160 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1015,7 +1015,8 @@ void OS_OSX::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi // physics_server = memnew( PhysicsServerSW ); physics_server->init(); - physics_2d_server = memnew( Physics2DServerSW ); + //physics_2d_server = memnew( Physics2DServerSW ); + physics_2d_server = Physics2DServerWrapMT::init_server(); physics_2d_server->init(); input = memnew( InputDefault ); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 13507197788..4e8f9fcd9b5 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1177,7 +1177,7 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_ physics_server = memnew( PhysicsServerSW ); physics_server->init(); - physics_2d_server = memnew( Physics2DServerSW ); + physics_2d_server = Physics2DServerWrapMT::init_server(); physics_2d_server->init(); if (!is_no_window_mode_enabled()) { @@ -1375,6 +1375,9 @@ void OS_Windows::finalize() { physics_2d_server->finish(); memdelete(physics_2d_server); + joystick_change_queue.clear(); + monitor_info.clear(); + } void OS_Windows::finalize_core() { @@ -2052,7 +2055,7 @@ String OS_Windows::get_executable_path() const { wchar_t bufname[4096]; GetModuleFileNameW(NULL,bufname,4096); String s= bufname; - print_line("EXEC PATHP¨®: "+s); + print_line("EXEC PATHP??: "+s); return s; } diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 2e3700da6ae..64fbbf23c0a 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -45,6 +45,7 @@ #include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h" #include "drivers/unix/ip_unix.h" #include "servers/physics_2d/physics_2d_server_sw.h" +#include "servers/physics_2d/physics_2d_server_wrap_mt.h" #include diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 28427fa2f03..f8c570a5c04 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -35,6 +35,7 @@ #include "print_string.h" #include "servers/physics/physics_server_sw.h" + #include "X11/Xutil.h" #include "X11/Xatom.h" @@ -426,7 +427,8 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi // physics_server = memnew( PhysicsServerSW ); physics_server->init(); - physics_2d_server = memnew( Physics2DServerSW ); + //physics_2d_server = memnew( Physics2DServerSW ); + physics_2d_server = Physics2DServerWrapMT::init_server(); physics_2d_server->init(); input = memnew( InputDefault ); diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 0036485f3f6..261a54dd254 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -45,6 +45,7 @@ #include "drivers/alsa/audio_driver_alsa.h" #include "drivers/pulseaudio/audio_driver_pulseaudio.h" #include "servers/physics_2d/physics_2d_server_sw.h" +#include "servers/physics_2d/physics_2d_server_wrap_mt.h" #include #include diff --git a/scene/io/resource_format_wav.cpp b/scene/io/resource_format_wav.cpp index b246eb66f53..7c90a4b3cd0 100644 --- a/scene/io/resource_format_wav.cpp +++ b/scene/io/resource_format_wav.cpp @@ -150,10 +150,10 @@ RES ResourceFormatLoaderWAV::load(const String &p_path,const String& p_original_ frames/=format_channels; frames/=(format_bits>>3); - print_line("chunksize: "+itos(chunksize)); + /*print_line("chunksize: "+itos(chunksize)); print_line("channels: "+itos(format_channels)); print_line("bits: "+itos(format_bits)); - +*/ sample->create( (format_bits==8) ? Sample::FORMAT_PCM8 : Sample::FORMAT_PCM16, (format_channels==2)?true:false, diff --git a/servers/audio/sample_manager_sw.cpp b/servers/audio/sample_manager_sw.cpp index 49ca5369ae8..9195136a5de 100644 --- a/servers/audio/sample_manager_sw.cpp +++ b/servers/audio/sample_manager_sw.cpp @@ -135,7 +135,7 @@ void SampleManagerMallocSW::sample_set_data(RID p_sample, const DVector ERR_EXPLAIN("Sample buffer size does not match sample size."); - print_line("len bytes: "+itos(s->length_bytes)+" bufsize: "+itos(buff_size)); + //print_line("len bytes: "+itos(s->length_bytes)+" bufsize: "+itos(buff_size)); ERR_FAIL_COND(s->length_bytes!=buff_size); DVector::Read buffer_r=p_buffer.read(); const uint8_t *src = buffer_r.ptr(); diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index 08d871be69b..b446f4928a8 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -30,7 +30,7 @@ #include "broad_phase_2d_basic.h" #include "broad_phase_2d_hash_grid.h" #include "collision_solver_2d_sw.h" - +#include "globals.h" RID Physics2DServerSW::shape_create(ShapeType p_shape) { Shape2DSW *shape=NULL; @@ -261,7 +261,7 @@ Physics2DDirectSpaceState* Physics2DServerSW::space_get_direct_state(RID p_space Space2DSW *space = space_owner.get(p_space); ERR_FAIL_COND_V(!space,NULL); - if (/*doing_sync ||*/ space->is_locked()) { + if ((using_threads && !doing_sync) || space->is_locked()) { ERR_EXPLAIN("Space state is inaccesible right now, wait for iteration or fixed process notification."); ERR_FAIL_V(NULL); @@ -733,7 +733,7 @@ void Physics2DServerSW::body_set_layer_mask(RID p_body, uint32_t p_flags) { }; -uint32_t Physics2DServerSW::body_get_layer_mask(RID p_body, uint32_t p_flags) const { +uint32_t Physics2DServerSW::body_get_layer_mask(RID p_body) const { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,0); @@ -750,7 +750,7 @@ void Physics2DServerSW::body_set_collision_mask(RID p_body, uint32_t p_flags) { }; -uint32_t Physics2DServerSW::body_get_collision_mask(RID p_body, uint32_t p_flags) const { +uint32_t Physics2DServerSW::body_get_collision_mask(RID p_body) const { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,0); @@ -1196,7 +1196,7 @@ void Physics2DServerSW::set_active(bool p_active) { void Physics2DServerSW::init() { - doing_sync=true; + doing_sync=false; last_step=0.001; iterations=8;// 8? stepper = memnew( Step2DSW ); @@ -1228,6 +1228,7 @@ void Physics2DServerSW::step(float p_step) { void Physics2DServerSW::sync() { + doing_sync=true; }; void Physics2DServerSW::flush_queries() { @@ -1235,7 +1236,7 @@ void Physics2DServerSW::flush_queries() { if (!active) return; - doing_sync=true; + for( Set::Element *E=active_spaces.front();E;E=E->next()) { Space2DSW *space=(Space2DSW *)E->get(); @@ -1244,6 +1245,10 @@ void Physics2DServerSW::flush_queries() { }; +void Physics2DServerSW::end_sync() { + doing_sync=false; +} + void Physics2DServerSW::finish() { @@ -1283,6 +1288,7 @@ Physics2DServerSW::Physics2DServerSW() { island_count=0; active_objects=0; collision_pairs=0; + using_threads=int(Globals::get_singleton()->get("physics_2d/thread_model"))==2; }; diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index 341df2fdc91..6e875701b87 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -51,6 +51,8 @@ friend class Physics2DDirectSpaceStateSW; int active_objects; int collision_pairs; + bool using_threads; + Step2DSW *stepper; Set active_spaces; @@ -179,10 +181,10 @@ public: virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const; virtual void body_set_layer_mask(RID p_body, uint32_t p_mask); - virtual uint32_t body_get_layer_mask(RID p_body, uint32_t p_mask) const; + virtual uint32_t body_get_layer_mask(RID p_body) const; virtual void body_set_collision_mask(RID p_body, uint32_t p_mask); - virtual uint32_t body_get_collision_mask(RID p_body, uint32_t p_mask) const; + virtual uint32_t body_get_collision_mask(RID p_) const; virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value); virtual float body_get_param(RID p_body, BodyParameter p_param) const; @@ -248,8 +250,9 @@ public: virtual void set_active(bool p_active); virtual void init(); virtual void step(float p_step); - virtual void sync(); + virtual void sync(); virtual void flush_queries(); + virtual void end_sync(); virtual void finish(); int get_process_info(ProcessInfo p_info); diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.cpp b/servers/physics_2d/physics_2d_server_wrap_mt.cpp new file mode 100644 index 00000000000..0ee78afbaa0 --- /dev/null +++ b/servers/physics_2d/physics_2d_server_wrap_mt.cpp @@ -0,0 +1,161 @@ +#include "physics_2d_server_wrap_mt.h" + +#include "os/os.h" + +void Physics2DServerWrapMT::thread_exit() { + + exit=true; +} + +void Physics2DServerWrapMT::thread_step(float p_delta) { + + physics_2d_server->step(p_delta); + step_sem->post(); + +} + +void Physics2DServerWrapMT::_thread_callback(void *_instance) { + + Physics2DServerWrapMT *vsmt = reinterpret_cast(_instance); + + + vsmt->thread_loop(); +} + +void Physics2DServerWrapMT::thread_loop() { + + server_thread=Thread::get_caller_ID(); + + OS::get_singleton()->make_rendering_thread(); + + physics_2d_server->init(); + + exit=false; + step_thread_up=true; + while(!exit) { + // flush commands one by one, until exit is requested + command_queue.wait_and_flush_one(); + } + + command_queue.flush_all(); // flush all + + physics_2d_server->finish(); + +} + + +/* EVENT QUEUING */ + + +void Physics2DServerWrapMT::step(float p_step) { + + if (create_thread) { + + command_queue.push( this, &Physics2DServerWrapMT::thread_step,p_step); + } else { + + command_queue.flush_all(); //flush all pending from other threads + physics_2d_server->step(p_step); + } +} + +void Physics2DServerWrapMT::sync() { + + step_sem->wait(); + physics_2d_server->sync();; +} + +void Physics2DServerWrapMT::flush_queries(){ + + physics_2d_server->flush_queries(); +} + +void Physics2DServerWrapMT::end_sync() { + + physics_2d_server->end_sync();; +} + +void Physics2DServerWrapMT::init() { + + if (create_thread) { + + step_sem = Semaphore::create(); + print_line("CREATING PHYSICS 2D THREAD"); + //OS::get_singleton()->release_rendering_thread(); + if (create_thread) { + thread = Thread::create( _thread_callback, this ); + print_line("STARTING PHYISICS 2D THREAD"); + } + while(!step_thread_up) { + OS::get_singleton()->delay_usec(1000); + } + print_line("DONE PHYSICS 2D THREAD"); + } else { + + physics_2d_server->init(); + } + +} + +void Physics2DServerWrapMT::finish() { + + + if (thread) { + + command_queue.push( this, &Physics2DServerWrapMT::thread_exit); + Thread::wait_to_finish( thread ); + memdelete(thread); + +/* + shape_free_cached_ids(); + area_free_cached_ids(); + body_free_cached_ids(); + pin_joint_free_cached_ids(); + groove_joint_free_cached_ids(); + damped_string_free_cached_ids(); +*/ + thread=NULL; + } else { + physics_2d_server->finish(); + } + + if (step_sem) + memdelete(step_sem); + +} + + +Physics2DServerWrapMT::Physics2DServerWrapMT(Physics2DServer* p_contained,bool p_create_thread) : command_queue(p_create_thread) { + + physics_2d_server=p_contained; + create_thread=p_create_thread; + thread=NULL; + step_sem=NULL; + step_pending=0; + step_thread_up=false; + alloc_mutex=Mutex::create(); + + shape_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + area_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + body_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + pin_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + groove_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + damped_spring_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + + if (!p_create_thread) { + server_thread=Thread::get_caller_ID(); + } else { + server_thread=0; + } +} + + +Physics2DServerWrapMT::~Physics2DServerWrapMT() { + + memdelete(physics_2d_server); + memdelete(alloc_mutex); + //finish(); + +} + + diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h new file mode 100644 index 00000000000..4c18464e396 --- /dev/null +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -0,0 +1,295 @@ +#ifndef PHYSICS2DSERVERWRAPMT_H +#define PHYSICS2DSERVERWRAPMT_H + + +#include "servers/physics_2d_server.h" +#include "command_queue_mt.h" +#include "os/thread.h" +#include "globals.h" + +#ifdef DEBUG_SYNC +#define SYNC_DEBUG print_line("sync on: "+String(__FUNCTION__)); +#else +#define SYNC_DEBUG +#endif + + +class Physics2DServerWrapMT : public Physics2DServer { + + mutable Physics2DServer *physics_2d_server; + + mutable CommandQueueMT command_queue; + + static void _thread_callback(void *_instance); + void thread_loop(); + + Thread::ID server_thread; + volatile bool exit; + Thread *thread; + volatile bool step_thread_up; + bool create_thread; + + Semaphore *step_sem; + int step_pending; + void thread_step(float p_delta); + void thread_flush(); + + void thread_exit(); + + Mutex*alloc_mutex; + + int shape_pool_max_size; + List shape_id_pool; + int area_pool_max_size; + List area_id_pool; + int body_pool_max_size; + List body_id_pool; + int pin_joint_pool_max_size; + List pin_joint_id_pool; + int groove_joint_pool_max_size; + List groove_joint_id_pool; + int damped_spring_joint_pool_max_size; + List damped_spring_joint_id_pool; + + +public: + +#define ServerName Physics2DServer +#define ServerNameWrapMT Physics2DServerWrapMT +#define server_name physics_2d_server +#include "servers/server_wrap_mt_common.h" + + //FUNC1RID(shape,ShapeType); todo fix + FUNC1R(RID,shape_create,ShapeType); + FUNC2(shape_set_data,RID,const Variant& ); + FUNC2(shape_set_custom_solver_bias,RID,real_t ); + + FUNC1RC(ShapeType,shape_get_type,RID ); + FUNC1RC(Variant,shape_get_data,RID); + FUNC1RC(real_t,shape_get_custom_solver_bias,RID); + + + //these work well, but should be used from the main thread only + bool shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count) { + + ERR_FAIL_COND_V(server_thread!=Thread::get_caller_ID(),false); + return physics_2d_server->shape_collide(p_shape_A,p_xform_A,p_motion_A,p_shape_B,p_xform_B,p_motion_B,r_results,p_result_max,r_result_count); + } + + /* SPACE API */ + + FUNC0R(RID,space_create); + FUNC2(space_set_active,RID,bool); + FUNC1RC(bool,space_is_active,RID); + + FUNC3(space_set_param,RID,SpaceParameter,real_t); + FUNC2RC(real_t,space_get_param,RID,SpaceParameter); + + // this function only works on fixed process, errors and returns null otherwise + Physics2DDirectSpaceState* space_get_direct_state(RID p_space) { + + ERR_FAIL_COND_V(server_thread!=Thread::get_caller_ID(),NULL); + return physics_2d_server->space_get_direct_state(p_space); + } + + + /* AREA API */ + + //FUNC0RID(area); + FUNC0R(RID,area_create); + + FUNC2(area_set_space,RID,RID); + FUNC1RC(RID,area_get_space,RID); + + FUNC2(area_set_space_override_mode,RID,AreaSpaceOverrideMode); + FUNC1RC(AreaSpaceOverrideMode,area_get_space_override_mode,RID); + + FUNC3(area_add_shape,RID,RID,const Matrix32&); + FUNC3(area_set_shape,RID,int,RID); + FUNC3(area_set_shape_transform,RID,int,const Matrix32&); + + FUNC1RC(int,area_get_shape_count,RID); + FUNC2RC(RID,area_get_shape,RID,int); + FUNC2RC(Matrix32,area_get_shape_transform,RID,int); + FUNC2(area_remove_shape,RID,int); + FUNC1(area_clear_shapes,RID); + + FUNC2(area_attach_object_instance_ID,RID,ObjectID); + FUNC1RC(ObjectID,area_get_object_instance_ID,RID); + + FUNC3(area_set_param,RID,AreaParameter,const Variant&); + FUNC2(area_set_transform,RID,const Matrix32&); + + FUNC2RC(Variant,area_get_param,RID,AreaParameter); + FUNC1RC(Matrix32,area_get_transform,RID); + + FUNC2(area_set_collision_mask,RID,uint32_t); + FUNC2(area_set_layer_mask,RID,uint32_t); + + FUNC2(area_set_monitorable,RID,bool); + FUNC2(area_set_pickable,RID,bool); + + FUNC3(area_set_monitor_callback,RID,Object*,const StringName&); + FUNC3(area_set_area_monitor_callback,RID,Object*,const StringName&); + + + /* BODY API */ + + //FUNC2RID(body,BodyMode,bool); + FUNC2R(RID,body_create,BodyMode,bool) + + FUNC2(body_set_space,RID,RID); + FUNC1RC(RID,body_get_space,RID); + + FUNC2(body_set_mode,RID,BodyMode); + FUNC1RC(BodyMode,body_get_mode,RID); + + + FUNC3(body_add_shape,RID,RID,const Matrix32&); + FUNC3(body_set_shape,RID,int,RID); + FUNC3(body_set_shape_transform,RID,int,const Matrix32&); + FUNC3(body_set_shape_metadata,RID,int,const Variant&); + + FUNC1RC(int,body_get_shape_count,RID); + FUNC2RC(Matrix32,body_get_shape_transform,RID,int); + FUNC2RC(Variant,body_get_shape_metadata,RID,int); + FUNC2RC(RID,body_get_shape,RID,int); + + FUNC3(body_set_shape_as_trigger,RID,int,bool); + FUNC2RC(bool,body_is_shape_set_as_trigger,RID,int); + + FUNC2(body_remove_shape,RID,int); + FUNC1(body_clear_shapes,RID); + + FUNC2(body_attach_object_instance_ID,RID,uint32_t); + FUNC1RC(uint32_t,body_get_object_instance_ID,RID); + + FUNC2(body_set_continuous_collision_detection_mode,RID,CCDMode); + FUNC1RC(CCDMode,body_get_continuous_collision_detection_mode,RID); + + FUNC2(body_set_layer_mask,RID,uint32_t); + FUNC1RC(uint32_t,body_get_layer_mask,RID); + + FUNC2(body_set_collision_mask,RID,uint32_t); + FUNC1RC(uint32_t,body_get_collision_mask,RID); + + + FUNC3(body_set_param,RID,BodyParameter,float); + FUNC2RC(float,body_get_param,RID,BodyParameter); + + + FUNC3(body_set_state,RID,BodyState,const Variant&); + FUNC2RC(Variant,body_get_state,RID,BodyState); + + FUNC2(body_set_applied_force,RID,const Vector2&); + FUNC1RC(Vector2,body_get_applied_force,RID); + + FUNC2(body_set_applied_torque,RID,float); + FUNC1RC(float,body_get_applied_torque,RID); + + FUNC3(body_apply_impulse,RID,const Vector2&,const Vector2&); + FUNC2(body_set_axis_velocity,RID,const Vector2&); + + FUNC2(body_add_collision_exception,RID,RID); + FUNC2(body_remove_collision_exception,RID,RID); + FUNC2S(body_get_collision_exceptions,RID,List*); + + FUNC2(body_set_max_contacts_reported,RID,int); + FUNC1RC(int,body_get_max_contacts_reported,RID); + + FUNC2(body_set_one_way_collision_direction,RID,const Vector2&); + FUNC1RC(Vector2,body_get_one_way_collision_direction,RID); + + FUNC2(body_set_one_way_collision_max_depth,RID,float); + FUNC1RC(float,body_get_one_way_collision_max_depth,RID); + + + FUNC2(body_set_contacts_reported_depth_treshold,RID,float); + FUNC1RC(float,body_get_contacts_reported_depth_treshold,RID); + + FUNC2(body_set_omit_force_integration,RID,bool); + FUNC1RC(bool,body_is_omitting_force_integration,RID); + + FUNC4(body_set_force_integration_callback,RID ,Object *,const StringName& ,const Variant& ); + + + bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count) { + return physics_2d_server->body_collide_shape(p_body,p_body_shape,p_shape,p_shape_xform,p_motion,r_results,p_result_max,r_result_count); + } + + FUNC2(body_set_pickable,RID,bool); + + bool body_test_motion(RID p_body,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL) { + + ERR_FAIL_COND_V(server_thread!=Thread::get_caller_ID(),false); + return body_test_motion(p_body,p_motion,p_margin,r_result); + } + + /* JOINT API */ + + + FUNC3(joint_set_param,RID,JointParam,real_t); + FUNC2RC(real_t,joint_get_param,RID,JointParam); + + + ///FUNC3RID(pin_joint,const Vector2&,RID,RID); + ///FUNC5RID(groove_joint,const Vector2&,const Vector2&,const Vector2&,RID,RID); + ///FUNC4RID(damped_spring_joint,const Vector2&,const Vector2&,RID,RID); + + FUNC3R(RID,pin_joint_create,const Vector2&,RID,RID); + FUNC5R(RID,groove_joint_create,const Vector2&,const Vector2&,const Vector2&,RID,RID); + FUNC4R(RID,damped_spring_joint_create,const Vector2&,const Vector2&,RID,RID); + + FUNC3(damped_string_joint_set_param,RID,DampedStringParam,real_t); + FUNC2RC(real_t,damped_string_joint_get_param,RID,DampedStringParam); + + FUNC1RC(JointType,joint_get_type,RID); + + + /* MISC */ + + + FUNC1(free,RID); + FUNC1(set_active,bool); + + virtual void init(); + virtual void step(float p_step); + virtual void sync(); + virtual void end_sync(); + virtual void flush_queries(); + virtual void finish(); + + int get_process_info(ProcessInfo p_info) { + return physics_2d_server->get_process_info(p_info); + } + + Physics2DServerWrapMT(Physics2DServer* p_contained,bool p_create_thread); + ~Physics2DServerWrapMT(); + + + template + static Physics2DServer* init_server() { + + int tm = GLOBAL_DEF("physics_2d/thread_model",1); + if (tm==0) //single unsafe + return memnew( T ); + else if (tm==1) //single saef + return memnew( Physics2DServerWrapMT( memnew( T ), false )); + else //single unsafe + return memnew( Physics2DServerWrapMT( memnew( T ), true )); + + + } + +#undef ServerNameWrapMT +#undef ServerName +#undef server_name + +}; + +#ifdef DEBUG_SYNC +#undef DEBUG_SYNC +#endif +#undef SYNC_DEBUG + +#endif // PHYSICS2DSERVERWRAPMT_H diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 5411228c0fd..9922d2e3459 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -405,10 +405,10 @@ public: virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const=0; virtual void body_set_layer_mask(RID p_body, uint32_t p_mask)=0; - virtual uint32_t body_get_layer_mask(RID p_body, uint32_t p_mask) const=0; + virtual uint32_t body_get_layer_mask(RID p_body) const=0; virtual void body_set_collision_mask(RID p_body, uint32_t p_mask)=0; - virtual uint32_t body_get_collision_mask(RID p_body, uint32_t p_mask) const=0; + virtual uint32_t body_get_collision_mask(RID p_body) const=0; // common body variables enum BodyParameter { @@ -539,6 +539,7 @@ public: virtual void step(float p_step)=0; virtual void sync()=0; virtual void flush_queries()=0; + virtual void end_sync()=0; virtual void finish()=0; enum ProcessInfo { diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h new file mode 100644 index 00000000000..cbb75129d01 --- /dev/null +++ b/servers/server_wrap_mt_common.h @@ -0,0 +1,700 @@ + +#define FUNC0R(m_r,m_type)\ + virtual m_r m_type() { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type();\ + }\ + } + + +#define FUNCRID(m_type)\ + int m_type##allocn() {\ + for(int i=0;im_type##_create() );\ + }\ + return 0;\ + }\ + void m_type##_free_cached_ids() {\ + while (m_type##_id_pool.size()) {\ + free(m_type##_id_pool.front()->get());\ + m_type##_id_pool.pop_front();\ + }\ + }\ + virtual RID m_type##_create() { \ + if (Thread::get_caller_ID()!=server_thread) {\ + RID rid;\ + alloc_mutex->lock();\ + if (m_type##_id_pool.size()==0) {\ + int ret;\ + command_queue.push_and_ret( this, &ServerNameWrapMT::m_type##allocn,&ret);\ + }\ + rid=m_type##_id_pool.front()->get();\ + m_type##_id_pool.pop_front();\ + alloc_mutex->unlock();\ + return rid;\ + } else {\ + return server_name->m_type##_create();\ + }\ + } + +#define FUNC1RID(m_type,m_arg1)\ + int m_type##allocn() {\ + for(int i=0;im_type##_create() );\ + }\ + return 0;\ + }\ + void m_type##_free_cached_ids() {\ + while (m_type##_id_pool.size()) {\ + free(m_type##_id_pool.front()->get());\ + m_type##_id_pool.pop_front();\ + }\ + }\ + virtual RID m_type##_create(m_arg1 p1) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + RID rid;\ + alloc_mutex->lock();\ + if (m_type##_id_pool.size()==0) {\ + int ret;\ + command_queue.push_and_ret( this, &ServerNameWrapMT::m_type##allocn,p1,&ret);\ + }\ + rid=m_type##_id_pool.front()->get();\ + m_type##_id_pool.pop_front();\ + alloc_mutex->unlock();\ + return rid;\ + } else {\ + return server_name->m_type##_create(p1);\ + }\ + } + +#define FUNC2RID(m_type,m_arg1,m_arg2)\ + int m_type##allocn() {\ + for(int i=0;im_type##_create() );\ + }\ + return 0;\ + }\ + void m_type##_free_cached_ids() {\ + while (m_type##_id_pool.size()) {\ + free(m_type##_id_pool.front()->get());\ + m_type##_id_pool.pop_front();\ + }\ + }\ + virtual RID m_type##_create(m_arg1 p1,m_arg2 p2) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + RID rid;\ + alloc_mutex->lock();\ + if (m_type##_id_pool.size()==0) {\ + int ret;\ + command_queue.push_and_ret( this, &ServerNameWrapMT::m_type##allocn,p1,p2,&ret);\ + }\ + rid=m_type##_id_pool.front()->get();\ + m_type##_id_pool.pop_front();\ + alloc_mutex->unlock();\ + return rid;\ + } else {\ + return server_name->m_type##_create(p1,p2);\ + }\ + } + +#define FUNC3RID(m_type,m_arg1,m_arg2,m_arg3)\ + int m_type##allocn() {\ + for(int i=0;im_type##_create() );\ + }\ + return 0;\ + }\ + void m_type##_free_cached_ids() {\ + while (m_type##_id_pool.size()) {\ + free(m_type##_id_pool.front()->get());\ + m_type##_id_pool.pop_front();\ + }\ + }\ + virtual RID m_type##_create(m_arg1 p1,m_arg2 p2,m_arg3 p3) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + RID rid;\ + alloc_mutex->lock();\ + if (m_type##_id_pool.size()==0) {\ + int ret;\ + command_queue.push_and_ret( this, &ServerNameWrapMT::m_type##allocn,p1,p2,p3,&ret);\ + }\ + rid=m_type##_id_pool.front()->get();\ + m_type##_id_pool.pop_front();\ + alloc_mutex->unlock();\ + return rid;\ + } else {\ + return server_name->m_type##_create(p1,p2,p3);\ + }\ + } + + +#define FUNC4RID(m_type,m_arg1,m_arg2,m_arg3,m_arg4)\ + int m_type##allocn() {\ + for(int i=0;im_type##_create() );\ + }\ + return 0;\ + }\ + void m_type##_free_cached_ids() {\ + while (m_type##_id_pool.size()) {\ + free(m_type##_id_pool.front()->get());\ + m_type##_id_pool.pop_front();\ + }\ + }\ + virtual RID m_type##_create(m_arg1 p1,m_arg2 p2,m_arg3 p3,m_arg4 p4) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + RID rid;\ + alloc_mutex->lock();\ + if (m_type##_id_pool.size()==0) {\ + int ret;\ + command_queue.push_and_ret( this, &ServerNameWrapMT::m_type##allocn,p1,p2,p3,p4,&ret);\ + }\ + rid=m_type##_id_pool.front()->get();\ + m_type##_id_pool.pop_front();\ + alloc_mutex->unlock();\ + return rid;\ + } else {\ + return server_name->m_type##_create(p1,p2,p3,p4);\ + }\ + } + + +#define FUNC5RID(m_type,m_arg1,m_arg2,m_arg3,m_arg4,m_arg5)\ + int m_type##allocn() {\ + for(int i=0;im_type##_create() );\ + }\ + return 0;\ + }\ + void m_type##_free_cached_ids() {\ + while (m_type##_id_pool.size()) {\ + free(m_type##_id_pool.front()->get());\ + m_type##_id_pool.pop_front();\ + }\ + }\ + virtual RID m_type##_create(m_arg1 p1,m_arg2 p2,m_arg3 p3,m_arg4 p4,m_arg5 p5) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + RID rid;\ + alloc_mutex->lock();\ + if (m_type##_id_pool.size()==0) {\ + int ret;\ + command_queue.push_and_ret( this, &ServerNameWrapMT::m_type##allocn,p1,p2,p3,p4,p5,&ret);\ + }\ + rid=m_type##_id_pool.front()->get();\ + m_type##_id_pool.pop_front();\ + alloc_mutex->unlock();\ + return rid;\ + } else {\ + return server_name->m_type##_create(p1,p2,p3,p4,p5);\ + }\ + } + +#define FUNC0RC(m_r,m_type)\ + virtual m_r m_type() const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type();\ + }\ + } + + +#define FUNC0(m_type)\ + virtual void m_type() { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type);\ + } else {\ + server_name->m_type();\ + }\ + } + +#define FUNC0C(m_type)\ + virtual void m_type() const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type);\ + } else {\ + server_name->m_type();\ + }\ + } + + +#define FUNC0S(m_type)\ + virtual void m_type() { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type);\ + } else {\ + server_name->m_type();\ + }\ + } + +#define FUNC0SC(m_type)\ + virtual void m_type() const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type);\ + } else {\ + server_name->m_type();\ + }\ + } + + +/////////////////////////////////////////////// + + +#define FUNC1R(m_r,m_type,m_arg1)\ + virtual m_r m_type(m_arg1 p1) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1);\ + }\ + } + +#define FUNC1RC(m_r,m_type,m_arg1)\ + virtual m_r m_type(m_arg1 p1) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1);\ + }\ + } + + +#define FUNC1S(m_type,m_arg1)\ + virtual void m_type(m_arg1 p1) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1);\ + } else {\ + server_name->m_type(p1);\ + }\ + } + +#define FUNC1SC(m_type,m_arg1)\ + virtual void m_type(m_arg1 p1) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1);\ + } else {\ + server_name->m_type(p1);\ + }\ + } + + +#define FUNC1(m_type,m_arg1)\ + virtual void m_type(m_arg1 p1) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1);\ + } else {\ + server_name->m_type(p1);\ + }\ + } + +#define FUNC1C(m_type,m_arg1)\ + virtual void m_type(m_arg1 p1) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1);\ + } else {\ + server_name->m_type(p1);\ + }\ + } + + + + +#define FUNC2R(m_r,m_type,m_arg1, m_arg2)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2);\ + }\ + } + +#define FUNC2RC(m_r,m_type,m_arg1, m_arg2)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2);\ + }\ + } + + +#define FUNC2S(m_type,m_arg1, m_arg2)\ + virtual void m_type(m_arg1 p1, m_arg2 p2) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2);\ + } else {\ + server_name->m_type(p1, p2);\ + }\ + } + +#define FUNC2SC(m_type,m_arg1, m_arg2)\ + virtual void m_type(m_arg1 p1, m_arg2 p2) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2);\ + } else {\ + server_name->m_type(p1, p2);\ + }\ + } + + +#define FUNC2(m_type,m_arg1, m_arg2)\ + virtual void m_type(m_arg1 p1, m_arg2 p2) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2);\ + } else {\ + server_name->m_type(p1, p2);\ + }\ + } + +#define FUNC2C(m_type,m_arg1, m_arg2)\ + virtual void m_type(m_arg1 p1, m_arg2 p2) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2);\ + } else {\ + server_name->m_type(p1, p2);\ + }\ + } + + + + +#define FUNC3R(m_r,m_type,m_arg1, m_arg2, m_arg3)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3);\ + }\ + } + +#define FUNC3RC(m_r,m_type,m_arg1, m_arg2, m_arg3)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3,&ret);\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3);\ + }\ + } + + +#define FUNC3S(m_type,m_arg1, m_arg2, m_arg3)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3);\ + } else {\ + server_name->m_type(p1, p2, p3);\ + }\ + } + +#define FUNC3SC(m_type,m_arg1, m_arg2, m_arg3)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3);\ + } else {\ + server_name->m_type(p1, p2, p3);\ + }\ + } + + +#define FUNC3(m_type,m_arg1, m_arg2, m_arg3)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3);\ + } else {\ + server_name->m_type(p1, p2, p3);\ + }\ + } + +#define FUNC3C(m_type,m_arg1, m_arg2, m_arg3)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3);\ + } else {\ + server_name->m_type(p1, p2, p3);\ + }\ + } + + + + +#define FUNC4R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4);\ + }\ + } + +#define FUNC4RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4);\ + }\ + } + + +#define FUNC4S(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4);\ + } else {\ + server_name->m_type(p1, p2, p3, p4);\ + }\ + } + +#define FUNC4SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4);\ + } else {\ + server_name->m_type(p1, p2, p3, p4);\ + }\ + } + + +#define FUNC4(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4);\ + } else {\ + server_name->m_type(p1, p2, p3, p4);\ + }\ + } + +#define FUNC4C(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4);\ + } else {\ + server_name->m_type(p1, p2, p3, p4);\ + }\ + } + + + + +#define FUNC5R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4, p5,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4, p5);\ + }\ + } + +#define FUNC5RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4, p5,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4, p5);\ + }\ + } + + +#define FUNC5S(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4, p5);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5);\ + }\ + } + +#define FUNC5SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4, p5);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5);\ + }\ + } + + +#define FUNC5(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4, p5);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5);\ + }\ + } + +#define FUNC5C(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4, p5);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5);\ + }\ + } + + + + +#define FUNC6R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4, p5, p6);\ + }\ + } + +#define FUNC6RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6,&ret);\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4, p5, p6);\ + }\ + } + + +#define FUNC6S(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6);\ + }\ + } + +#define FUNC6SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6);\ + }\ + } + + +#define FUNC6(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6);\ + }\ + } + +#define FUNC6C(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6);\ + }\ + } + + + + +#define FUNC7R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4, p5, p6, p7);\ + }\ + } + +#define FUNC7RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ + virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + m_r ret;\ + command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7,&ret);\ + SYNC_DEBUG\ + return ret;\ + } else {\ + return server_name->m_type(p1, p2, p3, p4, p5, p6, p7);\ + }\ + } + + +#define FUNC7S(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6, p7);\ + }\ + } + +#define FUNC7SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6, p7);\ + }\ + } + + +#define FUNC7(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6, p7);\ + }\ + } + +#define FUNC7C(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ + virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \ + if (Thread::get_caller_ID()!=server_thread) {\ + command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7);\ + } else {\ + server_name->m_type(p1, p2, p3, p4, p5, p6, p7);\ + }\ + } + diff --git a/servers/visual/visual_server_wrap_mt.cpp b/servers/visual/visual_server_wrap_mt.cpp index a044981bbbb..44a41a93da5 100644 --- a/servers/visual/visual_server_wrap_mt.cpp +++ b/servers/visual/visual_server_wrap_mt.cpp @@ -187,8 +187,8 @@ VisualServerWrapMT::VisualServerWrapMT(VisualServer* p_contained,bool p_create_t draw_pending=0; draw_thread_up=false; alloc_mutex=Mutex::create(); - texture_pool_max_size=GLOBAL_DEF("render/thread_textures_prealloc",20); - mesh_pool_max_size=GLOBAL_DEF("render/thread_meshes_prealloc",20); + texture_pool_max_size=GLOBAL_DEF("render/thread_textures_prealloc",5); + mesh_pool_max_size=GLOBAL_DEF("core/rid_pool_prealloc",20); if (!p_create_thread) { server_thread=Thread::get_caller_ID(); } else { diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 3d972438270..d07e1940d7f 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -79,554 +79,10 @@ class VisualServerWrapMT : public VisualServer { public: -#define FUNC0R(m_r,m_type)\ - virtual m_r m_type() { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type();\ - }\ - } - -#define FUNCRID(m_type)\ - int m_type##allocn() {\ - for(int i=0;im_type##_create() );\ - }\ - return 0;\ - }\ - void m_type##_free_cached_ids() {\ - while (m_type##_id_pool.size()) {\ - free(m_type##_id_pool.front()->get());\ - m_type##_id_pool.pop_front();\ - }\ - }\ - virtual RID m_type##_create() { \ - if (Thread::get_caller_ID()!=server_thread) {\ - RID rid;\ - alloc_mutex->lock();\ - if (m_type##_id_pool.size()==0) {\ - int ret;\ - command_queue.push_and_ret( this, &VisualServerWrapMT::m_type##allocn,&ret);\ - }\ - rid=m_type##_id_pool.front()->get();\ - m_type##_id_pool.pop_front();\ - alloc_mutex->unlock();\ - return rid;\ - } else {\ - return visual_server->m_type##_create();\ - }\ - } - -#define FUNC0RC(m_r,m_type)\ - virtual m_r m_type() const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type();\ - }\ - } - - -#define FUNC0(m_type)\ - virtual void m_type() { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type);\ - } else {\ - visual_server->m_type();\ - }\ - } - -#define FUNC0C(m_type)\ - virtual void m_type() const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type);\ - } else {\ - visual_server->m_type();\ - }\ - } - - -#define FUNC0S(m_type)\ - virtual void m_type() { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type);\ - } else {\ - visual_server->m_type();\ - }\ - } - -#define FUNC0SC(m_type)\ - virtual void m_type() const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type);\ - } else {\ - visual_server->m_type();\ - }\ - } - - -/////////////////////////////////////////////// - - -#define FUNC1R(m_r,m_type,m_arg1)\ - virtual m_r m_type(m_arg1 p1) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1);\ - }\ - } - -#define FUNC1RC(m_r,m_type,m_arg1)\ - virtual m_r m_type(m_arg1 p1) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1);\ - }\ - } - - -#define FUNC1S(m_type,m_arg1)\ - virtual void m_type(m_arg1 p1) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1);\ - } else {\ - visual_server->m_type(p1);\ - }\ - } - -#define FUNC1SC(m_type,m_arg1)\ - virtual void m_type(m_arg1 p1) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1);\ - } else {\ - visual_server->m_type(p1);\ - }\ - } - - -#define FUNC1(m_type,m_arg1)\ - virtual void m_type(m_arg1 p1) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1);\ - } else {\ - visual_server->m_type(p1);\ - }\ - } - -#define FUNC1C(m_type,m_arg1)\ - virtual void m_type(m_arg1 p1) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1);\ - } else {\ - visual_server->m_type(p1);\ - }\ - } - - - - -#define FUNC2R(m_r,m_type,m_arg1, m_arg2)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2);\ - }\ - } - -#define FUNC2RC(m_r,m_type,m_arg1, m_arg2)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2);\ - }\ - } - - -#define FUNC2S(m_type,m_arg1, m_arg2)\ - virtual void m_type(m_arg1 p1, m_arg2 p2) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2);\ - } else {\ - visual_server->m_type(p1, p2);\ - }\ - } - -#define FUNC2SC(m_type,m_arg1, m_arg2)\ - virtual void m_type(m_arg1 p1, m_arg2 p2) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2);\ - } else {\ - visual_server->m_type(p1, p2);\ - }\ - } - - -#define FUNC2(m_type,m_arg1, m_arg2)\ - virtual void m_type(m_arg1 p1, m_arg2 p2) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2);\ - } else {\ - visual_server->m_type(p1, p2);\ - }\ - } - -#define FUNC2C(m_type,m_arg1, m_arg2)\ - virtual void m_type(m_arg1 p1, m_arg2 p2) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2);\ - } else {\ - visual_server->m_type(p1, p2);\ - }\ - } - - - - -#define FUNC3R(m_r,m_type,m_arg1, m_arg2, m_arg3)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3);\ - }\ - } - -#define FUNC3RC(m_r,m_type,m_arg1, m_arg2, m_arg3)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3,&ret);\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3);\ - }\ - } - - -#define FUNC3S(m_type,m_arg1, m_arg2, m_arg3)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3);\ - } else {\ - visual_server->m_type(p1, p2, p3);\ - }\ - } - -#define FUNC3SC(m_type,m_arg1, m_arg2, m_arg3)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3);\ - } else {\ - visual_server->m_type(p1, p2, p3);\ - }\ - } - - -#define FUNC3(m_type,m_arg1, m_arg2, m_arg3)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3);\ - } else {\ - visual_server->m_type(p1, p2, p3);\ - }\ - } - -#define FUNC3C(m_type,m_arg1, m_arg2, m_arg3)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3);\ - } else {\ - visual_server->m_type(p1, p2, p3);\ - }\ - } - - - - -#define FUNC4R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4);\ - }\ - } - -#define FUNC4RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4);\ - }\ - } - - -#define FUNC4S(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4);\ - }\ - } - -#define FUNC4SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4);\ - }\ - } - - -#define FUNC4(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4);\ - }\ - } - -#define FUNC4C(m_type,m_arg1, m_arg2, m_arg3, m_arg4)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4);\ - }\ - } - - - - -#define FUNC5R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4, p5);\ - }\ - } - -#define FUNC5RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4, p5);\ - }\ - } - - -#define FUNC5S(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5);\ - }\ - } - -#define FUNC5SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5);\ - }\ - } - - -#define FUNC5(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5);\ - }\ - } - -#define FUNC5C(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5);\ - }\ - } - - - - -#define FUNC6R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4, p5, p6);\ - }\ - } - -#define FUNC6RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6,&ret);\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4, p5, p6);\ - }\ - } - - -#define FUNC6S(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6);\ - }\ - } - -#define FUNC6SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6);\ - }\ - } - - -#define FUNC6(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6);\ - }\ - } - -#define FUNC6C(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6);\ - }\ - } - - - - -#define FUNC7R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\ - }\ - } - -#define FUNC7RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ - virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - m_r ret;\ - command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7,&ret);\ - SYNC_DEBUG\ - return ret;\ - } else {\ - return visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\ - }\ - } - - -#define FUNC7S(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\ - }\ - } - -#define FUNC7SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push_and_sync( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\ - }\ - } - - -#define FUNC7(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\ - }\ - } - -#define FUNC7C(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7)\ - virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7) const { \ - if (Thread::get_caller_ID()!=server_thread) {\ - command_queue.push( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7);\ - } else {\ - visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\ - }\ - } - - - +#define ServerName VisualServer +#define ServerNameWrapMT VisualServerWrapMT +#define server_name visual_server +#include "servers/server_wrap_mt_common.h" //FUNC0R(RID,texture_create); FUNCRID(texture); @@ -1242,7 +698,15 @@ public: VisualServerWrapMT(VisualServer* p_contained,bool p_create_thread); ~VisualServerWrapMT(); +#undef ServerName +#undef ServerNameWrapMT +#undef server_name + }; +#ifdef DEBUG_SYNC +#undef DEBUG_SYNC +#endif +#undef SYNC_DEBUG #endif diff --git a/tools/pck/pck_packer.h b/tools/pck/pck_packer.h index 76752a61700..2bb51128e91 100644 --- a/tools/pck/pck_packer.h +++ b/tools/pck/pck_packer.h @@ -1,10 +1,10 @@ -#include "core/object.h" +#include "core/reference.h" class FileAccess; -class PCKPacker : public Object { +class PCKPacker : public Reference { - OBJ_TYPE(PCKPacker, Object); + OBJ_TYPE(PCKPacker, Reference); FileAccess* file; int alignment; From b1b7826ea7e04a3eb4d9b3d011e9a2a8dff5db03 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 26 May 2015 01:30:36 -0300 Subject: [PATCH 12/49] oops, previous commit was not working it is working now --- demos/2d/platformer/engine.cfg | 1 - servers/physics_2d/physics_2d_server_wrap_mt.cpp | 10 +++++++++- servers/physics_2d/physics_2d_server_wrap_mt.h | 8 +++++--- servers/physics_2d_server.cpp | 2 +- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/demos/2d/platformer/engine.cfg b/demos/2d/platformer/engine.cfg index 5461cbddcbc..50b6b862e97 100644 --- a/demos/2d/platformer/engine.cfg +++ b/demos/2d/platformer/engine.cfg @@ -28,7 +28,6 @@ spawn=[key(F1), jbutton(0, 11)] [physics_2d] default_gravity=700 -thread_model=1 [rasterizer] diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.cpp b/servers/physics_2d/physics_2d_server_wrap_mt.cpp index 0ee78afbaa0..c5f023f162a 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.cpp +++ b/servers/physics_2d/physics_2d_server_wrap_mt.cpp @@ -61,7 +61,12 @@ void Physics2DServerWrapMT::step(float p_step) { void Physics2DServerWrapMT::sync() { - step_sem->wait(); + if (step_sem) { + if (first_frame) + first_frame=false; + else + step_sem->wait(); //must not wait if a step was not issued + } physics_2d_server->sync();; } @@ -147,6 +152,9 @@ Physics2DServerWrapMT::Physics2DServerWrapMT(Physics2DServer* p_contained,bool p } else { server_thread=0; } + + main_thread = Thread::get_caller_ID(); + first_frame=true; } diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h index 4c18464e396..48382498efd 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.h +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -24,6 +24,7 @@ class Physics2DServerWrapMT : public Physics2DServer { void thread_loop(); Thread::ID server_thread; + Thread::ID main_thread; volatile bool exit; Thread *thread; volatile bool step_thread_up; @@ -37,6 +38,7 @@ class Physics2DServerWrapMT : public Physics2DServer { void thread_exit(); Mutex*alloc_mutex; + bool first_frame; int shape_pool_max_size; List shape_id_pool; @@ -72,7 +74,7 @@ public: //these work well, but should be used from the main thread only bool shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count) { - ERR_FAIL_COND_V(server_thread!=Thread::get_caller_ID(),false); + ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),false); return physics_2d_server->shape_collide(p_shape_A,p_xform_A,p_motion_A,p_shape_B,p_xform_B,p_motion_B,r_results,p_result_max,r_result_count); } @@ -88,7 +90,7 @@ public: // this function only works on fixed process, errors and returns null otherwise Physics2DDirectSpaceState* space_get_direct_state(RID p_space) { - ERR_FAIL_COND_V(server_thread!=Thread::get_caller_ID(),NULL); + ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),NULL); return physics_2d_server->space_get_direct_state(p_space); } @@ -221,7 +223,7 @@ public: bool body_test_motion(RID p_body,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL) { - ERR_FAIL_COND_V(server_thread!=Thread::get_caller_ID(),false); + ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),false); return body_test_motion(p_body,p_motion,p_margin,r_result); } diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index 279ad0d7421..c2ad7b2165b 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -713,7 +713,7 @@ void Physics2DServer::_bind_methods() { Physics2DServer::Physics2DServer() { - ERR_FAIL_COND( singleton!=NULL ); + //ERR_FAIL_COND( singleton!=NULL ); singleton=this; } From 3f975965e98544e4c22eba2838ecaf00a24eb836 Mon Sep 17 00:00:00 2001 From: Biliogadafr Date: Tue, 26 May 2015 22:17:54 +0300 Subject: [PATCH 13/49] Add get_color_at_offset(). Ensure correct points order. --- scene/2d/particles_2d.cpp | 30 +------------- scene/resources/color_ramp.cpp | 72 +++++++++++++++++++++++++++++----- scene/resources/color_ramp.h | 3 ++ 3 files changed, 67 insertions(+), 38 deletions(-) diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index 6effd4f31dc..f0b7c2be600 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -528,35 +528,7 @@ void Particles2D::_notification(int p_what) { if(color_ramp.is_valid()) { - Vector& color_points = color_ramp->get_points(); - - int cpos=0; - - while(cpos ptime) - break; - cpos++; - } - - cpos--; - //could be faster.. - if (cpos==-1) - if(color_points.size()) - color=color_points[0].color;//Extend color to the beginning - else - color=Color(1,1,1,1);//If no points just use white. - else { - if (cpos==color_points.size()-1) - color=color_points[cpos].color; - else { - float diff = (color_points[cpos+1].offset-color_points[cpos].offset); - if (diff>0) - color=color_points[cpos].color.linear_interpolate(color_points[cpos+1].color, (ptime - color_points[cpos].offset) / diff ); - else - color=color_points[cpos+1].color; - } - } + color = color_ramp->get_color_at_offset(ptime); } else { color = default_color; diff --git a/scene/resources/color_ramp.cpp b/scene/resources/color_ramp.cpp index ef32ccb6a77..df235e2f2ca 100644 --- a/scene/resources/color_ramp.cpp +++ b/scene/resources/color_ramp.cpp @@ -17,6 +17,7 @@ ColorRamp::ColorRamp() { points[0].offset = 0; points[1].color = Color(1,1,1,1); points[1].offset = 1; + is_sorted = true; } ColorRamp::~ColorRamp() { @@ -25,9 +26,6 @@ ColorRamp::~ColorRamp() { void ColorRamp::_bind_methods() { - //ObjectTypeDB::bind_method(_MD("set_offset", "pos", "offset"),&ColorRamp::set_offset); - //ObjectTypeDB::bind_method(_MD(COLOR_RAMP_GET_OFFSETS),&ColorRamp::get_offset); - ObjectTypeDB::bind_method(_MD(COLOR_RAMP_SET_OFFSETS,"offsets"),&ColorRamp::set_offsets); ObjectTypeDB::bind_method(_MD(COLOR_RAMP_GET_OFFSETS),&ColorRamp::get_offsets); @@ -58,19 +56,22 @@ Vector ColorRamp::get_colors() const { return colors; } -void ColorRamp::set_offsets(const Vector& offsets) { - points.resize(offsets.size()); +void ColorRamp::set_offsets(const Vector& p_offsets) { + points.resize(p_offsets.size()); for(int i = 0; i < points.size(); i++) { - points[i].offset = offsets[i]; + points[i].offset = p_offsets[i]; } + is_sorted = false; } -void ColorRamp::set_colors(const Vector& colors) { - points.resize(colors.size()); +void ColorRamp::set_colors(const Vector& p_colors) { + if(points.size()& ColorRamp::get_points() { void ColorRamp::set_points(Vector& p_points) { points = p_points; + is_sorted = false; } void ColorRamp::set_offset(int pos, const float offset) { if(points.size() <= pos) points.resize(pos + 1); points[pos].offset = offset; + is_sorted = false; } float ColorRamp::get_offset(int pos) const { @@ -96,7 +99,10 @@ float ColorRamp::get_offset(int pos) const { void ColorRamp::set_color(int pos, const Color& color) { if(points.size() <= pos) + { points.resize(pos + 1); + is_sorted = false; + } points[pos].color = color; } @@ -106,6 +112,54 @@ Color ColorRamp::get_color(int pos) const { return Color(0,0,0,1); //TODO: Maybe throw some error instead? } +Color ColorRamp::get_color_at_offset(float p_offset) { + + if (points.empty()) + return Color(0,0,0,1); + + if (points.size() == 1) + return points[0].color; + + if(!is_sorted) + { + points.sort(); + is_sorted = true; + } + + //binary search + int low = 0; + int high = points.size() -1; + int middle; + + while( low <= high ) + { + middle = ( low + high ) / 2; + Point& point = points[middle]; + if( point.offset > p_offset ) { + high = middle - 1; //search low end of array + } else if ( point.offset < p_offset) { + low = middle + 1; //search high end of array + } else { + return point.color; + } + } + + //return interpolated value + if (points[middle].offset>p_offset) + { + middle--; + } + int first=middle; + int second=middle+1; + if(second>=points.size()) + return points[points.size()-1].color; + if(first<0) + return points[0].color; + Point& pointFirst = points[first]; + Point& pointSecond = points[second]; + return pointFirst.color.linear_interpolate(pointSecond.color, (p_offset-pointFirst.offset)/(pointSecond.offset - pointFirst.offset)); +} + int ColorRamp::get_points_count() const { return points.size(); } diff --git a/scene/resources/color_ramp.h b/scene/resources/color_ramp.h index e2f1ac5ed4f..7db8b4f3b08 100644 --- a/scene/resources/color_ramp.h +++ b/scene/resources/color_ramp.h @@ -23,6 +23,7 @@ public: private: Vector points; + bool is_sorted; protected: static void _bind_methods(); @@ -46,6 +47,8 @@ public: void set_colors(const Vector& colors); Vector get_colors() const; + Color get_color_at_offset(float offset); + int get_points_count() const; }; From 57a78ec06bccbb55a85c73891d88b983b4f01c94 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 27 May 2015 10:56:57 -0300 Subject: [PATCH 14/49] added conversion from int, string to color fixes #1971 --- core/variant.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core/variant.cpp b/core/variant.cpp index d7817ac2689..034dc2b4fca 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -302,8 +302,8 @@ bool Variant::can_convert(Variant::Type p_type_from,Variant::Type p_type_to) { case COLOR: { static const Type valid[] = { - //STRING, - //INT, + STRING, + INT, NIL, }; @@ -1653,6 +1653,10 @@ Variant::operator Color() const { if (type==COLOR) return *reinterpret_cast(_data._mem); + else if (type==STRING) + return Color::html( operator String() ); + else if (type==INT) + return Color::hex( operator int() ); else return Color(); } From f62961aba3d9e11d4741649a591217796151a46c Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 27 May 2015 17:30:50 -0300 Subject: [PATCH 15/49] -fix bug in animation editor -fix crash bug in physics motion, closes #1993 --- demos/2d/motion/engine.cfg | 7 +++++++ servers/physics_2d/physics_2d_server_wrap_mt.h | 2 +- tools/editor/animation_editor.cpp | 10 +++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/demos/2d/motion/engine.cfg b/demos/2d/motion/engine.cfg index 064de6b331e..261111904ce 100644 --- a/demos/2d/motion/engine.cfg +++ b/demos/2d/motion/engine.cfg @@ -2,3 +2,10 @@ name="Motion Test" main_scene="res://motion.scn" + +[display] + +width=800 +height=600 +stretch_mode="2d" +stretch_aspect="keep" diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h index 48382498efd..0ddc8f16ec4 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.h +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -224,7 +224,7 @@ public: bool body_test_motion(RID p_body,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL) { ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),false); - return body_test_motion(p_body,p_motion,p_margin,r_result); + return physics_2d_server->body_test_motion(p_body,p_motion,p_margin,r_result); } /* JOINT API */ diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp index 36fb6fb5f82..bb6f7e9a6f7 100644 --- a/tools/editor/animation_editor.cpp +++ b/tools/editor/animation_editor.cpp @@ -1327,8 +1327,16 @@ void AnimationKeyEditor::_track_editor_draw() { float time = animation->track_get_key_time(idx,i); if (timekeys_to) + if (time>keys_to) { + + if (first && i>0 && animation->track_get_key_value(idx,i)==animation->track_get_key_value(idx,i-1)) { + //draw whole line + te->draw_line(ofs+Vector2(name_limit,y+h/2),ofs+Point2(settings_limit,y+h/2),color); + } + break; + } + float x = key_hofs + name_limit + (time-keys_from)*zoom_scale; Ref tex = type_icon[tt]; From dc1940d3e8a897c436e3075065644ccd17f58226 Mon Sep 17 00:00:00 2001 From: Biliogadafr Date: Thu, 28 May 2015 00:11:54 +0300 Subject: [PATCH 16/49] Inline get_color_at_offset(). Delete unnecessary check. --- scene/resources/color_ramp.cpp | 48 ---------------------------------- scene/resources/color_ramp.h | 45 ++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 49 deletions(-) diff --git a/scene/resources/color_ramp.cpp b/scene/resources/color_ramp.cpp index df235e2f2ca..97d3fafd588 100644 --- a/scene/resources/color_ramp.cpp +++ b/scene/resources/color_ramp.cpp @@ -112,54 +112,6 @@ Color ColorRamp::get_color(int pos) const { return Color(0,0,0,1); //TODO: Maybe throw some error instead? } -Color ColorRamp::get_color_at_offset(float p_offset) { - - if (points.empty()) - return Color(0,0,0,1); - - if (points.size() == 1) - return points[0].color; - - if(!is_sorted) - { - points.sort(); - is_sorted = true; - } - - //binary search - int low = 0; - int high = points.size() -1; - int middle; - - while( low <= high ) - { - middle = ( low + high ) / 2; - Point& point = points[middle]; - if( point.offset > p_offset ) { - high = middle - 1; //search low end of array - } else if ( point.offset < p_offset) { - low = middle + 1; //search high end of array - } else { - return point.color; - } - } - - //return interpolated value - if (points[middle].offset>p_offset) - { - middle--; - } - int first=middle; - int second=middle+1; - if(second>=points.size()) - return points[points.size()-1].color; - if(first<0) - return points[0].color; - Point& pointFirst = points[first]; - Point& pointSecond = points[second]; - return pointFirst.color.linear_interpolate(pointSecond.color, (p_offset-pointFirst.offset)/(pointSecond.offset - pointFirst.offset)); -} - int ColorRamp::get_points_count() const { return points.size(); } diff --git a/scene/resources/color_ramp.h b/scene/resources/color_ramp.h index 7db8b4f3b08..8f6ba2c3e5a 100644 --- a/scene/resources/color_ramp.h +++ b/scene/resources/color_ramp.h @@ -47,7 +47,50 @@ public: void set_colors(const Vector& colors); Vector get_colors() const; - Color get_color_at_offset(float offset); + _FORCE_INLINE_ Color get_color_at_offset(float p_offset) { + + if (points.empty()) + return Color(0,0,0,1); + + if(!is_sorted) + { + points.sort(); + is_sorted = true; + } + + //binary search + int low = 0; + int high = points.size() -1; + int middle; + + while( low <= high ) + { + middle = ( low + high ) / 2; + Point& point = points[middle]; + if( point.offset > p_offset ) { + high = middle - 1; //search low end of array + } else if ( point.offset < p_offset) { + low = middle + 1; //search high end of array + } else { + return point.color; + } + } + + //return interpolated value + if (points[middle].offset>p_offset) + { + middle--; + } + int first=middle; + int second=middle+1; + if(second>=points.size()) + return points[points.size()-1].color; + if(first<0) + return points[0].color; + Point& pointFirst = points[first]; + Point& pointSecond = points[second]; + return pointFirst.color.linear_interpolate(pointSecond.color, (p_offset-pointFirst.offset)/(pointSecond.offset - pointFirst.offset)); + } int get_points_count() const; }; From 14c63565ec6be69b6731bcda1da7072ef53d3d88 Mon Sep 17 00:00:00 2001 From: krzycho Date: Fri, 29 May 2015 23:37:23 +0200 Subject: [PATCH 17/49] Fixed ui_accept problem. It's possible now to make a custom ui_accept action event and pull it. --- scene/gui/base_button.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index dff23777666..8b6f433c9c2 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -148,6 +148,7 @@ void BaseButton::_input_event(InputEvent p_event) { update(); } } break; + case InputEvent::ACTION: case InputEvent::JOYSTICK_BUTTON: case InputEvent::KEY: { From d5348eebdc7228f7836582cd9bd4ed4f5fd59348 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 31 May 2015 01:59:42 -0300 Subject: [PATCH 18/49] work in progress, resource previews --- core/image.cpp | 10 +- core/image.h | 5 +- core/io/file_access_memory.cpp | 8 + core/io/file_access_memory.h | 1 + core/object.cpp | 2 +- drivers/png/image_loader_png.cpp | 22 +- drivers/png/image_loader_png.h | 3 + .../resources/default_theme/default_theme.cpp | 1 - tools/editor/editor_file_dialog.cpp | 874 ++++++++++++++++++ tools/editor/editor_file_dialog.h | 198 ++++ tools/editor/editor_node.cpp | 153 ++- tools/editor/editor_node.h | 12 +- tools/editor/editor_resource_preview.cpp | 260 ++++++ tools/editor/editor_resource_preview.h | 95 ++ tools/editor/editor_settings.cpp | 2 + tools/editor/icons/icon_wait_no_preview.png | Bin 0 -> 1041 bytes tools/editor/icons/icon_wait_preview_1.png | Bin 0 -> 1208 bytes tools/editor/icons/icon_wait_preview_2.png | Bin 0 -> 1270 bytes tools/editor/icons/icon_wait_preview_3.png | Bin 0 -> 1190 bytes tools/editor/icons/icon_wait_preview_4.png | Bin 0 -> 1269 bytes tools/editor/icons/icon_wait_preview_5.png | Bin 0 -> 1191 bytes tools/editor/icons/icon_wait_preview_6.png | Bin 0 -> 1278 bytes tools/editor/icons/icon_wait_preview_7.png | Bin 0 -> 1192 bytes tools/editor/icons/icon_wait_preview_8.png | Bin 0 -> 1341 bytes .../editor/plugins/editor_preview_plugins.cpp | 664 +++++++++++++ tools/editor/plugins/editor_preview_plugins.h | 69 ++ tools/editor/plugins/sample_editor_plugin.cpp | 119 +++ tools/editor/plugins/spatial_editor_plugin.h | 8 +- tools/editor/resources_dock.cpp | 4 +- tools/editor/resources_dock.h | 3 +- 30 files changed, 2485 insertions(+), 28 deletions(-) create mode 100644 tools/editor/editor_file_dialog.cpp create mode 100644 tools/editor/editor_file_dialog.h create mode 100644 tools/editor/editor_resource_preview.cpp create mode 100644 tools/editor/editor_resource_preview.h create mode 100644 tools/editor/icons/icon_wait_no_preview.png create mode 100644 tools/editor/icons/icon_wait_preview_1.png create mode 100644 tools/editor/icons/icon_wait_preview_2.png create mode 100644 tools/editor/icons/icon_wait_preview_3.png create mode 100644 tools/editor/icons/icon_wait_preview_4.png create mode 100644 tools/editor/icons/icon_wait_preview_5.png create mode 100644 tools/editor/icons/icon_wait_preview_6.png create mode 100644 tools/editor/icons/icon_wait_preview_7.png create mode 100644 tools/editor/icons/icon_wait_preview_8.png create mode 100644 tools/editor/plugins/editor_preview_plugins.cpp create mode 100644 tools/editor/plugins/editor_preview_plugins.h diff --git a/core/image.cpp b/core/image.cpp index 04b39054891..b516790494c 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -1746,6 +1746,10 @@ Error Image::_decompress_bc() { return OK; } +bool Image::is_compressed() const { + return format>=FORMAT_BC1; +} + Image Image::decompressed() const { @@ -1998,7 +2002,7 @@ void Image::blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2& } -Image (*Image::_png_mem_loader_func)(const uint8_t*)=NULL; +Image (*Image::_png_mem_loader_func)(const uint8_t*,int)=NULL; void (*Image::_image_compress_bc_func)(Image *)=NULL; void (*Image::_image_compress_pvrtc2_func)(Image *)=NULL; void (*Image::_image_compress_pvrtc4_func)(Image *)=NULL; @@ -2167,7 +2171,7 @@ void Image::fix_alpha_edges() { } -Image::Image(const uint8_t* p_png) { +Image::Image(const uint8_t* p_png,int p_len) { width=0; height=0; @@ -2175,7 +2179,7 @@ Image::Image(const uint8_t* p_png) { format=FORMAT_GRAYSCALE; if (_png_mem_loader_func) { - *this = _png_mem_loader_func(p_png); + *this = _png_mem_loader_func(p_png,p_len); } } diff --git a/core/image.h b/core/image.h index ddb5e88ebff..a9eb8fd7694 100644 --- a/core/image.h +++ b/core/image.h @@ -94,7 +94,7 @@ public: /* INTERPOLATE GAUSS */ }; - static Image (*_png_mem_loader_func)(const uint8_t* p_png); + static Image (*_png_mem_loader_func)(const uint8_t* p_png,int p_size); static void (*_image_compress_bc_func)(Image *); static void (*_image_compress_pvrtc2_func)(Image *); static void (*_image_compress_pvrtc4_func)(Image *); @@ -335,6 +335,7 @@ public: Image compressed(int p_mode); /* from the Image::CompressMode enum */ Error decompress(); Image decompressed() const; + bool is_compressed() const; void fix_alpha_edges(); void premultiply_alpha(); @@ -349,7 +350,7 @@ public: Image get_rect(const Rect2& p_area) const; static void set_compress_bc_func(void (*p_compress_func)(Image *)); - Image(const uint8_t* p_mem_png); + Image(const uint8_t* p_mem_png, int p_len=-1); Image(const char **p_xpm); ~Image(); diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp index 2880c4ebdab..83da55fc614 100644 --- a/core/io/file_access_memory.cpp +++ b/core/io/file_access_memory.cpp @@ -74,6 +74,14 @@ bool FileAccessMemory::file_exists(const String& p_name) { } +Error FileAccessMemory::open_custom(const uint8_t* p_data, int p_len) { + + data=(uint8_t*)p_data; + length=p_len; + pos=0; + return OK; +} + Error FileAccessMemory::_open(const String& p_path, int p_mode_flags) { ERR_FAIL_COND_V(!files, ERR_FILE_NOT_FOUND); diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h index 5a9ec2b3c63..8c58a8a8ced 100644 --- a/core/io/file_access_memory.h +++ b/core/io/file_access_memory.h @@ -44,6 +44,7 @@ public: static void register_file(String p_name, Vector p_data); static void cleanup(); + virtual Error open_custom(const uint8_t* p_data, int p_len); ///< open a file virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file virtual void close(); ///< close a file virtual bool is_open() const; ///< true when file is open diff --git a/core/object.cpp b/core/object.cpp index 84786df8d4d..83a6dada802 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -1351,7 +1351,7 @@ Error Object::connect(const StringName& p_signal, Object *p_to_object, const Str if (!s) { bool signal_is_valid = ObjectTypeDB::has_signal(get_type_name(),p_signal); if (!signal_is_valid) { - ERR_EXPLAIN("Attempt to connect to nonexistent signal: "+p_signal); + ERR_EXPLAIN("Attempt to connect nonexistent signal '"+p_signal+"' to method '"+p_to_method+"'"); ERR_FAIL_COND_V(!signal_is_valid,ERR_INVALID_PARAMETER); } signal_map[p_signal]=Signal(); diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp index 2e1488ff9d5..2a4720b07b6 100644 --- a/drivers/png/image_loader_png.cpp +++ b/drivers/png/image_loader_png.cpp @@ -31,6 +31,8 @@ #include "print_string.h" #include "os/os.h" + + void ImageLoaderPNG::_read_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length) { FileAccess *f = (FileAccess*)png_get_io_ptr(png_ptr); @@ -253,6 +255,7 @@ void ImageLoaderPNG::get_recognized_extensions(List *p_extensions) const struct PNGReadStatus { int offset; + int size; const unsigned char *image; }; @@ -261,17 +264,26 @@ static void user_read_data(png_structp png_ptr,png_bytep data, png_size_t p_leng PNGReadStatus *rstatus; rstatus=(PNGReadStatus*)png_get_io_ptr(png_ptr); - memcpy(data,&rstatus->image[rstatus->offset],p_length); - rstatus->offset+=p_length; + int to_read=p_length; + if (rstatus->size>=0) { + to_read = MIN( p_length, rstatus->size - rstatus->offset); + } + memcpy(data,&rstatus->image[rstatus->offset],to_read); + rstatus->offset+=to_read; + + if (to_read& p_data) { + int len = p_data.size(); DVector::Read r = p_data.read(); ERR_FAIL_COND_V(r[0]!='P' || r[1]!='N' || r[2]!='G' || r[3]!=' ',Image()); - return _load_mem_png(&r[4]); + return _load_mem_png(&r[4],len-4); } @@ -424,6 +437,7 @@ static DVector _lossless_pack_png(const Image& p_image) { ImageLoaderPNG::ImageLoaderPNG() { + Image::_png_mem_loader_func=_load_mem_png; Image::lossless_unpacker=_lossless_unpack_png; Image::lossless_packer=_lossless_pack_png; diff --git a/drivers/png/image_loader_png.h b/drivers/png/image_loader_png.h index 7acfd041eeb..8413a7eae18 100644 --- a/drivers/png/image_loader_png.h +++ b/drivers/png/image_loader_png.h @@ -40,7 +40,10 @@ class ImageLoaderPNG : public ImageFormatLoader { static void _read_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length); + public: + + static Error _load_image(void *rf_up,png_rw_ptr p_func,Image *p_image); virtual Error load_image(Image *p_image,FileAccess *f); virtual void get_recognized_extensions(List *p_extensions) const; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 2fddafc07bd..d43ffd21301 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -692,7 +692,6 @@ void make_default_theme() { // FileDialog t->set_icon("folder","FileDialog",make_icon(icon_folder_png)); - t->set_color("files_disabled","FileDialog",Color(0,0,0,0.7)); diff --git a/tools/editor/editor_file_dialog.cpp b/tools/editor/editor_file_dialog.cpp new file mode 100644 index 00000000000..359f807ae4b --- /dev/null +++ b/tools/editor/editor_file_dialog.cpp @@ -0,0 +1,874 @@ +#include "editor_file_dialog.h" +#include "scene/gui/label.h" +#include "scene/gui/center_container.h" +#include "print_string.h" +#include "os/keyboard.h" +#include "editor_resource_preview.h" + + +EditorFileDialog::GetIconFunc EditorFileDialog::get_icon_func=NULL; +EditorFileDialog::GetIconFunc EditorFileDialog::get_large_icon_func=NULL; + +EditorFileDialog::RegisterFunc EditorFileDialog::register_func=NULL; +EditorFileDialog::RegisterFunc EditorFileDialog::unregister_func=NULL; + + +VBoxContainer *EditorFileDialog::get_vbox() { + return vbox; + +} + +void EditorFileDialog::_notification(int p_what) { + if (p_what==NOTIFICATION_PROCESS) { + + if (preview_waiting) { + preview_wheel_timeout-=get_process_delta_time(); + if (preview_wheel_timeout<=0) { + preview_wheel_index++; + if (preview_wheel_index>=8) + preview_wheel_index=0; + Ref frame = get_icon("WaitPreview"+itos(preview_wheel_index+1),"EditorIcons"); + preview->set_texture(frame); + preview_wheel_timeout=0.1; + } + } + } + + if (p_what==NOTIFICATION_DRAW) { + + //RID ci = get_canvas_item(); + //get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size())); + } +} + +void EditorFileDialog::set_enable_multiple_selection(bool p_enable) { + + tree->set_select_mode(p_enable?Tree::SELECT_MULTI : Tree::SELECT_SINGLE); +}; + +Vector EditorFileDialog::get_selected_files() const { + + Vector list; + + TreeItem* item = tree->get_root(); + while ( (item = tree->get_next_selected(item)) ) { + + list.push_back(dir_access->get_current_dir().plus_file(item->get_text(0))); + }; + + return list; +}; + +void EditorFileDialog::update_dir() { + + dir->set_text(dir_access->get_current_dir()); +} + +void EditorFileDialog::_dir_entered(String p_dir) { + + + dir_access->change_dir(p_dir); + file->set_text(""); + invalidate(); + update_dir(); +} + +void EditorFileDialog::_file_entered(const String& p_file) { + + _action_pressed(); +} + +void EditorFileDialog::_save_confirm_pressed() { + String f=dir_access->get_current_dir().plus_file(file->get_text()); + emit_signal("file_selected",f); + hide(); +} + +void EditorFileDialog::_post_popup() { + + ConfirmationDialog::_post_popup(); + if (invalidated) { + update_file_list(); + invalidated=false; + } + if (mode==MODE_SAVE_FILE) + file->grab_focus(); + else + tree->grab_focus(); + + if (is_visible() && get_current_file()!="") + _request_single_thumbnail(get_current_dir().plus_file(get_current_file())); + +} + +void EditorFileDialog::_thumbnail_done(const String& p_path,const Ref& p_preview, const Variant& p_udata) { + + set_process(false); + preview_waiting=false; + + if (p_preview.is_valid() && get_current_path()==p_path) { + + preview->set_texture(p_preview); + preview_vb->show(); + + } else { + preview_vb->hide(); + preview->set_texture(Ref()); + + } + +} + +void EditorFileDialog::_request_single_thumbnail(const String& p_path) { + + EditorResourcePreview::get_singleton()->queue_resource_preview(p_path,this,"_thumbnail_done",p_path); + print_line("want file "+p_path); + set_process(true); + preview_waiting=true; + preview_wheel_timeout=0; + +} + +void EditorFileDialog::_action_pressed() { + + if (mode==MODE_OPEN_FILES) { + + TreeItem *ti=tree->get_next_selected(NULL); + String fbase=dir_access->get_current_dir(); + + DVector files; + while(ti) { + + files.push_back( fbase.plus_file(ti->get_text(0)) ); + ti=tree->get_next_selected(ti); + } + + if (files.size()) { + emit_signal("files_selected",files); + hide(); + } + + return; + } + + String f=dir_access->get_current_dir().plus_file(file->get_text()); + + if (mode==MODE_OPEN_FILE && dir_access->file_exists(f)) { + emit_signal("file_selected",f); + hide(); + } + + if (mode==MODE_OPEN_DIR) { + + + String path=dir_access->get_current_dir(); + /*if (tree->get_selected()) { + Dictionary d = tree->get_selected()->get_metadata(0); + if (d["dir"]) { + path=path+"/"+String(d["name"]); + } + }*/ + path=path.replace("\\","/"); + emit_signal("dir_selected",path); + hide(); + } + + if (mode==MODE_SAVE_FILE) { + + bool valid=false; + + if (filter->get_selected()==filter->get_item_count()-1) { + valid=true; //match none + } else if (filters.size()>1 && filter->get_selected()==0) { + // match all filters + for (int i=0;iget_selected(); + if (filters.size()>1) + idx--; + if (idx>=0 && idx0) { + String str = (flt.get_slice(",",0).strip_edges()); + f+=str.substr(1, str.length()-1); + _request_single_thumbnail(get_current_dir().plus_file(f.get_file())); + file->set_text(f.get_file()); + valid=true; + } + } else { + valid=true; + } + } + + + if (!valid) { + + exterr->popup_centered_minsize(Size2(250,80)); + return; + + } + + if (dir_access->file_exists(f)) { + confirm_save->set_text("File Exists, Overwrite?"); + confirm_save->popup_centered(Size2(200,80)); + } else { + + + emit_signal("file_selected",f); + hide(); + } + } +} + +void EditorFileDialog::_cancel_pressed() { + + file->set_text(""); + invalidate(); + hide(); +} + +void EditorFileDialog::_tree_selected() { + + TreeItem *ti=tree->get_selected(); + if (!ti) + return; + Dictionary d=ti->get_metadata(0); + + if (!d["dir"]) { + + file->set_text(d["name"]); + _request_single_thumbnail(get_current_dir().plus_file(get_current_file())); + } +} + +void EditorFileDialog::_tree_dc_selected() { + + + TreeItem *ti=tree->get_selected(); + if (!ti) + return; + + Dictionary d=ti->get_metadata(0); + + if (d["dir"]) { + + dir_access->change_dir(d["name"]); + if (mode==MODE_OPEN_FILE || mode==MODE_OPEN_FILES || mode==MODE_OPEN_DIR) + file->set_text(""); + call_deferred("_update_file_list"); + call_deferred("_update_dir"); + } else { + + _action_pressed(); + } +} + +void EditorFileDialog::update_file_list() { + + tree->clear(); + dir_access->list_dir_begin(); + + TreeItem *root = tree->create_item(); + Ref folder = get_icon("folder","FileDialog"); + List files; + List dirs; + + bool isdir; + bool ishidden; + bool show_hidden = show_hidden_files; + String item; + + while ((item=dir_access->get_next(&isdir))!="") { + + ishidden = dir_access->current_is_hidden(); + + if (show_hidden || !ishidden) { + if (!isdir) + files.push_back(item); + else + dirs.push_back(item); + } + } + + dirs.sort_custom(); + files.sort_custom(); + + while(!dirs.empty()) { + + if (dirs.front()->get()!=".") { + TreeItem *ti=tree->create_item(root); + ti->set_text(0,dirs.front()->get()+"/"); + ti->set_icon(0,folder); + Dictionary d; + d["name"]=dirs.front()->get(); + d["dir"]=true; + ti->set_metadata(0,d); + } + dirs.pop_front(); + + } + + dirs.clear(); + + List patterns; + // build filter + if (filter->get_selected()==filter->get_item_count()-1) { + + // match all + } else if (filters.size()>1 && filter->get_selected()==0) { + // match all filters + for (int i=0;iget_selected(); + if (filters.size()>1) + idx--; + + if (idx>=0 && idxget_current_dir(); + + + while(!files.empty()) { + + bool match=patterns.empty(); + + for(List::Element *E=patterns.front();E;E=E->next()) { + + if (files.front()->get().matchn(E->get())) { + + match=true; + break; + } + } + + if (match) { + TreeItem *ti=tree->create_item(root); + ti->set_text(0,files.front()->get()); + + if (get_icon_func) { + + Ref icon = get_icon_func(base_dir.plus_file(files.front()->get())); + ti->set_icon(0,icon); + } + + if (mode==MODE_OPEN_DIR) { + ti->set_custom_color(0,get_color("files_disabled")); + ti->set_selectable(0,false); + } + Dictionary d; + d["name"]=files.front()->get(); + d["dir"]=false; + ti->set_metadata(0,d); + + if (file->get_text()==files.front()->get()) + ti->select(0); + } + + files.pop_front(); + } + + if (tree->get_root() && tree->get_root()->get_children()) + tree->get_root()->get_children()->select(0); + + files.clear(); + +} + +void EditorFileDialog::_filter_selected(int) { + + update_file_list(); +} + +void EditorFileDialog::update_filters() { + + filter->clear(); + + if (filters.size()>1) { + String all_filters; + + const int max_filters=5; + + for(int i=0;i0) + all_filters+=","; + all_filters+=flt; + } + + if (max_filtersadd_item("All Recognized ( "+all_filters+" )"); + } + for(int i=0;iadd_item(desc+" ( "+flt+" )"); + else + filter->add_item("( "+flt+" )"); + } + + filter->add_item("All Files (*)"); + +} + +void EditorFileDialog::clear_filters() { + + filters.clear(); + update_filters(); + invalidate(); +} +void EditorFileDialog::add_filter(const String& p_filter) { + + filters.push_back(p_filter); + update_filters(); + invalidate(); + +} + +String EditorFileDialog::get_current_dir() const { + + return dir->get_text(); +} +String EditorFileDialog::get_current_file() const { + + return file->get_text(); +} +String EditorFileDialog::get_current_path() const { + + return dir->get_text().plus_file(file->get_text()); +} +void EditorFileDialog::set_current_dir(const String& p_dir) { + + dir_access->change_dir(p_dir); + update_dir(); + invalidate(); + +} +void EditorFileDialog::set_current_file(const String& p_file) { + + file->set_text(p_file); + update_dir(); + invalidate(); + int lp = p_file.find_last("."); + if (lp!=-1) { + file->select(0,lp); + file->grab_focus(); + } + + if (is_visible()) + _request_single_thumbnail(get_current_dir().plus_file(get_current_file())); + + +} +void EditorFileDialog::set_current_path(const String& p_path) { + + if (!p_path.size()) + return; + int pos=MAX( p_path.find_last("/"), p_path.find_last("\\") ); + if (pos==-1) { + + set_current_file(p_path); + } else { + + String dir=p_path.substr(0,pos); + String file=p_path.substr(pos+1,p_path.length()); + set_current_dir(dir); + set_current_file(file); + } +} + + +void EditorFileDialog::set_mode(Mode p_mode) { + + mode=p_mode; + switch(mode) { + + case MODE_OPEN_FILE: get_ok()->set_text("Open"); set_title("Open a File"); makedir->hide(); break; + case MODE_OPEN_FILES: get_ok()->set_text("Open"); set_title("Open File(s)"); makedir->hide(); break; + case MODE_SAVE_FILE: get_ok()->set_text("Save"); set_title("Save a File"); makedir->show(); break; + case MODE_OPEN_DIR: get_ok()->set_text("Open"); set_title("Open a Directory"); makedir->show(); break; + } + + if (mode==MODE_OPEN_FILES) { + tree->set_select_mode(Tree::SELECT_MULTI); + } else { + tree->set_select_mode(Tree::SELECT_SINGLE); + + } +} + +EditorFileDialog::Mode EditorFileDialog::get_mode() const { + + return mode; +} + +void EditorFileDialog::set_access(Access p_access) { + + ERR_FAIL_INDEX(p_access,3); + if (access==p_access) + return; + memdelete( dir_access ); + switch(p_access) { + case ACCESS_FILESYSTEM: { + + dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + } break; + case ACCESS_RESOURCES: { + + dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES); + } break; + case ACCESS_USERDATA: { + + dir_access = DirAccess::create(DirAccess::ACCESS_USERDATA); + } break; + } + access=p_access; + _update_drives(); + invalidate(); + update_filters(); + update_dir(); +} + +void EditorFileDialog::invalidate() { + + if (is_visible()) { + update_file_list(); + invalidated=false; + } else { + invalidated=true; + } + +} + +EditorFileDialog::Access EditorFileDialog::get_access() const{ + + return access; +} + +void EditorFileDialog::_make_dir_confirm() { + + + Error err = dir_access->make_dir( makedirname->get_text() ); + if (err==OK) { + dir_access->change_dir(makedirname->get_text()); + invalidate(); + update_filters(); + update_dir(); + } else { + mkdirerr->popup_centered_minsize(Size2(250,50)); + } +} + + +void EditorFileDialog::_make_dir() { + + makedialog->popup_centered_minsize(Size2(250,80)); + makedirname->grab_focus(); + +} + +void EditorFileDialog::_select_drive(int p_idx) { + + String d = drives->get_item_text(p_idx); + dir_access->change_dir(d); + file->set_text(""); + invalidate(); + update_dir(); + +} + +void EditorFileDialog::_update_drives() { + + + int dc = dir_access->get_drive_count(); + if (dc==0 || access!=ACCESS_FILESYSTEM) { + drives->hide(); + } else { + drives->clear(); + drives->show(); + + for(int i=0;iget_drive_count();i++) { + String d = dir_access->get_drive(i); + drives->add_item(dir_access->get_drive(i)); + } + + drives->select(dir_access->get_current_drive()); + + } +} + +bool EditorFileDialog::default_show_hidden_files=true; + + +void EditorFileDialog::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_tree_selected"),&EditorFileDialog::_tree_selected); + ObjectTypeDB::bind_method(_MD("_tree_db_selected"),&EditorFileDialog::_tree_dc_selected); + ObjectTypeDB::bind_method(_MD("_dir_entered"),&EditorFileDialog::_dir_entered); + ObjectTypeDB::bind_method(_MD("_file_entered"),&EditorFileDialog::_file_entered); + ObjectTypeDB::bind_method(_MD("_action_pressed"),&EditorFileDialog::_action_pressed); + ObjectTypeDB::bind_method(_MD("_cancel_pressed"),&EditorFileDialog::_cancel_pressed); + ObjectTypeDB::bind_method(_MD("_filter_selected"),&EditorFileDialog::_filter_selected); + ObjectTypeDB::bind_method(_MD("_save_confirm_pressed"),&EditorFileDialog::_save_confirm_pressed); + + ObjectTypeDB::bind_method(_MD("clear_filters"),&EditorFileDialog::clear_filters); + ObjectTypeDB::bind_method(_MD("add_filter","filter"),&EditorFileDialog::add_filter); + ObjectTypeDB::bind_method(_MD("get_current_dir"),&EditorFileDialog::get_current_dir); + ObjectTypeDB::bind_method(_MD("get_current_file"),&EditorFileDialog::get_current_file); + ObjectTypeDB::bind_method(_MD("get_current_path"),&EditorFileDialog::get_current_path); + ObjectTypeDB::bind_method(_MD("set_current_dir","dir"),&EditorFileDialog::set_current_dir); + ObjectTypeDB::bind_method(_MD("set_current_file","file"),&EditorFileDialog::set_current_file); + ObjectTypeDB::bind_method(_MD("set_current_path","path"),&EditorFileDialog::set_current_path); + ObjectTypeDB::bind_method(_MD("set_mode","mode"),&EditorFileDialog::set_mode); + ObjectTypeDB::bind_method(_MD("get_mode"),&EditorFileDialog::get_mode); + ObjectTypeDB::bind_method(_MD("get_vbox:VBoxContainer"),&EditorFileDialog::get_vbox); + ObjectTypeDB::bind_method(_MD("set_access","access"),&EditorFileDialog::set_access); + ObjectTypeDB::bind_method(_MD("get_access"),&EditorFileDialog::get_access); + ObjectTypeDB::bind_method(_MD("set_show_hidden_files"),&EditorFileDialog::set_show_hidden_files); + ObjectTypeDB::bind_method(_MD("is_showing_hidden_files"),&EditorFileDialog::is_showing_hidden_files); + ObjectTypeDB::bind_method(_MD("_select_drive"),&EditorFileDialog::_select_drive); + ObjectTypeDB::bind_method(_MD("_make_dir"),&EditorFileDialog::_make_dir); + ObjectTypeDB::bind_method(_MD("_make_dir_confirm"),&EditorFileDialog::_make_dir_confirm); + ObjectTypeDB::bind_method(_MD("_update_file_list"),&EditorFileDialog::update_file_list); + ObjectTypeDB::bind_method(_MD("_update_dir"),&EditorFileDialog::update_dir); + ObjectTypeDB::bind_method(_MD("_thumbnail_done"),&EditorFileDialog::_thumbnail_done); + + ObjectTypeDB::bind_method(_MD("invalidate"),&EditorFileDialog::invalidate); + + ADD_SIGNAL(MethodInfo("file_selected",PropertyInfo( Variant::STRING,"path"))); + ADD_SIGNAL(MethodInfo("files_selected",PropertyInfo( Variant::STRING_ARRAY,"paths"))); + ADD_SIGNAL(MethodInfo("dir_selected",PropertyInfo( Variant::STRING,"dir"))); + + BIND_CONSTANT( MODE_OPEN_FILE ); + BIND_CONSTANT( MODE_OPEN_FILES ); + BIND_CONSTANT( MODE_OPEN_DIR ); + BIND_CONSTANT( MODE_SAVE_FILE ); + + BIND_CONSTANT( ACCESS_RESOURCES ); + BIND_CONSTANT( ACCESS_USERDATA ); + BIND_CONSTANT( ACCESS_FILESYSTEM ); + +} + + +void EditorFileDialog::set_show_hidden_files(bool p_show) { + show_hidden_files=p_show; + invalidate(); +} + +bool EditorFileDialog::is_showing_hidden_files() const { + return show_hidden_files; +} + +void EditorFileDialog::set_default_show_hidden_files(bool p_show) { + default_show_hidden_files=p_show; +} + +EditorFileDialog::EditorFileDialog() { + + show_hidden_files=true; + + VBoxContainer *vbc = memnew( VBoxContainer ); + add_child(vbc); + set_child_rect(vbc); + + mode=MODE_SAVE_FILE; + set_title("Save a File"); + + dir = memnew(LineEdit); + HBoxContainer *pathhb = memnew( HBoxContainer ); + pathhb->add_child(dir); + dir->set_h_size_flags(SIZE_EXPAND_FILL); + + drives = memnew( OptionButton ); + pathhb->add_child(drives); + drives->connect("item_selected",this,"_select_drive"); + + makedir = memnew( Button ); + makedir->set_text("Create Folder"); + makedir->connect("pressed",this,"_make_dir"); + pathhb->add_child(makedir); + + vbc->add_margin_child("Path:",pathhb); + + list_hb = memnew( HBoxContainer ); + vbc->add_margin_child("Directories & Files:",list_hb,true); + + tree = memnew(Tree); + tree->set_hide_root(true); + tree->set_h_size_flags(SIZE_EXPAND_FILL); + list_hb->add_child(tree); + + HBoxContainer* filter_hb = memnew( HBoxContainer ); + vbc->add_child(filter_hb); + + VBoxContainer *filter_vb = memnew( VBoxContainer ); + filter_hb->add_child(filter_vb); + filter_vb->set_h_size_flags(SIZE_EXPAND_FILL); + + preview_vb = memnew( VBoxContainer ); + filter_hb->add_child(preview_vb); + CenterContainer *prev_cc = memnew( CenterContainer ); + preview_vb->add_margin_child("Preview:",prev_cc); + preview = memnew( TextureFrame ); + prev_cc->add_child(preview); + preview_vb->hide(); + + + file = memnew(LineEdit); + //add_child(file); + filter_vb->add_margin_child("File:",file); + + + filter = memnew( OptionButton ); + //add_child(filter); + filter_vb->add_margin_child("Filter:",filter); + filter->set_clip_text(true);//too many extensions overflow it + + dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES); + access=ACCESS_RESOURCES; + _update_drives(); + + + connect("confirmed", this,"_action_pressed"); + //cancel->connect("pressed", this,"_cancel_pressed"); + tree->connect("cell_selected", this,"_tree_selected",varray(),CONNECT_DEFERRED); + tree->connect("item_activated", this,"_tree_db_selected",varray()); + dir->connect("text_entered", this,"_dir_entered"); + file->connect("text_entered", this,"_file_entered"); + filter->connect("item_selected", this,"_filter_selected"); + + + confirm_save = memnew( ConfirmationDialog ); + confirm_save->set_as_toplevel(true); + add_child(confirm_save); + + + confirm_save->connect("confirmed", this,"_save_confirm_pressed"); + + makedialog = memnew( ConfirmationDialog ); + makedialog->set_title("Create Folder"); + VBoxContainer *makevb= memnew( VBoxContainer ); + makedialog->add_child(makevb); + makedialog->set_child_rect(makevb); + makedirname = memnew( LineEdit ); + makevb->add_margin_child("Name:",makedirname); + add_child(makedialog); + makedialog->register_text_enter(makedirname); + makedialog->connect("confirmed",this,"_make_dir_confirm"); + mkdirerr = memnew( AcceptDialog ); + mkdirerr->set_text("Could not create folder."); + add_child(mkdirerr); + + exterr = memnew( AcceptDialog ); + exterr->set_text("Must use a valid extension."); + add_child(exterr); + + + //update_file_list(); + update_filters(); + update_dir(); + + set_hide_on_ok(false); + vbox=vbc; + + + invalidated=true; + if (register_func) + register_func(this); + + preview_wheel_timeout=0; + preview_wheel_index=0; + preview_waiting=false; + +} + + +EditorFileDialog::~EditorFileDialog() { + + if (unregister_func) + unregister_func(this); + memdelete(dir_access); +} + + +void EditorLineEditFileChooser::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_browse"),&EditorLineEditFileChooser::_browse); + ObjectTypeDB::bind_method(_MD("_chosen"),&EditorLineEditFileChooser::_chosen); + ObjectTypeDB::bind_method(_MD("get_button:Button"),&EditorLineEditFileChooser::get_button); + ObjectTypeDB::bind_method(_MD("get_line_edit:LineEdit"),&EditorLineEditFileChooser::get_line_edit); + ObjectTypeDB::bind_method(_MD("get_file_dialog:EditorFileDialog"),&EditorLineEditFileChooser::get_file_dialog); + +} + +void EditorLineEditFileChooser::_chosen(const String& p_text){ + + line_edit->set_text(p_text); + line_edit->emit_signal("text_entered",p_text); +} + +void EditorLineEditFileChooser::_browse() { + + dialog->popup_centered_ratio(); +} + +EditorLineEditFileChooser::EditorLineEditFileChooser() { + + line_edit = memnew( LineEdit ); + add_child(line_edit); + line_edit->set_h_size_flags(SIZE_EXPAND_FILL); + button = memnew( Button ); + button->set_text(" .. "); + add_child(button); + button->connect("pressed",this,"_browse"); + dialog = memnew( EditorFileDialog); + add_child(dialog); + dialog->connect("file_selected",this,"_chosen"); + dialog->connect("dir_selected",this,"_chosen"); + dialog->connect("files_selected",this,"_chosen"); + +} diff --git a/tools/editor/editor_file_dialog.h b/tools/editor/editor_file_dialog.h new file mode 100644 index 00000000000..72b88487887 --- /dev/null +++ b/tools/editor/editor_file_dialog.h @@ -0,0 +1,198 @@ +/*************************************************************************/ +/* file_dialog.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + + +#ifndef EDITORFILEDIALOG_H +#define EDITORFILEDIALOG_H + +#include "scene/gui/dialogs.h" +#include "scene/gui/tree.h" +#include "scene/gui/line_edit.h" +#include "scene/gui/option_button.h" +#include "scene/gui/dialogs.h" +#include "os/dir_access.h" +#include "scene/gui/box_container.h" +#include "scene/gui/texture_frame.h" + +/** + @author Juan Linietsky +*/ +class EditorFileDialog : public ConfirmationDialog { + + OBJ_TYPE( EditorFileDialog, ConfirmationDialog ); + +public: + + enum Access { + ACCESS_RESOURCES, + ACCESS_USERDATA, + ACCESS_FILESYSTEM + }; + + + enum Mode { + MODE_OPEN_FILE, + MODE_OPEN_FILES, + MODE_OPEN_DIR, + MODE_SAVE_FILE, + }; + + typedef Ref (*GetIconFunc)(const String&); + typedef void (*RegisterFunc)(EditorFileDialog*); + + static GetIconFunc get_icon_func; + static GetIconFunc get_large_icon_func; + static RegisterFunc register_func; + static RegisterFunc unregister_func; + +private: + + ConfirmationDialog *makedialog; + LineEdit *makedirname; + + Button *makedir; + Access access; + //Button *action; + VBoxContainer *vbox; + Mode mode; + LineEdit *dir; + OptionButton *drives; + Tree *tree; + TextureFrame *preview; + VBoxContainer *preview_vb; + HBoxContainer *list_hb; + LineEdit *file; + AcceptDialog *mkdirerr; + AcceptDialog *exterr; + OptionButton *filter; + DirAccess *dir_access; + ConfirmationDialog *confirm_save; + + Vector filters; + + bool preview_waiting; + int preview_wheel_index; + float preview_wheel_timeout; + static bool default_show_hidden_files; + bool show_hidden_files; + + bool invalidated; + + void update_dir(); + void update_file_list(); + void update_filters(); + + void _tree_selected(); + + void _select_drive(int p_idx); + void _tree_dc_selected(); + void _dir_entered(String p_dir); + void _file_entered(const String& p_file); + void _action_pressed(); + void _save_confirm_pressed(); + void _cancel_pressed(); + void _filter_selected(int); + void _make_dir(); + void _make_dir_confirm(); + + void _update_drives(); + + virtual void _post_popup(); + + + //callback funtion is callback(String p_path,Ref preview,Variant udata) preview null if could not load + + void _thumbnail_done(const String& p_path,const Ref& p_preview, const Variant& p_udata); + void _request_single_thumbnail(const String& p_path); + +protected: + + void _notification(int p_what); + static void _bind_methods(); + //bind helpers +public: + + void clear_filters(); + void add_filter(const String& p_filter); + + void set_enable_multiple_selection(bool p_enable); + Vector get_selected_files() const; + + String get_current_dir() const; + String get_current_file() const; + String get_current_path() const; + void set_current_dir(const String& p_dir); + void set_current_file(const String& p_file); + void set_current_path(const String& p_path); + + void set_mode(Mode p_mode); + Mode get_mode() const; + + VBoxContainer *get_vbox(); + LineEdit *get_line_edit() { return file; } + + void set_access(Access p_access); + Access get_access() const; + + void set_show_hidden_files(bool p_show); + bool is_showing_hidden_files() const; + + static void set_default_show_hidden_files(bool p_show); + + void invalidate(); + + EditorFileDialog(); + ~EditorFileDialog(); + +}; + +class EditorLineEditFileChooser : public HBoxContainer { + + OBJ_TYPE( EditorLineEditFileChooser, HBoxContainer ); + Button *button; + LineEdit *line_edit; + EditorFileDialog *dialog; + + void _chosen(const String& p_text); + void _browse(); +protected: + static void _bind_methods(); +public: + + Button *get_button() { return button; } + LineEdit *get_line_edit() { return line_edit; } + EditorFileDialog *get_file_dialog() { return dialog; } + + EditorLineEditFileChooser(); +}; + +VARIANT_ENUM_CAST( EditorFileDialog::Mode ); +VARIANT_ENUM_CAST( EditorFileDialog::Access ); + +#endif // EDITORFILEDIALOG_H diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 7157dbda965..500f8d232e9 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -99,6 +99,7 @@ #include "tools/editor/io_plugins/editor_translation_import_plugin.h" #include "tools/editor/io_plugins/editor_mesh_import_plugin.h" +#include "plugins/editor_preview_plugins.h" EditorNode *EditorNode::singleton=NULL; @@ -320,6 +321,11 @@ void EditorNode::_fs_changed() { E->get()->invalidate(); } + + for(Set::Element *E=editor_file_dialogs.front();E;E=E->next()) { + + E->get()->invalidate(); + } } void EditorNode::_sources_changed(bool p_exist) { @@ -386,7 +392,7 @@ void EditorNode::edit_node(Node *p_node) { void EditorNode::open_resource(const String& p_type) { - file->set_mode(FileDialog::MODE_OPEN_FILE); + file->set_mode(EditorFileDialog::MODE_OPEN_FILE); List extensions; ResourceLoader::get_recognized_extensions_for_type(p_type,&extensions); @@ -718,6 +724,96 @@ void EditorNode::_save_edited_subresources(Node* scene,Map& processed, } +void EditorNode::_find_node_types(Node* p_node, int&count_2d, int&count_3d) { + + if (p_node->is_type("Viewport") || (p_node!=get_edited_scene() && p_node->get_owner()!=get_edited_scene())) + return; + + if (p_node->is_type("CanvasItem")) + count_2d++; + else if (p_node->is_type("Spatial")) + count_3d++; + + for(int i=0;iget_child_count();i++) + _find_node_types(p_node->get_child(i),count_2d,count_3d); + +} + + +void EditorNode::_save_scene_with_preview(String p_file) { + + int c2d=0; + int c3d=0; + + EditorProgress save("save","Saving Scene",4); + save.step("Analyzing",0); + _find_node_types(get_edited_scene(),c2d,c3d); + + RID viewport; + bool is2d; + if (c3dget_viewport(); + is2d=true; + } else { + viewport=SpatialEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_viewport(); + is2d=false; + + } + save.step("Creating Thumbnail",1); + //current view? + int screen =-1; + for(int i=0;iviewport_queue_screen_capture(viewport); + save.step("Creating Thumbnail",2); + save.step("Creating Thumbnail",3); + Image img = VS::get_singleton()->viewport_get_screen_capture(viewport); + int preview_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");; + int width,height; + if (img.get_width() > preview_size && img.get_width() >= img.get_height()) { + + width=preview_size; + height = img.get_height() * preview_size / img.get_width(); + } else if (img.get_height() > preview_size && img.get_height() >= img.get_width()) { + + height=preview_size; + width = img.get_width() * preview_size / img.get_height(); + } else { + + width=img.get_width(); + height=img.get_height(); + } + + img.convert(Image::FORMAT_RGB); + img.resize(width,height); + + String pfile = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/last_scene_preview.png"); + img.save_png(pfile); + Vector imgdata = FileAccess::get_file_as_array(pfile); + + print_line("img data is "+itos(imgdata.size())); + + if (scene_import_metadata.is_null()) + scene_import_metadata = Ref( memnew( ResourceImportMetadata ) ); + scene_import_metadata->set_option("thumbnail",imgdata); + + //tamanio tel thumbnail + if (screen!=-1) { + _editor_select(screen); + } + save.step("Saving Scene",4); + _save_scene(p_file); + +} + + void EditorNode::_save_scene(String p_file) { Node *scene = edited_scene; @@ -1016,7 +1112,9 @@ void EditorNode::_dialog_action(String p_file) { if (file->get_mode()==FileDialog::MODE_SAVE_FILE) { - _save_scene(p_file); + //_save_scene(p_file); + _save_scene_with_preview(p_file); + } } break; @@ -1024,7 +1122,8 @@ void EditorNode::_dialog_action(String p_file) { case FILE_SAVE_AND_RUN: { if (file->get_mode()==FileDialog::MODE_SAVE_FILE) { - _save_scene(p_file); + //_save_scene(p_file); + _save_scene_with_preview(p_file); _run(false); } } break; @@ -1177,7 +1276,8 @@ void EditorNode::_dialog_action(String p_file) { if (file->get_mode()==FileDialog::MODE_SAVE_FILE) { - _save_scene(p_file); + //_save_scene(p_file); + _save_scene_with_preview(p_file); } } break; @@ -1505,7 +1605,8 @@ void EditorNode::_run(bool p_current,const String& p_custom) { return; } - _save_scene(scene->get_filename()); + //_save_scene(scene->get_filename()); + _save_scene_with_preview(scene->get_filename()); } } @@ -1608,7 +1709,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { //print_tree(); - file->set_mode(FileDialog::MODE_OPEN_FILE); + file->set_mode(EditorFileDialog::MODE_OPEN_FILE); //not for now? List extensions; ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions); @@ -1659,7 +1760,8 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { Node *scene = edited_scene; if (scene && scene->get_filename()!="") { - _save_scene(scene->get_filename()); + //_save_scene(scene->get_filename()); + _save_scene_with_preview(scene->get_filename()); return; }; // fallthrough to save_as @@ -1678,7 +1780,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { break; } - file->set_mode(FileDialog::MODE_SAVE_FILE); + file->set_mode(EditorFileDialog::MODE_SAVE_FILE); bool relpaths = (scene->has_meta("__editor_relpaths__") && scene->get_meta("__editor_relpaths__").operator bool()); @@ -1761,7 +1863,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { bool relpaths = (scene->has_meta("__editor_relpaths__") && scene->get_meta("__editor_relpaths__").operator bool()); - file->set_mode(FileDialog::MODE_SAVE_FILE); + file->set_mode(EditorFileDialog::MODE_SAVE_FILE); file->set_current_path(cpath); file->set_title("Save Translatable Strings"); @@ -1810,7 +1912,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { break; } - file->set_mode(FileDialog::MODE_SAVE_FILE); + file->set_mode(EditorFileDialog::MODE_SAVE_FILE); List extensions; Ref sd = memnew( PackedScene ); @@ -3132,6 +3234,7 @@ void EditorNode::register_editor_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); //ObjectTypeDB::register_type(); @@ -3282,6 +3385,16 @@ void EditorNode::_file_dialog_unregister(FileDialog *p_dialog){ singleton->file_dialogs.erase(p_dialog); } +void EditorNode::_editor_file_dialog_register(EditorFileDialog *p_dialog) { + + singleton->editor_file_dialogs.insert(p_dialog); +} + +void EditorNode::_editor_file_dialog_unregister(EditorFileDialog *p_dialog){ + + singleton->editor_file_dialogs.erase(p_dialog); +} + Vector EditorNode::_init_callbacks; Error EditorNode::export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after) { @@ -3334,6 +3447,11 @@ EditorNode::EditorNode() { FileDialog::register_func=_file_dialog_register; FileDialog::unregister_func=_file_dialog_unregister; + EditorFileDialog::get_icon_func=_file_dialog_get_icon; + EditorFileDialog::register_func=_editor_file_dialog_register; + EditorFileDialog::unregister_func=_editor_file_dialog_unregister; + + editor_import_export = memnew( EditorImportExport ); add_child(editor_import_export); @@ -3358,6 +3476,9 @@ EditorNode::EditorNode() { editor_register_icons(theme); editor_register_fonts(theme); + //theme->set_icon("folder","EditorFileDialog",Theme::get_default()->get_icon("folder","EditorFileDialog")); + //theme->set_color("files_disabled","EditorFileDialog",Color(0,0,0,0.7)); + String global_font = EditorSettings::get_singleton()->get("global/font"); if (global_font!="") { Ref fnt = ResourceLoader::load(global_font); @@ -3376,6 +3497,8 @@ EditorNode::EditorNode() { theme->set_stylebox("EditorFocus","EditorStyles",focus_sbt); + resource_preview = memnew( EditorResourcePreview ); + add_child(resource_preview); progress_dialog = memnew( ProgressDialog ); gui_base->add_child(progress_dialog); @@ -3473,6 +3596,7 @@ EditorNode::EditorNode() { animation_panel=pc; animation_panel->hide(); + HBoxContainer *animation_hb = memnew( HBoxContainer); animation_vb->add_child(animation_hb); @@ -4031,7 +4155,7 @@ EditorNode::EditorNode() { file_templates->add_filter("*.tpz ; Template Package"); - file = memnew( FileDialog ); + file = memnew( EditorFileDialog ); gui_base->add_child(file); file->set_current_dir("res://"); @@ -4161,6 +4285,13 @@ EditorNode::EditorNode() { for(int i=0;iadd_preview_generator( Ref( memnew(EditorTexturePreviewPlugin ))); + resource_preview->add_preview_generator( Ref( memnew(EditorPackedScenePreviewPlugin ))); + resource_preview->add_preview_generator( Ref( memnew(EditorMaterialPreviewPlugin ))); + resource_preview->add_preview_generator( Ref( memnew(EditorScriptPreviewPlugin ))); + resource_preview->add_preview_generator( Ref( memnew(EditorSamplePreviewPlugin ))); + circle_step_msec=OS::get_singleton()->get_ticks_msec(); circle_step_frame=OS::get_singleton()->get_frames_drawn();; circle_step=0; diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index 614cec5bcc1..365dff84ee2 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -78,7 +78,7 @@ #include "tools/editor/editor_plugin.h" #include "fileserver/editor_file_server.h" - +#include "editor_resource_preview.h" @@ -238,7 +238,7 @@ class EditorNode : public Node { EditorSettingsDialog *settings_config_dialog; RunSettingsDialog *run_settings_dialog; ProjectSettings *project_settings; - FileDialog *file; + EditorFileDialog *file; FileDialog *file_templates; FileDialog *file_export; FileDialog *file_export_lib; @@ -304,6 +304,7 @@ class EditorNode : public Node { EditorSelection *editor_selection; ProjectExport *project_export; ProjectExportDialog *project_export_settings; + EditorResourcePreview *resource_preview; EditorFileServer *file_server; @@ -381,11 +382,15 @@ class EditorNode : public Node { String import_reload_fn; Set file_dialogs; + Set editor_file_dialogs; + Map > icon_type_cache; static Ref _file_dialog_get_icon(const String& p_path); static void _file_dialog_register(FileDialog *p_dialog); static void _file_dialog_unregister(FileDialog *p_dialog); + static void _editor_file_dialog_register(EditorFileDialog *p_dialog); + static void _editor_file_dialog_unregister(EditorFileDialog *p_dialog); void _cleanup_scene(); @@ -394,6 +399,9 @@ class EditorNode : public Node { bool _find_and_save_edited_subresources(Object *obj,Map& processed,int32_t flags); void _save_edited_subresources(Node* scene,Map& processed,int32_t flags); + void _find_node_types(Node* p_node, int&count_2d, int&count_3d); + void _save_scene_with_preview(String p_file); + struct ExportDefer { String platform; diff --git a/tools/editor/editor_resource_preview.cpp b/tools/editor/editor_resource_preview.cpp new file mode 100644 index 00000000000..9b7d8d227e0 --- /dev/null +++ b/tools/editor/editor_resource_preview.cpp @@ -0,0 +1,260 @@ +#include "editor_resource_preview.h" +#include "editor_settings.h" +#include "os/file_access.h" +#include "io/resource_loader.h" +#include "io/resource_saver.h" +#include "globals.h" + + +Ref EditorResourcePreviewGenerator::generate_from_path(const String& p_path) { + + RES res = ResourceLoader::load(p_path); + if (!res.is_valid()) + return res; + return generate(res); +} + +EditorResourcePreviewGenerator::EditorResourcePreviewGenerator() { + + +} + + +EditorResourcePreview* EditorResourcePreview::singleton=NULL; + + +void EditorResourcePreview::_thread_func(void *ud) { + + EditorResourcePreview *erp=(EditorResourcePreview*)ud; + erp->_thread(); + +} + + +void EditorResourcePreview::_preview_ready(const String& p_str,const Ref& p_texture,ObjectID id,const StringName& p_func,const Variant& p_ud) { + + print_line("preview is ready"); + preview_mutex->lock(); + + Item item; + item.order=order++; + item.preview=p_texture; + cache[p_str]=item; + + Object *recv = ObjectDB::get_instance(id); + if (recv) { + recv->call_deferred(p_func,p_str,p_texture,p_ud); + } + + preview_mutex->unlock(); +} + +Ref EditorResourcePreview::_generate_preview(const QueueItem& p_item,const String& cache_base) { + + String type = ResourceLoader::get_resource_type(p_item.path); + print_line("resource type is: "+type); + + if (type=="") + return Ref(); //could not guess type + + Ref generated; + + for(int i=0;ihandles(type)) + continue; + generated = preview_generators[i]->generate_from_path(p_item.path); + + break; + } + + if (generated.is_valid()) { + print_line("was generated"); + int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size"); + //wow it generated a preview... save cache + ResourceSaver::save(cache_base+".png",generated); + FileAccess *f=FileAccess::open(cache_base+".txt",FileAccess::WRITE); + f->store_line(itos(thumbnail_size)); + f->store_line(itos(FileAccess::get_modified_time(p_item.path))); + f->store_line(FileAccess::get_md5(p_item.path)); + memdelete(f); + } else { + print_line("was not generated"); + + } + + return generated; +} + +void EditorResourcePreview::_thread() { + + print_line("begin thread"); + while(!exit) { + + print_line("wait for semaphore"); + preview_sem->wait(); + preview_mutex->lock(); + + print_line("blue team go"); + + if (queue.size()) { + + print_line("pop from queue"); + + QueueItem item = queue.front()->get(); + queue.pop_front(); + preview_mutex->unlock(); + + Ref texture; + + + uint64_t modtime = FileAccess::get_modified_time(item.path); + int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size"); + + if (cache.has(item.path)) { + //already has it because someone loaded it, just let it know it's ready + call_deferred("_preview_ready",item.path,cache[item.path].preview,item.id,item.function,item.userdata); + + } else { + + + String temp_path=EditorSettings::get_singleton()->get_settings_path().plus_file("tmp"); + String cache_base = Globals::get_singleton()->globalize_path(item.path).md5_text(); + cache_base = temp_path.plus_file("resthumb-"+cache_base); + + //does not have it, try to load a cached thumbnail + + String file = cache_base+".txt"; + print_line("cachetxt at "+file); + FileAccess *f=FileAccess::open(file,FileAccess::READ); + if (!f) { + + print_line("generate because not cached"); + + //generate + texture=_generate_preview(item,cache_base); + } else { + + int tsize = f->get_line().to_int64(); + uint64_t last_modtime = f->get_line().to_int64(); + + bool cache_valid = true; + + if (tsize!=thumbnail_size) { + cache_valid=false; + memdelete(f); + } else if (last_modtime!=modtime) { + + String last_md5 = f->get_line(); + String md5 = FileAccess::get_md5(item.path); + memdelete(f); + + if (last_md5!=md5) { + + cache_valid=false; + } else { + //update modified time + + f=FileAccess::open(file,FileAccess::WRITE); + f->store_line(itos(modtime)); + f->store_line(md5); + memdelete(f); + } + } else { + memdelete(f); + } + + if (cache_valid) { + + texture = ResourceLoader::load(cache_base+".png","ImageTexture",true); + if (!texture.is_valid()) { + //well fuck + cache_valid=false; + } + } + + if (!cache_valid) { + + texture=_generate_preview(item,cache_base); + } + + } + + print_line("notify of preview ready"); + call_deferred("_preview_ready",item.path,texture,item.id,item.function,item.userdata); + + } + + } else { + preview_mutex->unlock(); + } + + } +} + + + + +void EditorResourcePreview::queue_resource_preview(const String& p_path, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata) { + + ERR_FAIL_NULL(p_receiver); + preview_mutex->lock(); + if (cache.has(p_path)) { + cache[p_path].order=order++; + p_receiver->call_deferred(p_receiver_func,p_path,cache[p_path].preview,p_userdata); + preview_mutex->unlock(); + return; + + } + + print_line("send to thread"); + QueueItem item; + item.function=p_receiver_func; + item.id=p_receiver->get_instance_ID(); + item.path=p_path; + item.userdata=p_userdata; + + queue.push_back(item); + preview_mutex->unlock(); + preview_sem->post(); + +} + +void EditorResourcePreview::add_preview_generator(const Ref& p_generator) { + + preview_generators.push_back(p_generator); +} + +EditorResourcePreview* EditorResourcePreview::get_singleton() { + + return singleton; +} + +void EditorResourcePreview::_bind_methods() { + + ObjectTypeDB::bind_method("_preview_ready",&EditorResourcePreview::_preview_ready); +} + +EditorResourcePreview::EditorResourcePreview() { + singleton=this; + preview_mutex = Mutex::create(); + preview_sem = Semaphore::create(); + order=0; + exit=false; + + thread = Thread::create(_thread_func,this); +} + + +EditorResourcePreview::~EditorResourcePreview() +{ + + exit=true; + preview_sem->post(); + Thread::wait_to_finish(thread); + memdelete(thread); + memdelete(preview_mutex); + memdelete(preview_sem); + + +} + diff --git a/tools/editor/editor_resource_preview.h b/tools/editor/editor_resource_preview.h new file mode 100644 index 00000000000..f8b96eca224 --- /dev/null +++ b/tools/editor/editor_resource_preview.h @@ -0,0 +1,95 @@ +#ifndef EDITORRESOURCEPREVIEW_H +#define EDITORRESOURCEPREVIEW_H + +#include "scene/main/node.h" +#include "os/semaphore.h" +#include "os/thread.h" +#include "scene/resources/texture.h" + +/* make previews for: +*packdscene +-wav +*image +-mesh +-font +*script +*material +-shader +-shader graph? +-navigation mesh +-collision? +-occluder polygon +-navigation polygon +-tileset +-curve and curve2D +*/ + + +class EditorResourcePreviewGenerator : public Reference { + + OBJ_TYPE(EditorResourcePreviewGenerator,Reference ); + +public: + + virtual bool handles(const String& p_type) const=0; + virtual Ref generate(const RES& p_from)=0; + virtual Ref generate_from_path(const String& p_path); + + EditorResourcePreviewGenerator(); +}; + + +class EditorResourcePreview : public Node { + + OBJ_TYPE(EditorResourcePreview,Node); + + + static EditorResourcePreview* singleton; + + struct QueueItem { + String path; + ObjectID id; + StringName function; + Variant userdata; + }; + + List queue; + + Mutex *preview_mutex; + Semaphore *preview_sem; + Thread *thread; + bool exit; + + struct Item { + Ref preview; + int order; + }; + + int order; + + Map cache; + + void _preview_ready(const String& p_str,const Ref& p_texture, ObjectID id, const StringName &p_func, const Variant &p_ud); + Ref _generate_preview(const QueueItem& p_item, const String &cache_base); + + static void _thread_func(void *ud); + void _thread(); + + Vector > preview_generators; +protected: + + static void _bind_methods(); +public: + + static EditorResourcePreview* get_singleton(); + + //callback funtion is callback(String p_path,Ref preview,Variant udata) preview null if could not load + void queue_resource_preview(const String& p_path, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata); + + void add_preview_generator(const Ref& p_generator); + + EditorResourcePreview(); + ~EditorResourcePreview(); +}; + +#endif // EDITORRESOURCEPREVIEW_H diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp index f49d3b496d4..2fac05753a4 100644 --- a/tools/editor/editor_settings.cpp +++ b/tools/editor/editor_settings.cpp @@ -448,6 +448,8 @@ void EditorSettings::_load_defaults() { set("text_editor/create_signal_callbacks",true); set("file_dialog/show_hidden_files", false); + set("file_dialog/thumbnail_size", 64); + hints["file_dialog/thumbnail_size"]=PropertyInfo(Variant::INT,"file_dialog/thumbnail_size",PROPERTY_HINT_RANGE,"32,128,16"); set("animation/autorename_animation_tracks",true); set("animation/confirm_insert_track",true); diff --git a/tools/editor/icons/icon_wait_no_preview.png b/tools/editor/icons/icon_wait_no_preview.png new file mode 100644 index 0000000000000000000000000000000000000000..5d20cd99ece8ad40b588346c38d01c3a5556ca72 GIT binary patch literal 1041 zcmV+s1n&EZP)WFU8GbZ8()Nlj2>E@cM*00VVNL_t(|+U=RoiyTE1 z$6HAJaZA>f5DaAFMLhTqM9n6_5OYyHg{X%ZZz2j35m8}}9*hPFfvg9GBzQ3ih6Dmh zAPR|*j1dnD>VmE=F60tty0?33wyHku@O80yyU;0b5o8{K$zAchEWaLX;2QtrGya zCLKPN=lP~IO~-)aV!JW20!ZgRiSohIH3H;iS(b~7i;o0br_b?NNqS(c4=I-QNc39(%nc>yFJ zJYOe(bM85SK1tA8YoA#a0?0^zJV2m*zzul?=D;=Q+@$WU6-7}LMN!rQz&YUDifvz` zJ$Me>_TInIudum{0vN!oxB!*H<_G_y0B2To288c-W6U<-vryAp^=q%+7h1dB-XH?> zs(#M7UBE9u5q-_=0a`#0nD^el6OHW8p{+4yLTUsP(UQB}@F_hg_HPp7Qe^ug)F!hm z8&8rX@!r2LwqFMd&}y~TNkQ|NG`Lmu1MXC6f0KagvwU8Xo4*~|4vOtyWP80%fTq~M zr}9j9L%st3jt1*Rv3(WFU8GbZ8()Nlj2>E@cM*00bOKL_t(|+U=TKZyQw< zg}*&^N)qQzi$kdd;?fd7A^rxB{7%GQ;VGn~1tg@9v=GN}oHlLj#lvh%!^p9Hj%Vyt zo+XXqj6HkrwdU+|_PIcX3Kc3;s8C^9VT*7o=?CD!{{k`lc@eSH7bN`mz=~f(ER_JQ z1^T`h0(=J4{BwU91=v_r|5K;{k`gl;L_GRYL7iz07?_#nE`X$UU`^Hf@MF*;^;8)`QR zeZb7FfHUA-CXkxHg?->a(q6&j_kaVppJc9@r@@JtUB=i>VjeQHbKp&IeE+Z>jJ-<*}t*&lh_B%>=p0=xXcBW6eU82d~*c(OW@e!VD19A2xq`=9*pIB z_L)S;kHhOO3q-^q~Es15) z;o1Z5MA+DN8|!6}FBOt@J)dW>u~AlKS)sy&K0wkFAJVow59@wqYjGRXnf+8?I{i4| zCxgt@_v^+>^^Tbx$BqJ7qV|EjOv}X{Jq#uzjDCnMJSn0M&^(6E5?X_1X#oQ_peY2o zccXBQM}-PiC0NY`MxtIK`JLg~fTSQ1GUOlot(GLp5Fsg%{1A_wKx0Z9jU0L0Ud!#@ zPXQ*Z2-O18%^1CLQi=%mIgmf|9KIS?+YjdsW_Bg%&~G>I5TUSiND3goPr73>j{JF0 z&z%1L(4QaG5)O)L3CWD)o4_*~OIvxv}^^xWgvbMnK35nTcgM+6ICW&=s>T!+*K{tB%3HG>Ejl8%8dJPmum zE8rh9>zCaEFtfgkAfKq5PrK_=)FOqMbtJtcJsb2EcpY;(B)SsJh|r02JSZR?t|Z-% zo)e5dZCalpfWZtz`nl=2B4c=e@210n0xTSh65w5K2p%k(0N2YdK$i*?DpaVjc>D)i W-0bIb*aj^C0000WFU8GbZ8()Nlj2>E@cM*00de|L_t(|+U=UVZyZ$= z#(!sQC&uf<4>>rAB7p!UWQ8aqECdKBD5w$QFQBDE;eVh-NE9^mfRI3&!0+JdY$xi^gl2*-ZGo=UQ@x14Ox4aL3 z`MaOZtX;YQ@yI**1~3UUB>iq?trYb~m<5!g{UzXC-~w>ZU%&33{b**pr3v73{)9hM zPJYsb7?*V2%hWdZeP9Wg0FJxx3&0NWQwk5v9t6#73t00J2&1^U2p1*I7fk+D;4<)nd+mh(JqFwb zzA>{aL(2kYwhr6`w%mpVe;0vfQ6fls4fr4+A7_sV;1=+inSD3(G-zgbfa}16ga}bl zA~^ZWz@@-;EW#har)KtTWrdKLt$E;i&?mCz5+Ol8nLYjlJ~6YeE3E{BW$cQJkVGaC z_8=eQCh)PDeKk`10g}#mDw^%{@fvW&1L#3^n!ty9kpB(%$jm+;iM2q&6K(^`K)*Vm zlcLz!1=_gN+%tG37RHm(kbp63NfTdjpbEi4c%K>#v%UC_{v(MDj7tI)TQ3 zHW~@?xV@&^A58%c*by2_G2M**M`xvoFg^tGYd(j!_N(pVwS$>$Nm};Ti+hMr*mQ^r zAb%Qo_5kwhsUmal`^*0Oex7i#C{M_HKVXsGA?0kJ>M#@e0Y#XhcMP{!nE-y%>%1?Q zlVx)*@&||zw{;RY@BJ9A0FoAfr-A8!c-*noBFOge9a#ld%xt5SlC>woicg17_#Jwu#0!#+ zmz@SXz$X9Q3y84++!*k3L>>_~B>n3Bn0NARdUqB!=^d(+CxDrCC2b@E(gtuVWxcN) zBHWjB4S3S0;WlswxMyaa(hDIo>$nK=h06M%r#?k(QkYpw(hcAg@DFe|?cJbUm0%!3 zD`Ugm0;a>3q&CpaGV-}gVZSewl}IPC99PCZ?2O!UIHdrUqbdO&B~ozrs0r}!s0*-3 gjT$v-)Tkc+0@W<_=I=MfjsO4v07*qoM6N<$f>}yKr2qf` literal 0 HcmV?d00001 diff --git a/tools/editor/icons/icon_wait_preview_3.png b/tools/editor/icons/icon_wait_preview_3.png new file mode 100644 index 0000000000000000000000000000000000000000..2775d1ef43c79d312ed9fdaa496613a9f3c90259 GIT binary patch literal 1190 zcmV;X1X=ruP)WFU8GbZ8()Nlj2>E@cM*00at2L_t(|+U=U_ZW~n; zg}*&^Xoz!jXmBW%KtNlPU%U%1#mn$6{0b>;0SO36fjExsl%(-2et26tjGWkWwI$Dz zMsddDefC;&_T|hRs8ORvjT$v-tSW2~gG%}si2mn@+1Vm|X)Z|kwhIu7uu=l-E^78I zivX?Q?#HVrzz55c1ak=>DKfJxcd$`VGHn2{nJKG{D97L%KwHv!#&IJTqLIZ9AAcX% zmK0Sw10=OPlWzfclFrPmU)2ndv;}*x%`dMaUGwYpq@-1K;Xi56T%z7#MkFW|T z#rQkG7hXx;`RRTC?ka6KG}Fes6W;SMr`XW{{m{uzV)y`fA*o$b_t*x$20B6RSaUyOpl4=xr6)l%8vy6PZQw}5@4^9a zC~2=?@_WFc+m8}S^c`?&W>=L}0W-S*egy_@!-BsZ;HW4O+|H4cx5RjT;Ab=Yr}8pr zW^aMlz*WMjs3;Kv@|`K}&$x+(Z5nI5x9Ci}E`v%8)yC>`o>z zO401duP>c^p#nT0!l^qxoYTh8ZJd@(zO+YTK{#By#KFq_)R%9vhow zb(S@1%*X+fo_a~!_Bd?%5%%KtKr;Kjz;OCw#wB;baqBC?OW=3!8NSO}1wx{>%KLy)Db!olbFb*isXcY^g=;65}< zB)>a(HXtdL2m$#ge(FdPWrz@!NPdDRPM|fXjaGs@ZtuwLFQ))Ao(MHkgqtz_)mbSb zG%Fx~?lC+FuK)JFwS$=rBpv(d&OIU&77kGXc=wE{?b415V}2E-?h zofScTiU?=H7@-JXN!qVW0I$(c8NU*bgQIZr2@!srB0}sp;j^qAW0aEo8nEYO>c*Fw z6GzVc=}WhimUS$`iHAcd{CmbbMIK9fRCXC0F@7Vvo~YGb;LV(yBl3vQmGsj6*mLre zjS+oPZjMMTfSJXTx`~9;1%6A}?<@u~@Mz3Kw=sZpawjT(!`e-T9H6`l&hWFU8GbZ8()Nlj2>E@cM*00db{L_t(|+U=UpYg|G3L=iAQF7G=m1k_@)-ALatuBV)Fn-295-?zDp~CC@lOE9B}F6k07*5ETf{|2WXmED|iqzvj@OB@F-?T#b;p&I4^0TVDJmTdDkB$g6KnF&CIq( zmIcgg1NZ}Y;5sb!xd<#5MS|;DcJP)MZwI(%X8(*l4Vu|~;4ZM8Fe)mFgc$h6KH#^3 zJ8lOfC%{Qq2Yz*9l94?Z2?_AYfY}6o@$nfO0kJmrwv&*QOe72dkAuHmRQqfN2C9>8 z^n9P6*MXlsfF7i026*!c;J1KPGyA(JyQ88MxlyZbWK!Bg6g%?&2M1p$0Ru=_bHjI2 z>ezK1YoWmh+Y*Z{hdnpEnL)>#>zED&KB!2l`+Cl!V%fbm9rId0+E5T(+Zy!bQCndcrX~k>$EIKYo`bN?XNgsu>wHg9^ zY+qpB-wo9eNxA@B23GvlB}tgswW95f0)p?!3v_pdYAJP`O@N2)LCB>Lo)85F-;>G^ zwL=wny3hL{B-jYRuX{hgF{rkW_YRUS0$&1e_0e|^_`0a&5ETG^iSCI_D)6ah#q2up z74Xv&JmHHJ4N`alBrO8x9K4DEpMnGduL7S-`e1AX_)V{~-YzH0=3L+hkf2!0`-+qB z{>TZC^c?USFcSmbBcV|Q_&y}uO7#0};AP-bN$-t}055D#(LEB6Z$uOhK0(42;KvyF z7Vy~9?8lN;f)gO=7_i`JZQl*)5zwG}VzU{fzcsr7Ty;-)>`#mC&hs2_(X&y|O0Z4$ zM7DP?peLKaZz(TFWFU8GbZ8()Nlj2>E@cM*00aw3L_t(|+U=U#ZW~n; zhQBp-A;dX3G&r=CKpa|^6H2R489JuC9UNgH*z8xdF=4<_kb-) z(Ly~yQp+>>CU7gMYi7emd4Qx%;HihwTYompD0_Fa)h4EIsOjtE%0fodKhpGjDXw9 za)7(o$p8Gr!B1j%A9x|DT~YVg2EGG2LGF0ucErHI%x)`Bf@XFF^nmw)Aq}5}ec(XS zZpq+xfdkhcrIP47;LOY}7ghz#>>T(VxN;p9e0PAuvPf_}hYsFS;|+md&Fr6rmq9ao z4V(g(DWjsYNC?1prhvZ$PTUR_PJolp1AcL1(wV&w2`TXDggF3S`uHr3fM6MW>?EWm z7YTQO$H5<$wS2Y`6V>N#^v;x@d%#bgKxgUM0KWeK_zU33%>F9N?x-w9Zq$(*nU-;e zW=H;h<={&t;0_Yb-0;zyI!3PJtZML;ZHWcp@YW3<u~AiL zSxYT5a)6{~UedNa4x9c7dvUuXnf+K|IQ=l=l{ol}{d4WD`oPRi@>YQmsNIvvw3O|+ z%V0D`>3#I@sEj^9izuHJc!P>~K$SjCX;uh+XR?x?grBF75c?#2k+)-vGJ<~u?0T8H_MMlBAzhLan|>uN zYeK@YheJsG4arTB$C5s-x(tp@1$9PS0PjH;qqnZU=F)rZBH>u^ga@ugSa?9a4 z<^8H`+$@WLVNgXZPxij=1oTp4KR5zTsil@$YN=)U@*kwe=h#n*N$mgt002ovPDHLk FV1m#ICG`LR literal 0 HcmV?d00001 diff --git a/tools/editor/icons/icon_wait_preview_6.png b/tools/editor/icons/icon_wait_preview_6.png new file mode 100644 index 0000000000000000000000000000000000000000..307e4123108af0693beccf37d6d890a605455d94 GIT binary patch literal 1278 zcmVWFU8GbZ8()Nlj2>E@cM*00d%5L_t(|+U=UjZX9J4 zg}+m7z<7v<#BqR#AOrz>#R7yPmat-h#PkF#kPu?aGawYPVZ$4+fR_M)B~X9`a%>!i zm5CD|o$AIeHKXm z=ZJKD5Wds~B>YSWkQQO61ehLF^qmv|##48{IgA24cv6aBPXgFZB;~n-BLx-H5uho_ zd2J*;EItOz*dEQfZW2O_rVksMkl!)AJ4^i+uf!^t=pUr;*-EwkRJ^p zYPPRQ+RTx9>TvyO;A!A=rh5pe1A9QDv>Fg0wij<74)X0BJ_kHwd#0r6aRzu6m`~M? z2f~jguqCNcdJ&Yg3v2*)QjUzoT{s6U*q$wz{4B5#_LEEzy$!5O+U{Eykn|7m2e2D9 zlzN>97K;)g>?{U(W!BpPev|Zf-`k+18^ASSJL6PRln5#E^M{b%2G+t4`Yu3-umSuM z&SWclPagJl;25FhQg`ka59U7E`}Y)?@K3Nr~pTZupW-@b!cNRY^;|}zO=u@ zQt7ZCj&J3#F%>q($|7GXY|lhK_hMtBtjV%Mg=1=f?eo#nPDLKp;!4lrI-;0;SztQ7 zdCX6msp}xFdW`B@lGgHefizLwCpS|W-*dOYX=BRvCEG8@-lD&QP%q?x4`}^&53mG$ zB#i<~bdb zy9=a5xRUc^Mzer)*tK1!bx!agubo;C4%8$6^57t|8+A?}?w*LfKo0^89D@?zPG){+ o4x0e`!!E!M6)IGyP+{=+55%?gn)(F2^Z)<=07*qoM6N<$f=zNT)&Kwi literal 0 HcmV?d00001 diff --git a/tools/editor/icons/icon_wait_preview_7.png b/tools/editor/icons/icon_wait_preview_7.png new file mode 100644 index 0000000000000000000000000000000000000000..b0edc94d93cf9077a302698b07f26cbdba8392e7 GIT binary patch literal 1192 zcmV;Z1XufsP)WFU8GbZ8()Nlj2>E@cM*00az4L_t(|+U=U#Zdz9m zhQHb1#4$eM#>Gu4wQAEO_C?iq>2)75@6s#BiIcWcB^RfyF$SF2G5oz?kXE(`uunk6 z9%&1CgJ@I5d zEeip)VDty8NWi^iNrIUOkQA9&nh~tzluRqYz|53ZN0h<%22hu@p3-jQL{!rF;r91| zZAsBwXMm)dXYwuJPEym%I`f(VlD2@y9!l5#u9IdqR@08WgRcSWKuyx`X4X#7e}q*) z3GD9x-+3i@@2~g$yQ`$(P)!>14txvPaPaF+L{-uoGrLR?dN!l|UEl}ci&*tA;0EXc zcZKBupJF}#^MQjO#qa^}Oj5m|?y(L$2O2@{SaUxHK-yKhd^gVE9W><5o0%mpr`~h@bhXtPv;3zK=T+fk%x0t;S@SBS~ zPtfehe_uHGTnU&!!kIhXn^8y4b(|FqzOXH^ARMmU@pcLwJFa7+DDZ`fq`Jp*79E>K zb(W=+G9?E{`UUtAc;Y4L0dU_JAXR^&3CZknj^Xt4l%EWOr|-{=x9V*(J55^!*8B;# zux-f)(_*_$smtKKVCTmE$1^<2qYuzL%4Y$yL0M+NZ4gg!Wm<9q6w42#lu~wr&9nD$SoYA9KatiJh7Ps{vuIk9{&E=|9{*}ILvD% zL>a+1fM@QM@&G?02|Emr;Tj7gz;Ajz1-8B2R6s%|@KZ<_+1du4x*zi;K+;3tdtfsF zK60#?2lz20Gy@wU2~Q;L&y4`D(O)w>5)U^bat9wH;pG?-20jSir0p1^gy7eJJug!? zzET`H(qwpI(<-E89g=Y3;Sdu4(f2MMO1fWk8SFDWkzJ3~>K5>J#>){|NN7oV<$mlr z_|e6P4hb(uBqqSj29jE_gwz85OxW)$0|}RsPJwSd412&k;2$&V7v2b&S>H*JFH|mO zJ@v_Jlful}lHM}B8}tGAJI(Eo)SX~JLOZ45K@Q>2m2|`Ko?t(%o@xdM1{r|#W6N=+ z^x@;uEr$~luy9!v0k^RdJXkdXu2-Fa4yBY*N-3o*Uj761Dd!XnIN0p~0000WFU8GbZ8()Nlj2>E@cM*00f~)L_t(|+U=T4k5p9@ zg}-&X5J(6QTWA_VKpxRV(U71*J5a(O@COiof{BSnojY-6OiWCi7$*)K=)^d1W?Dpu zLCoputjw zhS90*Z9wwBfk?j(V=S#93BNG}7|A?aQUYw~^?+evSOTog2+&!I0<2gpL9mnnwjYvo zr$oO3T%!LL(3Vu#MpB~l-N4JXw-ywj6+v)Wkr!cmHSid)-gYuD4~Wj51SWvpz<%3b zN;;9l%t%Sk8wGX&D}h__?3$$ZAf~|14Ee3VD6rM`$C4)N7Qprf;MrJ7{))$2;=8Mo zI<*O4dnK?Z$Uhq7*8*d}D%**qZ|jvK&|yVoVhY$hqHyq?5qcz|9!IvP?kR3%q6fV8!Iefdjzy z=%?FSF%3>hx;n5`K+-qBC%}cC!6Y$1-?4qDBJ!Jn7l9qoPm)QauLCC}ogerzDCrB} zBj9|7e78LVyj@m=AU_drUeUTDTm_CxI#Z^PQu(-~&w&qtKQiRI73Q8YBJ_~YR<8>3 zMtUq}5=ox{9{}g(DX$BOa1ZibTminTs(e<3f$A{uTI2@3I0?Ki>8AzQSqB`t z2l>muq@>@f8h2$SsiaSV_ksE5$Nip&f@c(14LsD7_b2^= zsHFEQoKA1v=O^ts@7pb0cjVxr9OYXC2kt{;8d6)T- zD)In7pi{e3#sk`6p#1=f;2s_g8Vn&59FNLwQD=gxiF|kK{8kh(SBlgEVPkcjg;1+T z@?+7kolAra`Caj7!Zvk?kkm-Ni(Nrr%>r$#=^;r(5eZV6@zLOE56!|_PI9fYIe=csE4K@bY z-b{K9`0zZr_G#cqS@KyCA|{yhV6>ePdlcAfyCdoBKm@S8p7esmnixzrnK}b}FX>{X z+1h_1v`KG;bTS(t>wu?h&q}&ns{poF0OL_(-|opK&jLRb8N>obxM=%GklvgTV3zdK z)fU@-N}8$D1MULTq-XNk|6T%qERyo(6ycKXqp{^R9^_|8kLs_J^KwLP0VK6;XWhFK zZF>QSu{uGlWI-85HLfEdH EditorTexturePreviewPlugin::generate(const RES& p_from) { + + Ref tex =p_from; + Image img = tex->get_data(); + if (img.empty()) + return Ref(); + + img.clear_mipmaps(); + + int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size"); + if (img.is_compressed()) { + if (img.decompress()!=OK) + return Ref(); + } else if (img.get_format()!=Image::FORMAT_RGB && img.get_format()!=Image::FORMAT_RGB) { + img.convert(Image::FORMAT_RGBA); + } + + int width,height; + if (img.get_width() > thumbnail_size && img.get_width() >= img.get_height()) { + + width=thumbnail_size; + height = img.get_height() * thumbnail_size / img.get_width(); + } else if (img.get_height() > thumbnail_size && img.get_height() >= img.get_width()) { + + height=thumbnail_size; + width = img.get_width() * thumbnail_size / img.get_height(); + } else { + + width=img.get_width(); + height=img.get_height(); + } + + img.resize(width,height); + + Ref ptex = Ref( memnew( ImageTexture )); + + ptex->create_from_image(img,0); + return ptex; + +} + +EditorTexturePreviewPlugin::EditorTexturePreviewPlugin() { + + +} + +/////////////////////////////////////////////////////////////////////////// + + +Ref EditorPackedScenePreviewPlugin::_gen_from_imd(Ref p_imd) { + + if (p_imd.is_null()) + return Ref(); + + if (!p_imd->has_option("thumbnail")) + return Ref(); + + Variant tn = p_imd->get_option("thumbnail"); + print_line(Variant::get_type_name(tn.get_type())); + DVector thumbnail = tn; + + int len = thumbnail.size(); + if (len==0) + return Ref(); + + + DVector::Read r = thumbnail.read(); + + Image img(r.ptr(),len); + if (img.empty()) + return Ref(); + + Ref ptex = Ref( memnew( ImageTexture )); + ptex->create_from_image(img,0); + return ptex; + +} + +bool EditorPackedScenePreviewPlugin::handles(const String& p_type) const { + + return ObjectTypeDB::is_type(p_type,"PackedScene"); +} +Ref EditorPackedScenePreviewPlugin::generate(const RES& p_from) { + + Ref imd = p_from->get_import_metadata(); + return _gen_from_imd(imd); +} + +Ref EditorPackedScenePreviewPlugin::generate_from_path(const String& p_path) { + + Ref imd = ResourceLoader::load_import_metadata(p_path); + return _gen_from_imd(imd); +} + +EditorPackedScenePreviewPlugin::EditorPackedScenePreviewPlugin() { + +} + +////////////////////////////////////////////////////////////////// + +bool EditorMaterialPreviewPlugin::handles(const String& p_type) const { + + return ObjectTypeDB::is_type(p_type,"Material"); //any material +} + +Ref EditorMaterialPreviewPlugin::generate(const RES& p_from) { + + Ref material = p_from; + ERR_FAIL_COND_V(material.is_null(),Ref()); + + VS::get_singleton()->mesh_surface_set_material(sphere,0,material->get_rid()); + + VS::get_singleton()->viewport_queue_screen_capture(viewport); + VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_ONCE); //once used for capture +// print_line("queue capture!"); + Image img; + + int timeout=1000; + while(timeout) { + //print_line("try capture?"); + OS::get_singleton()->delay_usec(10); + img = VS::get_singleton()->viewport_get_screen_capture(viewport); + if (!img.empty()) + break; + timeout--; + } + + //print_line("captured!"); + VS::get_singleton()->mesh_surface_set_material(sphere,0,RID()); + + int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size"); + img.resize(thumbnail_size,thumbnail_size); + + Ref ptex = Ref( memnew( ImageTexture )); + ptex->create_from_image(img,0); + return ptex; +} + +EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() { + + scenario = VS::get_singleton()->scenario_create(); + + viewport = VS::get_singleton()->viewport_create(); + VS::get_singleton()->viewport_set_as_render_target(viewport,true); + VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_DISABLED); + VS::get_singleton()->viewport_set_scenario(viewport,scenario); + VS::ViewportRect vr; + vr.x=0; + vr.y=0; + vr.width=128; + vr.height=128; + VS::get_singleton()->viewport_set_rect(viewport,vr); + + camera = VS::get_singleton()->camera_create(); + VS::get_singleton()->viewport_attach_camera(viewport,camera); + VS::get_singleton()->camera_set_transform(camera,Transform(Matrix3(),Vector3(0,0,3))); + VS::get_singleton()->camera_set_perspective(camera,45,0.1,10); + + light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL); + light_instance = VS::get_singleton()->instance_create2(light,scenario); + VS::get_singleton()->instance_set_transform(light_instance,Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0))); + + light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL); + VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_DIFFUSE,Color(0.7,0.7,0.7)); + VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_SPECULAR,Color(0.0,0.0,0.0)); + light_instance2 = VS::get_singleton()->instance_create2(light2,scenario); + + VS::get_singleton()->instance_set_transform(light_instance2,Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1))); + + sphere = VS::get_singleton()->mesh_create(); + sphere_instance = VS::get_singleton()->instance_create2(sphere,scenario); + + int lats=32; + int lons=32; + float radius=1.0; + + DVector vertices; + DVector normals; + DVector uvs; + DVector tangents; + Matrix3 tt = Matrix3(Vector3(0,1,0),Math_PI*0.5); + + for(int i = 1; i <= lats; i++) { + double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats); + double z0 = Math::sin(lat0); + double zr0 = Math::cos(lat0); + + double lat1 = Math_PI * (-0.5 + (double) i / lats); + double z1 = Math::sin(lat1); + double zr1 = Math::cos(lat1); + + for(int j = lons; j >= 1; j--) { + + double lng0 = 2 * Math_PI * (double) (j - 1) / lons; + double x0 = Math::cos(lng0); + double y0 = Math::sin(lng0); + + double lng1 = 2 * Math_PI * (double) (j) / lons; + double x1 = Math::cos(lng1); + double y1 = Math::sin(lng1); + + + Vector3 v[4]={ + Vector3(x1 * zr0, z0, y1 *zr0), + Vector3(x1 * zr1, z1, y1 *zr1), + Vector3(x0 * zr1, z1, y0 *zr1), + Vector3(x0 * zr0, z0, y0 *zr0) + }; + +#define ADD_POINT(m_idx) \ + normals.push_back(v[m_idx]);\ + vertices.push_back(v[m_idx]*radius);\ + { Vector2 uv(Math::atan2(v[m_idx].x,v[m_idx].z),Math::atan2(-v[m_idx].y,v[m_idx].z));\ + uv/=Math_PI;\ + uv*=4.0;\ + uv=uv*0.5+Vector2(0.5,0.5);\ + uvs.push_back(uv);\ + }\ + { Vector3 t = tt.xform(v[m_idx]);\ + tangents.push_back(t.x);\ + tangents.push_back(t.y);\ + tangents.push_back(t.z);\ + tangents.push_back(1.0);\ + } + + + + ADD_POINT(0); + ADD_POINT(1); + ADD_POINT(2); + + ADD_POINT(2); + ADD_POINT(3); + ADD_POINT(0); + } + } + + Array arr; + arr.resize(VS::ARRAY_MAX); + arr[VS::ARRAY_VERTEX]=vertices; + arr[VS::ARRAY_NORMAL]=normals; + arr[VS::ARRAY_TANGENT]=tangents; + arr[VS::ARRAY_TEX_UV]=uvs; + VS::get_singleton()->mesh_add_surface(sphere,VS::PRIMITIVE_TRIANGLES,arr); + +} + +EditorMaterialPreviewPlugin::~EditorMaterialPreviewPlugin() { + + VS::get_singleton()->free(sphere); + VS::get_singleton()->free(sphere_instance); + VS::get_singleton()->free(viewport); + VS::get_singleton()->free(light); + VS::get_singleton()->free(light_instance); + VS::get_singleton()->free(light2); + VS::get_singleton()->free(light_instance2); + VS::get_singleton()->free(camera); + VS::get_singleton()->free(scenario); + +} + +/////////////////////////////////////////////////////////////////////////// + +static bool _is_text_char(CharType c) { + + return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_'; +} + +bool EditorScriptPreviewPlugin::handles(const String& p_type) const { + + return ObjectTypeDB::is_type(p_type,"Script"); +} + +Ref EditorScriptPreviewPlugin::generate(const RES& p_from) { + + + Ref