diff options
Diffstat (limited to 'scene')
28 files changed, 1329 insertions, 464 deletions
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index 57495b5cb0..1c0be60764 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -41,7 +41,6 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { bool solids=build_mode==BUILD_SOLIDS; - if (solids) { //here comes the sun, lalalala @@ -51,6 +50,8 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { Ref<ConvexPolygonShape2D> convex = memnew( ConvexPolygonShape2D ); convex->set_points(decomp[i]); co->add_shape(convex,get_transform()); + if (trigger) + co->set_shape_as_trigger(co->get_shape_count()-1,true); } @@ -71,6 +72,8 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { concave->set_segments(segments); co->add_shape(concave,get_transform()); + if (trigger) + co->set_shape_as_trigger(co->get_shape_count()-1,true); } @@ -166,6 +169,18 @@ Rect2 CollisionPolygon2D::get_item_rect() const { return aabb; } +void CollisionPolygon2D::set_trigger(bool p_trigger) { + + trigger=p_trigger; + _update_parent(); +} + +bool CollisionPolygon2D::is_trigger() const{ + + return trigger; +} + + void CollisionPolygon2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon2D::_add_to_collision_object); @@ -175,14 +190,19 @@ void CollisionPolygon2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon2D::set_build_mode); ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon2D::get_build_mode); + ObjectTypeDB::bind_method(_MD("set_trigger"),&CollisionPolygon2D::set_trigger); + ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionPolygon2D::is_trigger); + ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Segments"),_SCS("set_build_mode"),_SCS("get_build_mode")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger")); } CollisionPolygon2D::CollisionPolygon2D() { aabb=Rect2(-10,-10,20,20); build_mode=BUILD_SOLIDS; + trigger=false; } diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h index 09c2060088..b8e27b6fb4 100644 --- a/scene/2d/collision_polygon_2d.h +++ b/scene/2d/collision_polygon_2d.h @@ -50,6 +50,7 @@ protected: Rect2 aabb; BuildMode build_mode; Vector<Point2> polygon; + bool trigger; void _add_to_collision_object(Object *p_obj); void _update_parent(); @@ -60,6 +61,9 @@ protected: static void _bind_methods(); public: + void set_trigger(bool p_trigger); + bool is_trigger() const; + void set_build_mode(BuildMode p_mode); BuildMode get_build_mode() const; diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 655c6e8bf6..9d10000d2b 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -858,7 +858,8 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { //motion recover for(int i=0;i<get_shape_count();i++) { - + if (is_shape_set_as_trigger(i)) + continue; if (dss->collide_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),Vector2(),margin,sr,max_shapes,res_shapes,exclude,get_layer_mask(),mask)) collided=true; @@ -902,6 +903,8 @@ Vector2 KinematicBody2D::move(const Vector2& p_motion) { for(int i=0;i<get_shape_count();i++) { + if (is_shape_set_as_trigger(i)) + continue; float lsafe,lunsafe; bool valid = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, 0,lsafe,lunsafe,exclude,get_layer_mask(),mask); diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 21ecac6e3d..5c047b3fef 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -870,6 +870,9 @@ Vector3 KinematicBody::move(const Vector3& p_motion) { for(int j=0;j<8;j++) { for(int i=0;i<res_shapes;i++) { + if (is_shape_set_as_trigger(i)) + continue; + Vector3 a = sr[i*2+0]; Vector3 b = sr[i*2+1]; //print_line(String()+a+" -> "+b); @@ -930,6 +933,8 @@ Vector3 KinematicBody::move(const Vector3& p_motion) { for(int i=0;i<get_shape_count();i++) { + if (is_shape_set_as_trigger(i)) + continue; float lsafe,lunsafe; PhysicsDirectSpaceState::ShapeRestInfo lrest; @@ -1041,6 +1046,8 @@ bool KinematicBody::can_move_to(const Vector3& p_position, bool p_discrete) { //fill exclude list.. for(int i=0;i<get_shape_count();i++) { + if (is_shape_set_as_trigger(i)) + continue; bool col = dss->intersect_shape(get_shape(i)->get_rid(), xform * get_shape_transform(i),0,NULL,0,exclude,get_layer_mask(),mask); if (col) diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 011850138b..f9d36138a2 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -1178,6 +1178,19 @@ NodePath AnimationPlayer::get_root() const { return root; } +void AnimationPlayer::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const { + + String pf = p_function; + if (p_function=="play" || p_function=="remove_animation" || p_function=="has_animation" || p_function=="queue") { + List<StringName> al; + get_animation_list(&al); + for (List<StringName>::Element *E=al.front();E;E=E->next()) { + + r_options->push_back("\""+String(E->get())+"\""); + } + } + Node::get_argument_options(p_function,p_idx,r_options); +} void AnimationPlayer::_bind_methods() { diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 038c43d569..8ac5d96bf3 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -289,6 +289,9 @@ public: NodePath get_root() const; void clear_caches(); ///< must be called by hand if an animation was modified after added + + void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const; + AnimationPlayer(); ~AnimationPlayer(); diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 59793815f5..f668e52590 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -124,32 +124,34 @@ void Tween::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_tween_process_mode"),&Tween::get_tween_process_mode); ObjectTypeDB::bind_method(_MD("start"),&Tween::start ); - ObjectTypeDB::bind_method(_MD("reset","node","key"),&Tween::reset ); + ObjectTypeDB::bind_method(_MD("reset","object","key"),&Tween::reset ); ObjectTypeDB::bind_method(_MD("reset_all"),&Tween::reset_all ); - ObjectTypeDB::bind_method(_MD("stop","node","key"),&Tween::stop ); + ObjectTypeDB::bind_method(_MD("stop","object","key"),&Tween::stop ); ObjectTypeDB::bind_method(_MD("stop_all"),&Tween::stop_all ); - ObjectTypeDB::bind_method(_MD("resume","node","key"),&Tween::resume ); + ObjectTypeDB::bind_method(_MD("resume","object","key"),&Tween::resume ); ObjectTypeDB::bind_method(_MD("resume_all"),&Tween::resume_all ); - ObjectTypeDB::bind_method(_MD("remove","node","key"),&Tween::remove ); + ObjectTypeDB::bind_method(_MD("remove","object","key"),&Tween::remove ); ObjectTypeDB::bind_method(_MD("remove_all"),&Tween::remove_all ); ObjectTypeDB::bind_method(_MD("seek","time"),&Tween::seek ); ObjectTypeDB::bind_method(_MD("tell"),&Tween::tell ); ObjectTypeDB::bind_method(_MD("get_runtime"),&Tween::get_runtime ); - ObjectTypeDB::bind_method(_MD("interpolate_property","node","property","initial_val","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::interpolate_property, DEFVAL(0) ); - ObjectTypeDB::bind_method(_MD("interpolate_method","node","method","initial_val","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::interpolate_method, DEFVAL(0) ); - ObjectTypeDB::bind_method(_MD("interpolate_callback","node","callback","times_in_sec","args"),&Tween::interpolate_callback, DEFVAL(Variant()) ); - ObjectTypeDB::bind_method(_MD("follow_property","node","property","initial_val","target","target_property","times_in_sec","trans_type","ease_type","delay"),&Tween::follow_property, DEFVAL(0) ); - ObjectTypeDB::bind_method(_MD("follow_method","node","method","initial_val","target","target_method","times_in_sec","trans_type","ease_type","delay"),&Tween::follow_method, DEFVAL(0) ); - ObjectTypeDB::bind_method(_MD("targeting_property","node","property","initial","initial_val","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::targeting_property, DEFVAL(0) ); - ObjectTypeDB::bind_method(_MD("targeting_method","node","method","initial","initial_method","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::targeting_method, DEFVAL(0) ); + ObjectTypeDB::bind_method(_MD("interpolate_property","object","property","initial_val","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::interpolate_property, DEFVAL(0) ); + ObjectTypeDB::bind_method(_MD("interpolate_method","object","method","initial_val","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::interpolate_method, DEFVAL(0) ); + ObjectTypeDB::bind_method(_MD("interpolate_callback","object","times_in_sec","callback","args"),&Tween::interpolate_callback, DEFVAL(Variant()) ); + ObjectTypeDB::bind_method(_MD("follow_property","object","property","initial_val","target","target_property","times_in_sec","trans_type","ease_type","delay"),&Tween::follow_property, DEFVAL(0) ); + ObjectTypeDB::bind_method(_MD("follow_method","object","method","initial_val","target","target_method","times_in_sec","trans_type","ease_type","delay"),&Tween::follow_method, DEFVAL(0) ); + ObjectTypeDB::bind_method(_MD("targeting_property","object","property","initial","initial_val","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::targeting_property, DEFVAL(0) ); + ObjectTypeDB::bind_method(_MD("targeting_method","object","method","initial","initial_method","final_val","times_in_sec","trans_type","ease_type","delay"),&Tween::targeting_method, DEFVAL(0) ); - ADD_SIGNAL( MethodInfo("tween_start", PropertyInfo( Variant::OBJECT,"node"), PropertyInfo( Variant::STRING,"key")) ); - ADD_SIGNAL( MethodInfo("tween_step", PropertyInfo( Variant::OBJECT,"node"), PropertyInfo( Variant::STRING,"key"), PropertyInfo( Variant::REAL,"elapsed"), PropertyInfo( Variant::OBJECT,"value")) ); - ADD_SIGNAL( MethodInfo("tween_complete", PropertyInfo( Variant::OBJECT,"node"), PropertyInfo( Variant::STRING,"key")) ); + ADD_SIGNAL( MethodInfo("tween_start", PropertyInfo( Variant::OBJECT,"object"), PropertyInfo( Variant::STRING,"key")) ); + ADD_SIGNAL( MethodInfo("tween_step", PropertyInfo( Variant::OBJECT,"object"), PropertyInfo( Variant::STRING,"key"), PropertyInfo( Variant::REAL,"elapsed"), PropertyInfo( Variant::OBJECT,"value")) ); + ADD_SIGNAL( MethodInfo("tween_complete", PropertyInfo( Variant::OBJECT,"object"), PropertyInfo( Variant::STRING,"key")) ); ADD_PROPERTY( PropertyInfo( Variant::INT, "playback/process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_tween_process_mode"), _SCS("get_tween_process_mode")); - //ADD_PROPERTY( PropertyInfo( Variant::BOOL, "activate"), _SCS("set_active"), _SCS("is_active")); + + BIND_CONSTANT(TWEEN_PROCESS_FIXED); + BIND_CONSTANT(TWEEN_PROCESS_IDLE); BIND_CONSTANT(TRANS_LINEAR); BIND_CONSTANT(TRANS_SINE); @@ -181,19 +183,19 @@ Variant& Tween::_get_initial_val(InterpolateData& p_data) { case TARGETING_PROPERTY: case TARGETING_METHOD: { - Node *node = get_node(p_data.target); - ERR_FAIL_COND_V(node == NULL,p_data.initial_val); + Object *object = ObjectDB::get_instance(p_data.target_id); + ERR_FAIL_COND_V(object == NULL,p_data.initial_val); static Variant initial_val; if(p_data.type == TARGETING_PROPERTY) { bool valid = false; - initial_val = node->get(p_data.target_key, &valid); + initial_val = object->get(p_data.target_key, &valid); ERR_FAIL_COND_V(!valid,p_data.initial_val); } else { Variant::CallError error; - initial_val = node->call(p_data.target_key, NULL, 0, error); + initial_val = object->call(p_data.target_key, NULL, 0, error); ERR_FAIL_COND_V(error.error != Variant::CallError::CALL_OK,p_data.initial_val); } return initial_val; @@ -213,7 +215,7 @@ Variant& Tween::_get_delta_val(InterpolateData& p_data) { case FOLLOW_PROPERTY: case FOLLOW_METHOD: { - Node *target = get_node(p_data.target); + Object *target = ObjectDB::get_instance(p_data.target_id); ERR_FAIL_COND_V(target == NULL,p_data.initial_val); Variant final_val; @@ -264,6 +266,11 @@ Variant Tween::_run_equation(InterpolateData& p_data) { switch(initial_val.get_type()) { + + case Variant::BOOL: + result = ((int) _run_equation(p_data.trans_type, p_data.ease_type, p_data.elapsed - p_data.delay, (int) initial_val, (int) delta_val, p_data.times_in_sec)) >= 0.5; + break; + case Variant::INT: result = (int) _run_equation(p_data.trans_type, p_data.ease_type, p_data.elapsed - p_data.delay, (int) initial_val, (int) delta_val, p_data.times_in_sec); break; @@ -409,7 +416,7 @@ Variant Tween::_run_equation(InterpolateData& p_data) { bool Tween::_apply_tween_value(InterpolateData& p_data, Variant& value) { - Object *object = get_node(p_data.path); + Object *object = ObjectDB::get_instance(p_data.id); ERR_FAIL_COND_V(object == NULL, false); switch(p_data.type) { @@ -452,6 +459,7 @@ void Tween::_tween_process(float p_delta) { return; p_delta *= speed_scale; + pending_update ++; // if repeat and all interpolates was finished then reset all interpolates if(repeat) { bool all_finished = true; @@ -476,7 +484,7 @@ void Tween::_tween_process(float p_delta) { if(!data.active || data.finish) continue; - Object *object = get_node(data.path); + Object *object = ObjectDB::get_instance(data.id); if(object == NULL) continue; @@ -523,6 +531,7 @@ void Tween::_tween_process(float p_delta) { if(data.finish) emit_signal("tween_complete",object,data.key); } + pending_update --; } void Tween::set_tween_process_mode(TweenProcessMode p_mode) { @@ -598,16 +607,17 @@ bool Tween::start() { return true; } -bool Tween::reset(Node *p_node, String p_key) { +bool Tween::reset(Object *p_object, String p_key) { + pending_update ++; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); - Node *node = get_node(data.path); - if(node == NULL) + Object *object = ObjectDB::get_instance(data.id); + if(object == NULL) continue; - if(node == p_node && data.key == p_key) { + if(object == p_object && data.key == p_key) { data.elapsed = 0; data.finish = false; @@ -615,11 +625,13 @@ bool Tween::reset(Node *p_node, String p_key) { _apply_tween_value(data, data.initial_val); } } + pending_update --; return true; } bool Tween::reset_all() { + pending_update ++; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); @@ -628,20 +640,23 @@ bool Tween::reset_all() { if(data.delay == 0) _apply_tween_value(data, data.initial_val); } + pending_update --; return true; } -bool Tween::stop(Node *p_node, String p_key) { +bool Tween::stop(Object *p_object, String p_key) { + pending_update ++; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); - Node *node = get_node(data.path); - if(node == NULL) + Object *object = ObjectDB::get_instance(data.id); + if(object == NULL) continue; - if(node == p_node && data.key == p_key) + if(object == p_object && data.key == p_key) data.active = false; } + pending_update --; return true; } @@ -650,28 +665,32 @@ bool Tween::stop_all() { set_active(false); _set_process(false); + pending_update ++; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); data.active = false; } + pending_update --; return true; } -bool Tween::resume(Node *p_node, String p_key) { +bool Tween::resume(Object *p_object, String p_key) { set_active(true); _set_process(true); + pending_update ++; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); - Node *node = get_node(data.path); - if(node == NULL) + Object *object = ObjectDB::get_instance(data.id); + if(object == NULL) continue; - if(node == p_node && data.key == p_key) + if(object == p_object && data.key == p_key) data.active = true; } + pending_update --; return true; } @@ -680,23 +699,26 @@ bool Tween::resume_all() { set_active(true); _set_process(true); + pending_update ++; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); data.active = true; } + pending_update --; return true; } -bool Tween::remove(Node *p_node, String p_key) { +bool Tween::remove(Object *p_object, String p_key) { + ERR_FAIL_COND_V(pending_update != 0, false); for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); - Node *node = get_node(data.path); - if(node == NULL) + Object *object = ObjectDB::get_instance(data.id); + if(object == NULL) continue; - if(node == p_node && data.key == p_key) { + if(object == p_object && data.key == p_key) { interpolates.erase(E); return true; } @@ -706,6 +728,7 @@ bool Tween::remove(Node *p_node, String p_key) { bool Tween::remove_all() { + ERR_FAIL_COND_V(pending_update != 0, false); set_active(false); _set_process(false); interpolates.clear(); @@ -714,6 +737,7 @@ bool Tween::remove_all() { bool Tween::seek(real_t p_time) { + pending_update ++; for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); @@ -744,11 +768,13 @@ bool Tween::seek(real_t p_time) { _apply_tween_value(data, result); } + pending_update --; return true; } real_t Tween::tell() const { + pending_update ++; real_t pos = 0; for(const List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { @@ -756,11 +782,13 @@ real_t Tween::tell() const { if(data.elapsed > pos) pos = data.elapsed; } + pending_update --; return pos; } real_t Tween::get_runtime() const { + pending_update ++; real_t runtime = 0; for(const List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { @@ -769,6 +797,7 @@ real_t Tween::get_runtime() const { if(t > runtime) runtime = t; } + pending_update --; return runtime; } @@ -779,6 +808,12 @@ bool Tween::_calc_delta_val(const Variant& p_initial_val, const Variant& p_final Variant& delta_val = p_delta_val; switch(initial_val.get_type()) { + + case Variant::BOOL: + //delta_val = p_final_val; + delta_val = (int) p_final_val - (int) p_initial_val; + break; + case Variant::INT: delta_val = (int) final_val - (int) initial_val; break; @@ -873,7 +908,7 @@ bool Tween::_calc_delta_val(const Variant& p_initial_val, const Variant& p_final return true; } -bool Tween::interpolate_property(Node *p_node +bool Tween::interpolate_property(Object *p_object , String p_property , Variant p_initial_val , Variant p_final_val @@ -882,11 +917,12 @@ bool Tween::interpolate_property(Node *p_node , EaseType p_ease_type , real_t p_delay ) { + ERR_FAIL_COND_V(pending_update != 0, false); // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); - ERR_FAIL_COND_V(p_node == NULL, false); + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_initial_val.get_type() != p_final_val.get_type(), false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); @@ -894,7 +930,7 @@ bool Tween::interpolate_property(Node *p_node ERR_FAIL_COND_V(p_delay < 0, false); bool prop_valid = false; - p_node->get(p_property,&prop_valid); + p_object->get(p_property,&prop_valid); ERR_FAIL_COND_V(!prop_valid, false); InterpolateData data; @@ -903,7 +939,7 @@ bool Tween::interpolate_property(Node *p_node data.finish = false; data.elapsed = 0; - data.path = p_node->get_path(); + data.id = p_object->get_instance_ID(); data.key = p_property; data.initial_val = p_initial_val; data.final_val = p_final_val; @@ -919,7 +955,7 @@ bool Tween::interpolate_property(Node *p_node return true; } -bool Tween::interpolate_method(Node *p_node +bool Tween::interpolate_method(Object *p_object , String p_method , Variant p_initial_val , Variant p_final_val @@ -928,18 +964,19 @@ bool Tween::interpolate_method(Node *p_node , EaseType p_ease_type , real_t p_delay ) { + ERR_FAIL_COND_V(pending_update != 0, false); // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); - ERR_FAIL_COND_V(p_node == NULL, false); + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_initial_val.get_type() != p_final_val.get_type(), false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false); ERR_FAIL_COND_V(p_delay < 0, false); - ERR_FAIL_COND_V(!p_node->has_method(p_method), false); + ERR_FAIL_COND_V(!p_object->has_method(p_method), false); InterpolateData data; data.active = true; @@ -947,7 +984,7 @@ bool Tween::interpolate_method(Node *p_node data.finish = false; data.elapsed = 0; - data.path = p_node->get_path(); + data.id = p_object->get_instance_ID(); data.key = p_method; data.initial_val = p_initial_val; data.final_val = p_final_val; @@ -963,16 +1000,17 @@ bool Tween::interpolate_method(Node *p_node return true; } -bool Tween::interpolate_callback(Node *p_node - , String p_callback +bool Tween::interpolate_callback(Object *p_object , real_t p_times_in_sec + , String p_callback , Variant p_arg ) { - ERR_FAIL_COND_V(p_node == NULL, false); + ERR_FAIL_COND_V(pending_update != 0, false); + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_times_in_sec < 0, false); - ERR_FAIL_COND_V(!p_node->has_method(p_callback), false); + ERR_FAIL_COND_V(!p_object->has_method(p_callback), false); InterpolateData data; data.active = true; @@ -980,30 +1018,33 @@ bool Tween::interpolate_callback(Node *p_node data.finish = false; data.elapsed = 0; - data.path = p_node->get_path(); + data.id = p_object->get_instance_ID(); data.key = p_callback; data.times_in_sec = p_times_in_sec; data.delay = 0; data.arg = p_arg; + pending_update ++; interpolates.push_back(data); + pending_update --; return true; } -bool Tween::follow_property(Node *p_node +bool Tween::follow_property(Object *p_object , String p_property , Variant p_initial_val - , Node *p_target + , Object *p_target , String p_target_property , real_t p_times_in_sec , TransitionType p_trans_type , EaseType p_ease_type , real_t p_delay ) { + ERR_FAIL_COND_V(pending_update != 0, false); // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); - ERR_FAIL_COND_V(p_node == NULL, false); + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_target == NULL, false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); @@ -1011,7 +1052,7 @@ bool Tween::follow_property(Node *p_node ERR_FAIL_COND_V(p_delay < 0, false); bool prop_valid = false; - p_node->get(p_property,&prop_valid); + p_object->get(p_property,&prop_valid); ERR_FAIL_COND_V(!prop_valid, false); bool target_prop_valid = false; @@ -1028,10 +1069,10 @@ bool Tween::follow_property(Node *p_node data.finish = false; data.elapsed = 0; - data.path = p_node->get_path(); + data.id = p_object->get_instance_ID(); data.key = p_property; data.initial_val = p_initial_val; - data.target = p_target->get_path(); + data.target_id = p_target->get_instance_ID(); data.target_key = p_target_property; data.times_in_sec = p_times_in_sec; data.trans_type = p_trans_type; @@ -1042,27 +1083,28 @@ bool Tween::follow_property(Node *p_node return true; } -bool Tween::follow_method(Node *p_node +bool Tween::follow_method(Object *p_object , String p_method , Variant p_initial_val - , Node *p_target + , Object *p_target , String p_target_method , real_t p_times_in_sec , TransitionType p_trans_type , EaseType p_ease_type , real_t p_delay ) { + ERR_FAIL_COND_V(pending_update != 0, false); // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); - ERR_FAIL_COND_V(p_node == NULL, false); + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_target == NULL, false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false); ERR_FAIL_COND_V(p_delay < 0, false); - ERR_FAIL_COND_V(!p_node->has_method(p_method), false); + ERR_FAIL_COND_V(!p_object->has_method(p_method), false); ERR_FAIL_COND_V(!p_target->has_method(p_target_method), false); Variant::CallError error; @@ -1079,10 +1121,10 @@ bool Tween::follow_method(Node *p_node data.finish = false; data.elapsed = 0; - data.path = p_node->get_path(); + data.id = p_object->get_instance_ID(); data.key = p_method; data.initial_val = p_initial_val; - data.target = p_target->get_path(); + data.target_id = p_target->get_instance_ID(); data.target_key = p_target_method; data.times_in_sec = p_times_in_sec; data.trans_type = p_trans_type; @@ -1093,9 +1135,9 @@ bool Tween::follow_method(Node *p_node return true; } -bool Tween::targeting_property(Node *p_node +bool Tween::targeting_property(Object *p_object , String p_property - , Node *p_initial + , Object *p_initial , String p_initial_property , Variant p_final_val , real_t p_times_in_sec @@ -1103,10 +1145,11 @@ bool Tween::targeting_property(Node *p_node , EaseType p_ease_type , real_t p_delay ) { + ERR_FAIL_COND_V(pending_update != 0, false); // convert INT to REAL is better for interpolaters if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); - ERR_FAIL_COND_V(p_node == NULL, false); + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_initial == NULL, false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); @@ -1114,7 +1157,7 @@ bool Tween::targeting_property(Node *p_node ERR_FAIL_COND_V(p_delay < 0, false); bool prop_valid = false; - p_node->get(p_property,&prop_valid); + p_object->get(p_property,&prop_valid); ERR_FAIL_COND_V(!prop_valid, false); bool initial_prop_valid = false; @@ -1131,9 +1174,9 @@ bool Tween::targeting_property(Node *p_node data.finish = false; data.elapsed = 0; - data.path = p_node->get_path(); + data.id = p_object->get_instance_ID(); data.key = p_property; - data.target = p_initial->get_path(); + data.target_id = p_initial->get_instance_ID(); data.target_key = p_initial_property; data.initial_val = initial_val; data.final_val = p_final_val; @@ -1150,9 +1193,9 @@ bool Tween::targeting_property(Node *p_node } -bool Tween::targeting_method(Node *p_node +bool Tween::targeting_method(Object *p_object , String p_method - , Node *p_initial + , Object *p_initial , String p_initial_method , Variant p_final_val , real_t p_times_in_sec @@ -1160,17 +1203,18 @@ bool Tween::targeting_method(Node *p_node , EaseType p_ease_type , real_t p_delay ) { + ERR_FAIL_COND_V(pending_update != 0, false); // convert INT to REAL is better for interpolaters if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); - ERR_FAIL_COND_V(p_node == NULL, false); + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_initial == NULL, false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false); ERR_FAIL_COND_V(p_delay < 0, false); - ERR_FAIL_COND_V(!p_node->has_method(p_method), false); + ERR_FAIL_COND_V(!p_object->has_method(p_method), false); ERR_FAIL_COND_V(!p_initial->has_method(p_initial_method), false); Variant::CallError error; @@ -1187,9 +1231,9 @@ bool Tween::targeting_method(Node *p_node data.finish = false; data.elapsed = 0; - data.path = p_node->get_path(); + data.id = p_object->get_instance_ID(); data.key = p_method; - data.target = p_initial->get_path(); + data.target_id = p_initial->get_instance_ID(); data.target_key = p_initial_method; data.initial_val = initial_val; data.final_val = p_final_val; @@ -1213,6 +1257,7 @@ Tween::Tween() { active=false; repeat=false; speed_scale=1; + pending_update=0; } Tween::~Tween() { diff --git a/scene/animation/tween.h b/scene/animation/tween.h index c9d9863397..3e23cc362a 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -54,15 +54,17 @@ public: TRANS_CIRC, TRANS_BOUNCE, TRANS_BACK, - TRANS_COUNT, + + TRANS_COUNT, }; enum EaseType { EASE_IN, EASE_OUT, EASE_IN_OUT, - EASE_OUT_IN, - EASE_COUNT, + EASE_OUT_IN, + + EASE_COUNT, }; private: @@ -82,12 +84,12 @@ private: InterpolateType type; bool finish; real_t elapsed; - NodePath path; + ObjectID id; StringName key; Variant initial_val; Variant delta_val; Variant final_val; - NodePath target; + ObjectID target_id; StringName target_key; real_t times_in_sec; TransitionType trans_type; @@ -102,6 +104,7 @@ private: bool active; bool repeat; float speed_scale; + mutable int pending_update; List<InterpolateData> interpolates; @@ -142,20 +145,20 @@ public: float get_speed() const; bool start(); - bool reset(Node *p_node, String p_key); + bool reset(Object *p_node, String p_key); bool reset_all(); - bool stop(Node *p_node, String p_key); + bool stop(Object *p_node, String p_key); bool stop_all(); - bool resume(Node *p_node, String p_key); + bool resume(Object *p_node, String p_key); bool resume_all(); - bool remove(Node *p_node, String p_key); + bool remove(Object *p_node, String p_key); bool remove_all(); bool seek(real_t p_time); real_t tell() const; real_t get_runtime() const; - bool interpolate_property(Node *p_node + bool interpolate_property(Object *p_node , String p_property , Variant p_initial_val , Variant p_final_val @@ -165,7 +168,7 @@ public: , real_t p_delay = 0 ); - bool interpolate_method(Node *p_node + bool interpolate_method(Object *p_node , String p_method , Variant p_initial_val , Variant p_final_val @@ -175,16 +178,16 @@ public: , real_t p_delay = 0 ); - bool interpolate_callback(Node *p_node - , String p_callback + bool interpolate_callback(Object *p_node , real_t p_times_in_sec + , String p_callback , Variant p_arg = Variant() ); - bool follow_property(Node *p_node + bool follow_property(Object *p_node , String p_property , Variant p_initial_val - , Node *p_target + , Object *p_target , String p_target_property , real_t p_times_in_sec , TransitionType p_trans_type @@ -192,10 +195,10 @@ public: , real_t p_delay = 0 ); - bool follow_method(Node *p_node + bool follow_method(Object *p_node , String p_method , Variant p_initial_val - , Node *p_target + , Object *p_target , String p_target_method , real_t p_times_in_sec , TransitionType p_trans_type @@ -203,9 +206,9 @@ public: , real_t p_delay = 0 ); - bool targeting_property(Node *p_node + bool targeting_property(Object *p_node , String p_property - , Node *p_initial + , Object *p_initial , String p_initial_property , Variant p_final_val , real_t p_times_in_sec @@ -214,9 +217,9 @@ public: , real_t p_delay = 0 ); - bool targeting_method(Node *p_node + bool targeting_method(Object *p_node , String p_method - , Node *p_initial + , Object *p_initial , String p_initial_method , Variant p_final_val , real_t p_times_in_sec diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index 216c6d7122..5ed60e88f8 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -44,7 +44,7 @@ void BoxContainer::_resort() { Size2i new_size=get_size();; - int sep=get_constant("separation",vertical?"VBoxContainer":"HBoxContainer"); + int sep=get_constant("separation");//,vertical?"VBoxContainer":"HBoxContainer"); bool first=true; int children_count=0; @@ -202,7 +202,7 @@ Size2 BoxContainer::get_minimum_size() const { /* Calculate MINIMUM SIZE */ Size2i minimum; - int sep=get_constant("separation",vertical?"VBoxContainer":"HBoxContainer"); + int sep=get_constant("separation");//,vertical?"VBoxContainer":"HBoxContainer"); bool first=true; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index aea0aacf42..5a0706f01e 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -1325,9 +1325,12 @@ Size2 Control::get_minimum_size() const { Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type) const { - const Ref<Texture>* tex = data.icon_override.getptr(p_name); - if (tex) - return *tex; + if (p_type==StringName()) { + + const Ref<Texture>* tex = data.icon_override.getptr(p_name); + if (tex) + return *tex; + } StringName type = p_type?p_type:get_type_name(); @@ -1353,12 +1356,11 @@ Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p_type) const { - - const Ref<StyleBox>* style = data.style_override.getptr(p_name); - - - if (style) - return *style; + if (p_type==StringName()) { + const Ref<StyleBox>* style = data.style_override.getptr(p_name); + if (style) + return *style; + } StringName type = p_type?p_type:get_type_name(); @@ -1381,10 +1383,12 @@ Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p } Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) const { - - const Ref<Font>* font = data.font_override.getptr(p_name); - if (font) - return *font; + + if (p_type==StringName()) { + const Ref<Font>* font = data.font_override.getptr(p_name); + if (font) + return *font; + } StringName type = p_type?p_type:get_type_name(); @@ -1410,10 +1414,12 @@ Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) c } Color Control::get_color(const StringName& p_name,const StringName& p_type) const { - - const Color* color = data.color_override.getptr(p_name); - if (color) - return *color; + + if (p_type==StringName()) { + const Color* color = data.color_override.getptr(p_name); + if (color) + return *color; + } StringName type = p_type?p_type:get_type_name(); // try with custom themes @@ -1437,10 +1443,12 @@ Color Control::get_color(const StringName& p_name,const StringName& p_type) cons } int Control::get_constant(const StringName& p_name,const StringName& p_type) const { - - const int* constant = data.constant_override.getptr(p_name); - if (constant) - return *constant; + + if (p_type==StringName()) { + const int* constant = data.constant_override.getptr(p_name); + if (constant) + return *constant; + } StringName type = p_type?p_type:get_type_name(); // try with custom themes @@ -1467,9 +1475,11 @@ int Control::get_constant(const StringName& p_name,const StringName& p_type) con bool Control::has_icon(const StringName& p_name,const StringName& p_type) const { - const Ref<Texture>* tex = data.icon_override.getptr(p_name); - if (tex) - return true; + if (p_type==StringName()) { + const Ref<Texture>* tex = data.icon_override.getptr(p_name); + if (tex) + return true; + } StringName type = p_type?p_type:get_type_name(); @@ -1494,11 +1504,12 @@ bool Control::has_icon(const StringName& p_name,const StringName& p_type) const } bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) const { - - const Ref<StyleBox>* style = data.style_override.getptr(p_name); - - if (style) - return true; + if (p_type==StringName()) { + const Ref<StyleBox>* style = data.style_override.getptr(p_name); + + if (style) + return true; + } StringName type = p_type?p_type:get_type_name(); @@ -1523,9 +1534,11 @@ bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) co } bool Control::has_font(const StringName& p_name,const StringName& p_type) const { - const Ref<Font>* font = data.font_override.getptr(p_name); - if (font) - return true; + if (p_type==StringName()) { + const Ref<Font>* font = data.font_override.getptr(p_name); + if (font) + return true; + } StringName type = p_type?p_type:get_type_name(); @@ -1551,9 +1564,11 @@ bool Control::has_font(const StringName& p_name,const StringName& p_type) const } bool Control::has_color(const StringName& p_name,const StringName& p_type) const { - const Color* color = data.color_override.getptr(p_name); - if (color) - return true; + if (p_type==StringName()) { + const Color* color = data.color_override.getptr(p_name); + if (color) + return true; + } StringName type = p_type?p_type:get_type_name(); @@ -1578,10 +1593,13 @@ bool Control::has_color(const StringName& p_name,const StringName& p_type) const } bool Control::has_constant(const StringName& p_name,const StringName& p_type) const { - - const int* constant = data.constant_override.getptr(p_name); - if (constant) - return true; + + if (p_type==StringName()) { + + const int* constant = data.constant_override.getptr(p_name); + if (constant) + return true; + } StringName type = p_type?p_type:get_type_name(); diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp new file mode 100644 index 0000000000..6e3afeefd0 --- /dev/null +++ b/scene/gui/graph_node.cpp @@ -0,0 +1,320 @@ +#include "graph_node.h" + + +bool GraphNode::_set(const StringName& p_name, const Variant& p_value) { + + if (!p_name.operator String().begins_with("slot/")) + return false; + + int idx=p_name.operator String().get_slice("/",1).to_int(); + String what = p_name.operator String().get_slice("/",2); + + + Slot si; + if (slot_info.has(idx)) + si=slot_info[idx]; + + + if (what=="left_enabled") + si.enable_left=p_value; + else if (what=="left_type") + si.type_left=p_value; + else if (what=="left_color") + si.color_left=p_value; + else if (what=="right_enabled") + si.enable_right=p_value; + else if (what=="right_type") + si.type_right=p_value; + else if (what=="right_color") + si.color_right=p_value; + else + return false; + + set_slot(idx,si.enable_left,si.type_left,si.color_left,si.enable_right,si.type_right,si.color_right); + update(); + return true; +} + +bool GraphNode::_get(const StringName& p_name,Variant &r_ret) const{ + + + print_line("get "+p_name.operator String()); + if (!p_name.operator String().begins_with("slot/")) { + print_line("no begins"); + return false; + } + + int idx=p_name.operator String().get_slice("/",1).to_int(); + String what = p_name.operator String().get_slice("/",2); + + + + Slot si; + if (slot_info.has(idx)) + si=slot_info[idx]; + + if (what=="left_enabled") + r_ret=si.enable_left; + else if (what=="left_type") + r_ret=si.type_left; + else if (what=="left_color") + r_ret=si.color_left; + else if (what=="right_enabled") + r_ret=si.enable_right; + else if (what=="right_type") + r_ret=si.type_right; + else if (what=="right_color") + r_ret=si.color_right; + else + return false; + + print_line("ask for: "+p_name.operator String()+" get: "+String(r_ret)); + return true; +} +void GraphNode::_get_property_list( List<PropertyInfo> *p_list) const{ + + int idx=0; + for(int i=0;i<get_child_count();i++) { + Control *c=get_child(i)->cast_to<Control>(); + if (!c || c->is_set_as_toplevel() || !c->get_owner()) + continue; + + String base="slot/"+itos(idx)+"/"; + + p_list->push_back(PropertyInfo(Variant::BOOL,base+"left_enabled")); + p_list->push_back(PropertyInfo(Variant::INT,base+"left_type")); + p_list->push_back(PropertyInfo(Variant::COLOR,base+"left_color")); + p_list->push_back(PropertyInfo(Variant::BOOL,base+"right_enabled")); + p_list->push_back(PropertyInfo(Variant::INT,base+"right_type")); + p_list->push_back(PropertyInfo(Variant::COLOR,base+"right_color")); + + idx++; + } +} + + +void GraphNode::_resort() { + + + + int sep=get_constant("separation"); + Ref<StyleBox> sb=get_stylebox("frame"); + bool first=true; + + Size2 minsize; + + for(int i=0;i<get_child_count();i++) { + Control *c=get_child(i)->cast_to<Control>(); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; + + Size2i size=c->get_combined_minimum_size(); + + minsize.y+=size.y; + minsize.x=MAX(minsize.x,size.x); + + if (first) + first=false; + else + minsize.y+=sep; + + } + + int vofs=0; + int w = get_size().x - sb->get_minimum_size().x; + + + cache_y.clear(); + for(int i=0;i<get_child_count();i++) { + Control *c=get_child(i)->cast_to<Control>(); + if (!c) + continue; + if (c->is_set_as_toplevel() || !c->get_owner()) + continue; + + Size2i size=c->get_combined_minimum_size(); + + Rect2 r(sb->get_margin(MARGIN_LEFT),sb->get_margin(MARGIN_TOP)+vofs,w,size.y); + + fit_child_in_rect(c,r); + cache_y.push_back(vofs+size.y*0.5); + + if (vofs>0) + vofs+=sep; + vofs+=size.y; + + + } + + _change_notify(); + update(); + +} + + +void GraphNode::_notification(int p_what) { + + if (p_what==NOTIFICATION_DRAW) { + + Ref<StyleBox> sb=get_stylebox("frame"); + Ref<Texture> port =get_icon("port"); + Point2i icofs = -port->get_size()*0.5; + int edgeofs=3; + icofs.y+=sb->get_margin(MARGIN_TOP); + draw_style_box(sb,Rect2(Point2(),get_size())); + + for (Map<int,Slot>::Element *E=slot_info.front();E;E=E->next()) { + + if (E->key()>cache_y.size()) + continue; + if (!slot_info.has(E->key())) + continue; + const Slot &s=slot_info[E->key()]; + //left + if (s.enable_left) + port->draw(get_canvas_item(),icofs+Point2(edgeofs,cache_y[E->key()]),s.color_left); + if (s.enable_right) + port->draw(get_canvas_item(),icofs+Point2(get_size().x-edgeofs,cache_y[E->key()]),s.color_right); + + } + } + if (p_what==NOTIFICATION_SORT_CHILDREN) { + + _resort(); + } + +} + +void GraphNode::set_title(const String& p_title) { + + title=p_title; + update(); +} + +String GraphNode::get_title() const { + + return title; +} + +void GraphNode::set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right) { + + ERR_FAIL_COND(p_idx<0); + + if (!p_enable_left && p_type_left==0 && p_color_left==Color(1,1,1,1) && !p_enable_right && p_type_right==0 && p_color_right==Color(1,1,1,1)) { + slot_info.erase(p_idx); + return; + } + + Slot s; + s.enable_left=p_enable_left; + s.type_left=p_type_left; + s.color_left=p_color_left; + s.enable_right=p_enable_right; + s.type_right=p_type_right; + s.color_right=p_color_right; + slot_info[p_idx]=s; + update(); +} + +void GraphNode::clear_slot(int p_idx){ + + slot_info.erase(p_idx); + update(); +} +void GraphNode::clear_all_slots(){ + + slot_info.clear(); + update(); +} +bool GraphNode::is_slot_enabled_left(int p_idx) const{ + + if (!slot_info.has(p_idx)) + return false; + return slot_info[p_idx].enable_left; + +} + +int GraphNode::get_slot_type_left(int p_idx) const{ + + if (!slot_info.has(p_idx)) + return 0; + return slot_info[p_idx].type_left; + +} + +Color GraphNode::get_slot_color_left(int p_idx) const{ + + if (!slot_info.has(p_idx)) + return Color(1,1,1,1); + return slot_info[p_idx].color_left; + +} + +bool GraphNode::is_slot_enabled_right(int p_idx) const{ + + if (!slot_info.has(p_idx)) + return false; + return slot_info[p_idx].enable_right; + +} + + + +int GraphNode::get_slot_type_right(int p_idx) const{ + + if (!slot_info.has(p_idx)) + return 0; + return slot_info[p_idx].type_right; + +} + +Color GraphNode::get_slot_color_right(int p_idx) const{ + + if (!slot_info.has(p_idx)) + return Color(1,1,1,1); + return slot_info[p_idx].color_right; + +} + +Size2 GraphNode::get_minimum_size() const { + + int sep=get_constant("separation"); + Ref<StyleBox> sb=get_stylebox("frame"); + bool first=true; + + Size2 minsize; + + for(int i=0;i<get_child_count();i++) { + + Control *c=get_child(i)->cast_to<Control>(); + if (!c) + continue; + if (c->is_set_as_toplevel() || !c->get_owner()) + continue; + + Size2i size=c->get_combined_minimum_size(); + + minsize.y+=size.y; + minsize.x=MAX(minsize.x,size.x); + + if (first) + first=false; + else + minsize.y+=sep; + } + + return minsize+sb->get_minimum_size(); +} + + +void GraphNode::_bind_methods() { + + +} + +GraphNode::GraphNode() { + + +} diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h new file mode 100644 index 0000000000..3b89da9f0f --- /dev/null +++ b/scene/gui/graph_node.h @@ -0,0 +1,61 @@ +#ifndef GRAPH_NODE_H +#define GRAPH_NODE_H + +#include "scene/gui/container.h" + +class GraphNode : public Container { + + OBJ_TYPE(GraphNode,Container); + + + String title; + struct Slot { + bool enable_left; + int type_left; + Color color_left; + bool enable_right; + int type_right; + Color color_right; + + + Slot() { enable_left=false; type_left=0; color_left=Color(1,1,1,1); enable_right=false; type_right=0; color_right=Color(1,1,1,1); }; + }; + + Vector<int> cache_y; + + Map<int,Slot> slot_info; + + void _resort(); +protected: + + void _notification(int p_what); + static void _bind_methods(); + + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List<PropertyInfo> *p_list) const; + +public: + + + + void set_title(const String& p_title); + String get_title() const; + + void set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right); + void clear_slot(int p_idx); + void clear_all_slots(); + bool is_slot_enabled_left(int p_idx) const; + int get_slot_type_left(int p_idx) const; + Color get_slot_color_left(int p_idx) const; + bool is_slot_enabled_right(int p_idx) const; + int get_slot_type_right(int p_idx) const; + Color get_slot_color_right(int p_idx) const; + + virtual Size2 get_minimum_size() const; + + GraphNode(); +}; + + +#endif // GRAPH_NODE_H diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index ba68948e6b..3f2f95bbd9 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -359,385 +359,591 @@ void TextEdit::_update_scrollbars() { void TextEdit::_notification(int p_what) { - switch(p_what) { - case NOTIFICATION_ENTER_TREE: { + switch(p_what) { + case NOTIFICATION_ENTER_TREE: { - _update_caches(); - if (cursor_changed_dirty) - MessageQueue::get_singleton()->push_call(this,"_cursor_changed_emit"); - if (text_changed_dirty) - MessageQueue::get_singleton()->push_call(this,"_text_changed_emit"); + _update_caches(); + if (cursor_changed_dirty) + MessageQueue::get_singleton()->push_call(this,"_cursor_changed_emit"); + if (text_changed_dirty) + MessageQueue::get_singleton()->push_call(this,"_text_changed_emit"); - } break; - case NOTIFICATION_RESIZED: { + } break; + case NOTIFICATION_RESIZED: { - cache.size=get_size(); - adjust_viewport_to_cursor(); + cache.size=get_size(); + adjust_viewport_to_cursor(); - } break; - case NOTIFICATION_THEME_CHANGED: { + } break; + case NOTIFICATION_THEME_CHANGED: { - _update_caches(); - }; - case NOTIFICATION_DRAW: { + _update_caches(); + }; + case NOTIFICATION_DRAW: { - int line_number_char_count=0; + int line_number_char_count=0; - { - int lc=text.size()+1; - cache.line_number_w=0; - while(lc) { - cache.line_number_w+=1; - lc/=10; - }; + { + int lc=text.size()+1; + cache.line_number_w=0; + while(lc) { + cache.line_number_w+=1; + lc/=10; + }; - if (line_numbers) { + if (line_numbers) { - line_number_char_count=cache.line_number_w; - cache.line_number_w=(cache.line_number_w+1)*cache.font->get_char_size('0').width; - } else { - cache.line_number_w=0; - } + line_number_char_count=cache.line_number_w; + cache.line_number_w=(cache.line_number_w+1)*cache.font->get_char_size('0').width; + } else { + cache.line_number_w=0; + } - } - _update_scrollbars(); + } + _update_scrollbars(); - RID ci = get_canvas_item(); - int xmargin_beg=cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w; - int xmargin_end=cache.size.width-cache.style_normal->get_margin(MARGIN_RIGHT); - //let's do it easy for now: - cache.style_normal->draw(ci,Rect2(Point2(),cache.size)); - if (has_focus()) - cache.style_focus->draw(ci,Rect2(Point2(),cache.size)); + RID ci = get_canvas_item(); + int xmargin_beg=cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w; + int xmargin_end=cache.size.width-cache.style_normal->get_margin(MARGIN_RIGHT); + //let's do it easy for now: + cache.style_normal->draw(ci,Rect2(Point2(),cache.size)); + if (has_focus()) + cache.style_focus->draw(ci,Rect2(Point2(),cache.size)); - int ascent=cache.font->get_ascent(); + int ascent=cache.font->get_ascent(); - int visible_rows = get_visible_rows(); + int visible_rows = get_visible_rows(); - int tab_w = cache.font->get_char_size(' ').width*tab_size; + int tab_w = cache.font->get_char_size(' ').width*tab_size; - Color color = cache.font_color; - int in_region=-1; + Color color = cache.font_color; + int in_region=-1; - if (syntax_coloring) { + if (syntax_coloring) { - if (custom_bg_color.a>0.01) { + if (custom_bg_color.a>0.01) { - Point2i ofs = Point2i(cache.style_normal->get_offset())/2.0; - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(ofs, get_size()-cache.style_normal->get_minimum_size()+ofs),custom_bg_color); - } - //compute actual region to start (may be inside say, a comment). - //slow in very large documments :( but ok for source! + Point2i ofs = Point2i(cache.style_normal->get_offset())/2.0; + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(ofs, get_size()-cache.style_normal->get_minimum_size()+ofs),custom_bg_color); + } + //compute actual region to start (may be inside say, a comment). + //slow in very large documments :( but ok for source! - for(int i=0;i<cursor.line_ofs;i++) { + for(int i=0;i<cursor.line_ofs;i++) { - const Map<int,Text::ColorRegionInfo>& cri_map=text.get_color_region_info(i); + const Map<int,Text::ColorRegionInfo>& cri_map=text.get_color_region_info(i); - if (in_region>=0 && color_regions[in_region].line_only) { - in_region=-1; //reset regions that end at end of line - } + if (in_region>=0 && color_regions[in_region].line_only) { + in_region=-1; //reset regions that end at end of line + } - for( const Map<int,Text::ColorRegionInfo>::Element* E= cri_map.front();E;E=E->next() ) { + for( const Map<int,Text::ColorRegionInfo>::Element* E= cri_map.front();E;E=E->next() ) { - const Text::ColorRegionInfo &cri=E->get(); + const Text::ColorRegionInfo &cri=E->get(); - if (in_region==-1) { + if (in_region==-1) { - if (!cri.end) { + if (!cri.end) { - in_region=cri.region; - } - } else if (in_region==cri.region && !color_regions[cri.region].line_only) { //ignore otherwise + in_region=cri.region; + } + } else if (in_region==cri.region && !color_regions[cri.region].line_only) { //ignore otherwise - if (cri.end || color_regions[cri.region].eq) { + if (cri.end || color_regions[cri.region].eq) { - in_region=-1; - } - } - } - } - } + in_region=-1; + } + } + } + } + } - int deregion=0; //force it to clear inrgion - Point2 cursor_pos; + int brace_open_match_line=-1; + int brace_open_match_column=-1; + bool brace_open_matching=false; + bool brace_open_mismatch=false; + int brace_close_match_line=-1; + int brace_close_match_column=-1; + bool brace_close_matching=false; + bool brace_close_mismatch=false; - for (int i=0;i<visible_rows;i++) { - int line=i+cursor.line_ofs; + if (brace_matching_enabled) { - if (line<0 || line>=(int)text.size()) - continue; + if (cursor.column<text[cursor.line].length()) { + //check for open + CharType c = text[cursor.line][cursor.column]; + CharType closec=0; - const String &str=text[line]; + if (c=='[') { + closec=']'; + } else if (c=='{') { + closec='}'; + } else if (c=='(') { + closec=')'; + } - int char_margin=xmargin_beg-cursor.x_ofs; - int char_ofs=0; - int ofs_y=i*get_row_height()+cache.line_spacing/2; - bool prev_is_char=false; - bool in_keyword=false; - Color keyword_color; + if (closec!=0) { - if (cache.line_number_w) { - Color fcol = cache.font_color; - fcol.a*=0.4; - String fc = String::num(line+1); - while (fc.length() < line_number_char_count) { - fc="0"+fc; - } + int stack=1; - cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT),ofs_y+cache.font->get_ascent()),fc,fcol); - } - const Map<int,Text::ColorRegionInfo>& cri_map=text.get_color_region_info(line); + for(int i=cursor.line;i<text.size();i++) { + int from = i==cursor.line?cursor.column+1:0; + for(int j=from;j<text[i].length();j++) { - if (text.is_marked(line)) { + CharType cc = text[i][j]; + if (cc==c) + stack++; + else if (cc==closec) + stack--; - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.mark_color); - } + if (stack==0) { + brace_open_match_line=i; + brace_open_match_column=j; + brace_open_matching=true; - if (text.is_breakpoint(line)) { + break; + } + } + if (brace_open_match_line!=-1) + break; + } - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.breakpoint_color); - } + if (!brace_open_matching) + brace_open_mismatch=true; - if (line==cursor.line) { + } + } - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.current_line_color); + if (cursor.column>0) { + CharType c = text[cursor.line][cursor.column-1]; + CharType closec=0; - } - for (int j=0;j<str.length();j++) { - //look for keyword - if (deregion>0) { - deregion--; - if (deregion==0) - in_region=-1; - } - if (syntax_coloring && deregion==0) { + if (c==']') { + closec='['; + } else if (c=='}') { + closec='{'; + } else if (c==')') { + closec='('; + } + if (closec!=0) { - color = cache.font_color; //reset - //find keyword - bool is_char = _is_text_char(str[j]); - bool is_symbol=_is_symbol(str[j]); + int stack=1; - if (j==0 && in_region>=0 && color_regions[in_region].line_only) { - in_region=-1; //reset regions that end at end of line - } - if (is_symbol && cri_map.has(j)) { + for(int i=cursor.line;i>=0;i--) { + int from = i==cursor.line?cursor.column-2:text[i].length()-1; + for(int j=from;j>=0;j--) { - const Text::ColorRegionInfo &cri=cri_map[j]; + CharType cc = text[i][j]; + if (cc==c) + stack++; + else if (cc==closec) + stack--; - if (in_region==-1) { + if (stack==0) { + brace_close_match_line=i; + brace_close_match_column=j; + brace_close_matching=true; - if (!cri.end) { + break; + } + } + if (brace_close_match_line!=-1) + break; + } - in_region=cri.region; - } - } else if (in_region==cri.region && !color_regions[cri.region].line_only) { //ignore otherwise + if (!brace_close_matching) + brace_close_mismatch=true; - if (cri.end || color_regions[cri.region].eq) { - deregion=color_regions[cri.region].eq?color_regions[cri.region].begin_key.length():color_regions[cri.region].end_key.length(); - } - } - } + } - if (!is_char) - in_keyword=false; - if (in_region==-1 && !in_keyword && is_char && !prev_is_char) { + } + } - int to=j; - while(_is_text_char(str[to]) && to<str.length()) - to++; - uint32_t hash = String::hash(&str[j],to-j); - StrRange range(&str[j],to-j); + int deregion=0; //force it to clear inrgion + Point2 cursor_pos; - const Color *col=keywords.custom_getptr(range,hash); + for (int i=0;i<visible_rows;i++) { - if (col) { + int line=i+cursor.line_ofs; - in_keyword=true; - keyword_color=*col; - } - } + if (line<0 || line>=(int)text.size()) + continue; + const String &str=text[line]; - if (in_region>=0) - color=color_regions[in_region].color; - else if (in_keyword) - color=keyword_color; - else if (is_symbol) - color=symbol_color; + int char_margin=xmargin_beg-cursor.x_ofs; + int char_ofs=0; + int ofs_y=i*get_row_height()+cache.line_spacing/2; + bool prev_is_char=false; + bool in_keyword=false; + Color keyword_color; - prev_is_char=is_char; + if (cache.line_number_w) { + Color fcol = cache.font_color; + fcol.a*=0.4; + String fc = String::num(line+1); + while (fc.length() < line_number_char_count) { + fc="0"+fc; + } - } - int char_w; + cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT),ofs_y+cache.font->get_ascent()),fc,fcol); + } - //handle tabulator + const Map<int,Text::ColorRegionInfo>& cri_map=text.get_color_region_info(line); - if (str[j]=='\t') { - int left = char_ofs%tab_w; - if (left==0) - char_w=tab_w; - else - char_w=tab_w-char_ofs%tab_w; // is right... + if (text.is_marked(line)) { - } else { - char_w=cache.font->get_char_size(str[j],str[j+1]).width; - } + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.mark_color); + } - if ( (char_ofs+char_margin)<xmargin_beg) { - char_ofs+=char_w; - continue; - } + if (text.is_breakpoint(line)) { - if ( (char_ofs+char_margin+char_w)>=xmargin_end) { - if (syntax_coloring) - continue; - else - break; - } + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.breakpoint_color); + } - bool in_selection = (selection.active && line>=selection.from_line && line<=selection.to_line && (line>selection.from_line || j>=selection.from_column) && (line<selection.to_line || j<selection.to_column)); + if (line==cursor.line) { - if (in_selection) { - //inside selection! - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w,get_row_height())),cache.selection_color); - } + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.current_line_color); + } + for (int j=0;j<str.length();j++) { + //look for keyword - if (str[j]>=32) - cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),str[j],str[j+1],in_selection?cache.font_selected_color:color); - else if (draw_tabs && str[j]=='\t') { - int yofs= (get_row_height() - cache.tab_icon->get_height())/2; - cache.tab_icon->draw(ci, Point2(char_ofs+char_margin,ofs_y+yofs),in_selection?cache.font_selected_color:color); - } + if (deregion>0) { + deregion--; + if (deregion==0) + in_region=-1; + } + if (syntax_coloring && deregion==0) { - if (cursor.column==j && cursor.line==line) { + color = cache.font_color; //reset + //find keyword + bool is_char = _is_text_char(str[j]); + bool is_symbol=_is_symbol(str[j]); - cursor_pos = Point2i( char_ofs+char_margin, ofs_y ); - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.font_color); + if (j==0 && in_region>=0 && color_regions[in_region].line_only) { + in_region=-1; //reset regions that end at end of line + } + if (is_symbol && cri_map.has(j)) { - } - char_ofs+=char_w; - } + const Text::ColorRegionInfo &cri=cri_map[j]; - if (cursor.column==str.length() && cursor.line==line) { + if (in_region==-1) { - cursor_pos=Point2i( char_ofs+char_margin, ofs_y ); - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.font_color); + if (!cri.end) { - } - } + in_region=cri.region; + } + } else if (in_region==cri.region && !color_regions[cri.region].line_only) { //ignore otherwise - if (completion_active) { - // code completion box - Ref<StyleBox> csb = get_stylebox("completion"); - Ref<StyleBox> csel = get_stylebox("completion_selected"); - int maxlines = get_constant("completion_lines"); - int cmax_width = get_constant("completion_max_width")*cache.font->get_char_size('x').x; - Color existing = get_color("completion_existing"); - int scrollw = get_constant("completion_scroll_width"); - Color scrollc = get_color("completion_scroll_color"); + if (cri.end || color_regions[cri.region].eq) { + deregion=color_regions[cri.region].eq?color_regions[cri.region].begin_key.length():color_regions[cri.region].end_key.length(); + } + } + } + if (!is_char) + in_keyword=false; - int lines = MIN(completion_options.size(),maxlines); - int w=0; - int h=lines*get_row_height(); - int nofs = cache.font->get_string_size(completion_base).width; + if (in_region==-1 && !in_keyword && is_char && !prev_is_char) { + int to=j; + while(_is_text_char(str[to]) && to<str.length()) + to++; - if (completion_options.size() < 50) { - for(int i=0;i<completion_options.size();i++) { - int w2=MIN(cache.font->get_string_size(completion_options[i]).x,cmax_width); - if (w2>w) - w=w2; - } - } else { - w=cmax_width; - } + uint32_t hash = String::hash(&str[j],to-j); + StrRange range(&str[j],to-j); - int th = h + csb->get_minimum_size().y; - if (cursor_pos.y+get_row_height()+th > get_size().height) { - completion_rect.pos.y=cursor_pos.y-th; - } else { - completion_rect.pos.y=cursor_pos.y+get_row_height()+csb->get_offset().y; - } + const Color *col=keywords.custom_getptr(range,hash); - if (cursor_pos.x-nofs+w+scrollw > get_size().width) { - completion_rect.pos.x=get_size().width-w-scrollw; - } else { - completion_rect.pos.x=cursor_pos.x-nofs; - } + if (col) { - completion_rect.size.width=w; - completion_rect.size.height=h; - if (completion_options.size()<=maxlines) - scrollw=0; + in_keyword=true; + keyword_color=*col; + } + } - draw_style_box(csb,Rect2(completion_rect.pos-csb->get_offset(),completion_rect.size+csb->get_minimum_size()+Size2(scrollw,0))); + if (in_region>=0) + color=color_regions[in_region].color; + else if (in_keyword) + color=keyword_color; + else if (is_symbol) + color=symbol_color; - int line_from = CLAMP(completion_index - lines/2, 0, completion_options.size() - lines); - draw_style_box(csel,Rect2(Point2(completion_rect.pos.x,completion_rect.pos.y+(completion_index-line_from)*get_row_height()),Size2(completion_rect.size.width,get_row_height()))); + prev_is_char=is_char; - draw_rect(Rect2(completion_rect.pos,Size2(nofs,completion_rect.size.height)),existing); + } + int char_w; - for(int i=0;i<lines;i++) { + //handle tabulator - int l = line_from + i; - ERR_CONTINUE( l < 0 || l>= completion_options.size()); - draw_string(cache.font,Point2(completion_rect.pos.x,completion_rect.pos.y+i*get_row_height()+cache.font->get_ascent()),completion_options[l],cache.font_color,completion_rect.size.width); - } - if (scrollw) { - //draw a small scroll rectangle to show a position in the options - float r = maxlines / (float)completion_options.size(); - float o = line_from / (float)completion_options.size(); - draw_rect(Rect2(completion_rect.pos.x+completion_rect.size.width,completion_rect.pos.y+o*completion_rect.size.y,scrollw,completion_rect.size.y*r),scrollc); - } + if (str[j]=='\t') { + int left = char_ofs%tab_w; + if (left==0) + char_w=tab_w; + else + char_w=tab_w-char_ofs%tab_w; // is right... - completion_line_ofs=line_from; + } else { + char_w=cache.font->get_char_size(str[j],str[j+1]).width; + } - } + if ( (char_ofs+char_margin)<xmargin_beg) { + char_ofs+=char_w; + continue; + } + if ( (char_ofs+char_margin+char_w)>=xmargin_end) { + if (syntax_coloring) + continue; + else + break; + } + bool in_selection = (selection.active && line>=selection.from_line && line<=selection.to_line && (line>selection.from_line || j>=selection.from_column) && (line<selection.to_line || j<selection.to_column)); - } break; - case NOTIFICATION_FOCUS_ENTER: { - if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->show_virtual_keyboard(get_text(),get_global_rect()); + if (in_selection) { + //inside selection! + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w,get_row_height())),cache.selection_color); + } - } break; - case NOTIFICATION_FOCUS_EXIT: { - if (OS::get_singleton()->has_virtual_keyboard()) - OS::get_singleton()->hide_virtual_keyboard(); + if (brace_matching_enabled) { + if ( (brace_open_match_line==line && brace_open_match_column==j) || + (cursor.column==j && cursor.line==line && (brace_open_matching||brace_open_mismatch))) { - } break; + if (brace_open_mismatch) + color=cache.brace_mismatch_color; + cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),'_',str[j+1],in_selection?cache.font_selected_color:color); - } + } + + if ( + (brace_close_match_line==line && brace_close_match_column==j) || + (cursor.column==j+1 && cursor.line==line && (brace_close_matching||brace_close_mismatch))) { + + + if (brace_close_mismatch) + color=cache.brace_mismatch_color; + cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),'_',str[j+1],in_selection?cache.font_selected_color:color); + + } + } + + + if (str[j]>=32) + cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),str[j],str[j+1],in_selection?cache.font_selected_color:color); + + else if (draw_tabs && str[j]=='\t') { + int yofs= (get_row_height() - cache.tab_icon->get_height())/2; + cache.tab_icon->draw(ci, Point2(char_ofs+char_margin,ofs_y+yofs),in_selection?cache.font_selected_color:color); + } + + + if (cursor.column==j && cursor.line==line) { + + cursor_pos = Point2i( char_ofs+char_margin, ofs_y ); + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.font_color); + + + } + char_ofs+=char_w; + + } + + if (cursor.column==str.length() && cursor.line==line) { + + cursor_pos=Point2i( char_ofs+char_margin, ofs_y ); + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.font_color); + + } + } + + + if (completion_active) { + // code completion box + Ref<StyleBox> csb = get_stylebox("completion"); + Ref<StyleBox> csel = get_stylebox("completion_selected"); + int maxlines = get_constant("completion_lines"); + int cmax_width = get_constant("completion_max_width")*cache.font->get_char_size('x').x; + Color existing = get_color("completion_existing"); + existing.a=0.2; + int scrollw = get_constant("completion_scroll_width"); + Color scrollc = get_color("completion_scroll_color"); + + + + int lines = MIN(completion_options.size(),maxlines); + int w=0; + int h=lines*get_row_height(); + int nofs = cache.font->get_string_size(completion_base).width; + + + if (completion_options.size() < 50) { + for(int i=0;i<completion_options.size();i++) { + int w2=MIN(cache.font->get_string_size(completion_options[i]).x,cmax_width); + if (w2>w) + w=w2; + } + } else { + w=cmax_width; + } + + int th = h + csb->get_minimum_size().y; + if (cursor_pos.y+get_row_height()+th > get_size().height) { + completion_rect.pos.y=cursor_pos.y-th; + } else { + completion_rect.pos.y=cursor_pos.y+get_row_height()+csb->get_offset().y; + + } + + if (cursor_pos.x-nofs+w+scrollw > get_size().width) { + completion_rect.pos.x=get_size().width-w-scrollw; + } else { + completion_rect.pos.x=cursor_pos.x-nofs; + } + + completion_rect.size.width=w; + completion_rect.size.height=h; + if (completion_options.size()<=maxlines) + scrollw=0; + + draw_style_box(csb,Rect2(completion_rect.pos-csb->get_offset(),completion_rect.size+csb->get_minimum_size()+Size2(scrollw,0))); + + + int line_from = CLAMP(completion_index - lines/2, 0, completion_options.size() - lines); + draw_style_box(csel,Rect2(Point2(completion_rect.pos.x,completion_rect.pos.y+(completion_index-line_from)*get_row_height()),Size2(completion_rect.size.width,get_row_height()))); + + draw_rect(Rect2(completion_rect.pos,Size2(nofs,completion_rect.size.height)),existing); + + + + + for(int i=0;i<lines;i++) { + + int l = line_from + i; + ERR_CONTINUE( l < 0 || l>= completion_options.size()); + Color text_color = cache.font_color; + for(int j=0;j<color_regions.size();j++) { + if (completion_options[l].begins_with(color_regions[j].begin_key)) { + text_color=color_regions[j].color; + } + } + draw_string(cache.font,Point2(completion_rect.pos.x,completion_rect.pos.y+i*get_row_height()+cache.font->get_ascent()),completion_options[l],text_color,completion_rect.size.width); + } + + if (scrollw) { + //draw a small scroll rectangle to show a position in the options + float r = maxlines / (float)completion_options.size(); + float o = line_from / (float)completion_options.size(); + draw_rect(Rect2(completion_rect.pos.x+completion_rect.size.width,completion_rect.pos.y+o*completion_rect.size.y,scrollw,completion_rect.size.y*r),scrollc); + } + + completion_line_ofs=line_from; + + } + + if (completion_hint!="") { + + Ref<StyleBox> sb = get_stylebox("panel","TooltipPanel"); + Ref<Font> font = cache.font; + Color font_color = get_color("font_color","TooltipLabel"); + + + int max_w=0; + int sc = completion_hint.get_slice_count("\n"); + int offset=0; + int spacing=0; + for(int i=0;i<sc;i++) { + + String l = completion_hint.get_slice("\n",i); + int len = font->get_string_size(l).x; + max_w = MAX(len,max_w); + if (i==0) { + offset = font->get_string_size(l.substr(0,l.find(String::chr(0xFFFF)))).x; + } else { + spacing+=cache.line_spacing; + } + + + } + + + + Size2 size = Size2(max_w,sc*font->get_height()+spacing); + Size2 minsize = size+sb->get_minimum_size(); + + + if (completion_hint_offset==-0xFFFF) { + completion_hint_offset=cursor_pos.x-offset; + } + + + Point2 hint_ofs = Vector2(completion_hint_offset,cursor_pos.y-minsize.y); + draw_style_box(sb,Rect2(hint_ofs,minsize)); + + spacing=0; + for(int i=0;i<sc;i++) { + int begin=0; + int end=0; + String l = completion_hint.get_slice("\n",i); + + if (l.find(String::chr(0xFFFF))!=-1) { + begin = font->get_string_size(l.substr(0,l.find(String::chr(0xFFFF)))).x; + end = font->get_string_size(l.substr(0,l.rfind(String::chr(0xFFFF)))).x; + } + + draw_string(font,hint_ofs+sb->get_offset()+Vector2(0,font->get_ascent()+font->get_height()*i+spacing),l.replace(String::chr(0xFFFF),""),font_color); + if (end>0) { + Vector2 b = hint_ofs+sb->get_offset()+Vector2(begin,font->get_height()+font->get_height()*i+spacing-1); + draw_line(b,b+Vector2(end-begin,0),font_color); + } + spacing+=cache.line_spacing; + } + } + + + } break; + case NOTIFICATION_FOCUS_ENTER: { + + if (OS::get_singleton()->has_virtual_keyboard()) + OS::get_singleton()->show_virtual_keyboard(get_text(),get_global_rect()); + + } break; + case NOTIFICATION_FOCUS_EXIT: { + + if (OS::get_singleton()->has_virtual_keyboard()) + OS::get_singleton()->hide_virtual_keyboard(); + + } break; + + } } void TextEdit::_consume_pair_symbol(CharType ch) { @@ -918,6 +1124,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { return; } else { _cancel_completion(); + _cancel_code_hint(); } if (mb.pressed) { @@ -1172,6 +1379,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } _cancel_completion(); + } /* TEST CONTROL FIRST!! */ @@ -1268,6 +1476,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { break; unselect=true; break; + default: if (k.unicode>=32 && !k.mod.command && !k.mod.alt && !k.mod.meta) clear=true; @@ -1318,6 +1527,13 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { _push_current_op(); } break; + case KEY_ESCAPE: { + if (completion_hint!="") { + completion_hint=""; + update(); + + } + } break; case KEY_TAB: { if (readonly) @@ -1454,6 +1670,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (k.mod.shift) _post_shift_selection(); + _cancel_code_hint(); } break; case KEY_DOWN: { @@ -1473,6 +1690,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (k.mod.shift) _post_shift_selection(); + _cancel_code_hint(); } break; @@ -1703,27 +1921,6 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } break; - case KEY_K:{ - if (!k.mod.command || k.mod.shift || k.mod.alt) { - scancode_handled=false; - break; - } - else { - if (selection.active) { - int ini = selection.from_line; - int end = selection.to_line; - for (int i=ini; i<= end; i++) - { - _insert_text(i,0,"#"); - } - } - else{ - _insert_text(cursor.line,0,"#"); - } - update(); - } - break;} - case KEY_U:{ if (!k.mod.command || k.mod.shift || k.mod.alt) { scancode_handled=false; @@ -2333,6 +2530,30 @@ String TextEdit::get_text() { }; +String TextEdit::get_text_for_completion() { + + String longthing; + int len = text.size(); + for (int i=0;i<len;i++) { + + if (i==cursor.line) { + longthing+=text[i].substr(0,cursor.column); + longthing+=String::chr(0xFFFF); //not unicode, represents the cursor + longthing+=text[i].substr(cursor.column,text[i].size()); + } else { + + longthing+=text[i]; + } + + + if (i!=len-1) + longthing+="\n"; + } + + return longthing; + +}; + String TextEdit::get_line(int line) const { @@ -2392,6 +2613,7 @@ void TextEdit::_update_caches() { cache.mark_color=get_color("mark_color"); cache.current_line_color=get_color("current_line_color"); cache.breakpoint_color=get_color("breakpoint_color"); + cache.brace_mismatch_color=get_color("brace_mismatch_color"); cache.line_spacing=get_constant("line_spacing"); cache.row_height = cache.font->get_height() + cache.line_spacing; cache.tab_icon=get_icon("tab"); @@ -2966,33 +3188,56 @@ void TextEdit::_confirm_completion() { if (same) cursor_set_column(cursor.column+remaining.length()); - else + else { insert_text_at_cursor(remaining); + if (remaining.ends_with("(") && auto_brace_completion_enabled) { + insert_text_at_cursor(")"); + cursor.column--; + } + } _cancel_completion(); } + +void TextEdit::_cancel_code_hint() { + completion_hint=""; + update(); +} + void TextEdit::_cancel_completion() { if (!completion_active) return; - completion_active=false; + completion_active=false; update(); } +static bool _is_completable(CharType c) { + + return !_is_symbol(c) || c=='"' || c=='\''; +} + + void TextEdit::_update_completion_candidates() { String l = text[cursor.line]; int cofs = CLAMP(cursor.column,0,l.length()); + String s; - while(cofs>0 && l[cofs-1]>32 && !_is_symbol(l[cofs-1])) { - s=String::chr(l[cofs-1])+s; + + while(cofs>0 && l[cofs-1]>32 && _is_completable(l[cofs-1])) { + s=String::chr(l[cofs-1])+s; + if (l[cofs-1]=='\'' || l[cofs-1]=='"') + break; + cofs--; } + update(); if (s=="" && (cofs==0 || !completion_prefixes.has(String::chr(l[cofs-1])))) { @@ -3055,36 +3300,24 @@ void TextEdit::_update_completion_candidates() { completion_enabled=true; } + + void TextEdit::query_code_comple() { - String l = text[cursor.line]; - int ofs = CLAMP(cursor.column,0,l.length()); - String cs; - while(ofs>0 && l[ofs-1]>32) { - - if (_is_symbol(l[ofs-1])) { - String s; - while(ofs>0 && l[ofs-1]>32 && _is_symbol(l[ofs-1])) { - s=String::chr(l[ofs-1])+s; - ofs--; - } - if (completion_prefixes.has(s)) - cs=s+cs; - else - break; - } else { + String l = text[cursor.line]; + int ofs = CLAMP(cursor.column,0,l.length()); - cs=String::chr(l[ofs-1])+cs; - ofs--; - } + if (ofs>0 && (_is_completable(l[ofs-1]) || completion_prefixes.has(String::chr(l[ofs-1])))) + emit_signal("request_completion"); - } +} - if (cs!="") { - emit_signal("request_completion",cs,cursor.line); - } +void TextEdit::set_code_hint(const String& p_hint) { + completion_hint=p_hint; + completion_hint_offset=-0xFFFF; + update(); } void TextEdit::code_complete(const Vector<String> &p_strings) { @@ -3236,7 +3469,7 @@ void TextEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("cursor_changed")); ADD_SIGNAL(MethodInfo("text_changed")); - ADD_SIGNAL(MethodInfo("request_completion",PropertyInfo(Variant::STRING,"keyword"),PropertyInfo(Variant::INT,"line"))); + ADD_SIGNAL(MethodInfo("request_completion")); } @@ -3321,6 +3554,8 @@ TextEdit::TextEdit() { line_numbers=false; next_operation_is_complex=false; auto_brace_completion_enabled=false; + brace_matching_enabled=false; + } TextEdit::~TextEdit() diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index d70403a944..ed4d30a9d2 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -79,6 +79,7 @@ class TextEdit : public Control { Color mark_color; Color breakpoint_color; Color current_line_color; + Color brace_mismatch_color; int row_height; int line_spacing; @@ -185,6 +186,8 @@ class TextEdit : public Control { int completion_index; Rect2i completion_rect; int completion_line_ofs; + String completion_hint; + int completion_hint_offset; bool setting_text; @@ -208,6 +211,7 @@ class TextEdit : public Control { bool line_numbers; bool auto_brace_completion_enabled; + bool brace_matching_enabled; bool cut_copy_line; uint64_t last_dblclk; @@ -261,6 +265,7 @@ class TextEdit : public Control { void _clear(); void _cancel_completion(); + void _cancel_code_hint(); void _confirm_completion(); void _update_completion_candidates(); @@ -313,7 +318,11 @@ public: inline void set_auto_brace_completion(bool p_enabled) { auto_brace_completion_enabled = p_enabled; } - + inline void set_brace_matching(bool p_enabled) { + brace_matching_enabled=p_enabled; + update(); + } + void cursor_set_column(int p_col); void cursor_set_line(int p_row); @@ -350,7 +359,7 @@ public: void undo(); void redo(); - void clear_undo_history(); + void clear_undo_history(); void set_draw_tabs(bool p_draw); @@ -376,10 +385,13 @@ public: void set_tooltip_request_func(Object *p_obj, const StringName& p_function, const Variant& p_udata); - void set_completion(bool p_enabled,const Vector<String>& p_prefixes); + void set_completion(bool p_enabled,const Vector<String>& p_prefixes); void code_complete(const Vector<String> &p_strings); + void set_code_hint(const String& p_hint); void query_code_comple(); + String get_text_for_completion(); + TextEdit(); ~TextEdit(); }; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 45a30d7bca..d9b208d6d3 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1731,6 +1731,26 @@ NodePath Node::get_import_path() const { #endif +static void _add_nodes_to_options(const Node *p_base,const Node *p_node,List<String>*r_options) { + + if (p_node!=p_base && !p_node->get_owner()) + return; + String n = p_base->get_path_to(p_node); + r_options->push_back("\""+n+"\""); + for(int i=0;i<p_node->get_child_count();i++) { + _add_nodes_to_options(p_base,p_node->get_child(i),r_options); + } +} + +void Node::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const { + + String pf=p_function; + if ((pf=="has_node" || pf=="get_node") && p_idx==0) { + + _add_nodes_to_options(this,this,r_options); + } + Object::get_argument_options(p_function,p_idx,r_options); +} void Node::_bind_methods() { diff --git a/scene/main/node.h b/scene/main/node.h index 371a5325ca..47f49eb625 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -284,6 +284,7 @@ public: NodePath get_import_path() const; #endif + void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const; _FORCE_INLINE_ Viewport *get_viewport() const { return data.viewport; } diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 741deccdbe..962e8c26e0 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -75,6 +75,7 @@ #include "scene/gui/split_container.h" #include "scene/gui/video_player.h" #include "scene/gui/reference_frame.h" +#include "scene/gui/graph_node.h" #include "scene/resources/video_stream.h" #include "scene/2d/particles_2d.h" #include "scene/2d/path_2d.h" @@ -303,6 +304,7 @@ void register_scene_types() { ObjectTypeDB::register_virtual_type<SplitContainer>(); ObjectTypeDB::register_type<HSplitContainer>(); ObjectTypeDB::register_type<VSplitContainer>(); + ObjectTypeDB::register_type<GraphNode>(); OS::get_singleton()->yield(); //may take time to init diff --git a/scene/resources/audio_stream_resampled.cpp b/scene/resources/audio_stream_resampled.cpp index 8e694a6110..bc7bffa9d2 100644 --- a/scene/resources/audio_stream_resampled.cpp +++ b/scene/resources/audio_stream_resampled.cpp @@ -38,15 +38,18 @@ int AudioStreamResampled::get_channel_count() const { template<int C> -void AudioStreamResampled::_resample(int32_t *p_dest,int p_todo,int32_t p_increment) { +uint32_t AudioStreamResampled::_resample(int32_t *p_dest,int p_todo,int32_t p_increment) { + + uint32_t read=offset&MIX_FRAC_MASK; for (int i=0;i<p_todo;i++) { offset = (offset + p_increment)&(((1<<(rb_bits+MIX_FRAC_BITS))-1)); + read+=p_increment; uint32_t pos = offset >> MIX_FRAC_BITS; uint32_t frac = offset & MIX_FRAC_MASK; #ifndef FAST_AUDIO - ERR_FAIL_COND(pos>=rb_len); + ERR_FAIL_COND_V(pos>=rb_len,0); #endif uint32_t pos_next = (pos+1)&rb_mask; //printf("rb pos %i\n",pos); @@ -151,7 +154,7 @@ void AudioStreamResampled::_resample(int32_t *p_dest,int p_todo,int32_t p_increm } - rb_read_pos=offset>>MIX_FRAC_BITS; + return read>>MIX_FRAC_BITS;//rb_read_pos=offset>>MIX_FRAC_BITS; } @@ -173,10 +176,10 @@ bool AudioStreamResampled::mix(int32_t *p_dest, int p_frames) { } else if (rb_read_pos<write_pos_cache) { - rb_todo=write_pos_cache-rb_read_pos-1; + rb_todo=write_pos_cache-rb_read_pos; //-1? } else { - rb_todo=(rb_len-rb_read_pos)+write_pos_cache-1; + rb_todo=(rb_len-rb_read_pos)+write_pos_cache; //-1? } int todo = MIN( ((int64_t(rb_todo)<<MIX_FRAC_BITS)/increment)+1, p_frames ); @@ -220,13 +223,22 @@ bool AudioStreamResampled::mix(int32_t *p_dest, int p_frames) { #endif { + uint32_t read=0; switch(channels) { - case 1: _resample<1>(p_dest,todo,increment); break; - case 2: _resample<2>(p_dest,todo,increment); break; - case 4: _resample<4>(p_dest,todo,increment); break; - case 6: _resample<6>(p_dest,todo,increment); break; + case 1: read=_resample<1>(p_dest,todo,increment); break; + case 2: read=_resample<2>(p_dest,todo,increment); break; + case 4: read=_resample<4>(p_dest,todo,increment); break; + case 6: read=_resample<6>(p_dest,todo,increment); break; } + if (read>rb_todo) + read=rb_todo; + + rb_read_pos = (rb_read_pos+read)&rb_mask; + + + + } return true; diff --git a/scene/resources/audio_stream_resampled.h b/scene/resources/audio_stream_resampled.h index f1e3629ac7..a1b95e81d5 100644 --- a/scene/resources/audio_stream_resampled.h +++ b/scene/resources/audio_stream_resampled.h @@ -57,7 +57,7 @@ class AudioStreamResampled : public AudioStream { template<int C> - void _resample(int32_t *p_dest,int p_todo,int32_t p_increment); + uint32_t _resample(int32_t *p_dest,int p_todo,int32_t p_increment); protected: @@ -97,7 +97,7 @@ protected: _FORCE_INLINE_ int16_t *get_write_buffer() { return read_buf; } _FORCE_INLINE_ void write(uint32_t p_frames) { - ERR_FAIL_COND(p_frames > rb_len); + ERR_FAIL_COND(p_frames >= rb_len); switch(channels) { case 1: { diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index d10bb37f60..050e462902 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -65,7 +65,7 @@ static Ref<Texture> make_icon(T p_src) { Ref<ImageTexture> texture( memnew( ImageTexture ) ); - texture->create_from_image( Image(p_src) ); + texture->create_from_image( Image(p_src),ImageTexture::FLAG_FILTER ); return texture; } @@ -331,6 +331,7 @@ void make_default_theme() { t->set_color("current_line_color","TextEdit", Color(0.3,0.5,0.8,0.15) ); t->set_color("cursor_color","TextEdit", control_font_color ); t->set_color("symbol_color","TextEdit", control_font_color_hover ); + t->set_color("brace_mismatch_color","TextEdit", Color(1,0.2,0.2) ); t->set_constant("line_spacing","TextEdit",1 ); t->set_stylebox("scroll","HScrollBar", make_stylebox( hscroll_bg_png,3,3,3,3,0,0,0,0) ); @@ -415,7 +416,15 @@ void make_default_theme() { t->set_color("font_color_hover","PopupMenu", control_font_color ); t->set_constant("hseparation","PopupMenu",2); t->set_constant("vseparation","PopupMenu",1); - + + Ref<StyleBoxTexture> graphsb = make_stylebox(graph_node_png,6,21,6,5,16,21,16,5); + //graphsb->set_expand_margin_size(MARGIN_LEFT,10); + //graphsb->set_expand_margin_size(MARGIN_RIGHT,10); + t->set_stylebox("frame","GraphNode", graphsb ); + t->set_constant("separation","GraphNode", 1 ); + t->set_icon("port","GraphNode", make_icon( graph_port_png ) ); + + t->set_stylebox("bg","Tree", make_stylebox( tree_bg_png,4,4,4,5,3,3,3,3) ); t->set_stylebox("bg_focus","Tree", focus ); Ref<StyleBoxTexture> tree_selected = make_stylebox( selection_png,4,4,4,4); diff --git a/scene/resources/default_theme/graph_node.png b/scene/resources/default_theme/graph_node.png Binary files differnew file mode 100644 index 0000000000..3adccf2c3b --- /dev/null +++ b/scene/resources/default_theme/graph_node.png diff --git a/scene/resources/default_theme/graph_port.png b/scene/resources/default_theme/graph_port.png Binary files differnew file mode 100644 index 0000000000..92f425f977 --- /dev/null +++ b/scene/resources/default_theme/graph_port.png diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index 9cef0265ee..9fe77b3223 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -99,6 +99,16 @@ static const unsigned char full_panel_bg_png[]={ }; +static const unsigned char graph_node_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,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,0xde,0xc,0x14,0x10,0x3,0x2e,0x15,0xb6,0x7,0x4a,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x6a,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0x97,0xbb,0x6e,0x13,0x51,0x10,0x86,0xbf,0xf1,0x2e,0xb1,0x83,0x85,0x63,0x5,0x10,0xe2,0x22,0xa5,0x0,0x1a,0x24,0x90,0x22,0x9e,0x81,0x2,0xd1,0x53,0xf1,0x2,0x20,0xa,0x1a,0xa,0xa0,0x44,0xd0,0xd0,0x20,0x81,0xe0,0x5,0xa8,0xe8,0x11,0x5,0xcf,0x80,0x22,0x81,0x42,0x3,0x14,0x91,0xb8,0x4,0x85,0x58,0x8e,0x21,0x78,0xd7,0xd9,0x73,0x86,0xe2,0x9c,0xdd,0xec,0xae,0xd7,0xce,0x85,0xe,0xed,0x34,0xbb,0x3a,0x3e,0xf3,0xcd,0xcc,0x3f,0x63,0x69,0x47,0xd8,0x36,0x1,0x1a,0x40,0xe0,0x9f,0x42,0xd1,0x14,0xb0,0x80,0xf1,0x4f,0x25,0x77,0xa9,0x1,0x1c,0x4,0xe6,0x81,0xa3,0x40,0x7,0x38,0x50,0x2,0x6c,0x1,0x3,0x60,0xd,0xe8,0x1,0x7f,0x0,0x9b,0x46,0x6d,0x3,0x67,0xe6,0xe,0x75,0xaf,0xb7,0x9a,0xad,0xcb,0x33,0x33,0xcd,0x53,0x54,0xd8,0x68,0x14,0x7f,0x89,0xe2,0xe8,0xf5,0xc6,0xaf,0xfe,0x73,0xe0,0x13,0xb0,0x29,0x3e,0xd2,0xc2,0x7c,0xf7,0xf0,0xe3,0xd3,0xb,0x67,0xaf,0x3c,0xb8,0xfb,0x88,0xd9,0x4e,0xab,0xca,0x9f,0xe1,0x20,0xe2,0xde,0xc3,0xdb,0x7c,0x5e,0xf9,0xf8,0xaa,0xd7,0x5f,0xbf,0x5,0xac,0x8,0xd0,0x2,0x16,0x8f,0x1f,0x3b,0xf9,0xe6,0xc5,0xb3,0x97,0xed,0x24,0xb1,0x24,0xa3,0xa4,0x12,0x10,0xce,0x84,0x84,0x61,0x83,0x6b,0x37,0xae,0x6e,0x7e,0xff,0xf1,0xf5,0x12,0xb0,0x14,0x7a,0x1d,0xda,0x61,0x10,0xb6,0x87,0xbf,0x63,0x10,0x75,0x47,0xa,0x2a,0x79,0x85,0x95,0x51,0xbc,0xc5,0x28,0x86,0x30,0x8,0xdb,0xbe,0x6c,0x49,0x1,0x1,0x80,0x51,0xeb,0xfc,0x9d,0xc0,0x4e,0x6b,0xf,0xd1,0xfc,0xb9,0xb3,0x20,0x5,0x68,0xfa,0x8b,0x5a,0x8b,0xaa,0x80,0x28,0x82,0xa0,0x28,0xa2,0x92,0x73,0xd3,0xb1,0xde,0x86,0x85,0x46,0x5b,0x45,0x51,0x50,0x45,0xc4,0x95,0x61,0x53,0x27,0x71,0x61,0x74,0x1a,0xc0,0xaa,0xcd,0x6e,0xa8,0x64,0x2f,0xee,0x5d,0x29,0x8a,0x32,0x39,0x3,0x5f,0xb6,0x2f,0x4c,0x45,0x73,0x5a,0xd8,0x31,0x48,0x1,0x60,0xac,0x2d,0xf1,0x5,0x51,0x75,0x45,0x68,0x5a,0xbf,0x4e,0xcf,0x60,0xfb,0x82,0x2b,0x5a,0x73,0x4e,0xb6,0xe2,0xf,0x52,0x2,0xd8,0x82,0xe2,0x14,0x50,0x54,0xc4,0x2f,0x8b,0x68,0xad,0x1f,0x99,0x54,0x79,0x41,0xdd,0x0,0xf8,0xb6,0x82,0x88,0x4e,0xeb,0x82,0x66,0x89,0xaa,0x3b,0xc8,0x52,0x48,0x41,0x56,0x76,0xcc,0x60,0x7b,0x74,0x75,0xac,0x1a,0x49,0x47,0x72,0x72,0x6,0xe2,0xe7,0x56,0x45,0xfd,0x5d,0xc9,0x44,0x28,0x40,0x2b,0x45,0x34,0xea,0x7,0xa8,0x14,0xc9,0x92,0x75,0x64,0x7,0x11,0x8d,0x8f,0x98,0x9b,0x87,0xf2,0xf4,0x4d,0xd5,0x40,0xd5,0xc9,0x97,0xf,0xa3,0x5a,0x74,0x9c,0x36,0x89,0xf7,0x9f,0xdc,0x61,0xaf,0x96,0x1,0x92,0x2d,0xc3,0xe2,0xf9,0x8b,0xbb,0x72,0x5a,0x7a,0xff,0xb6,0x3a,0x83,0x8d,0x41,0x7f,0xcf,0x19,0x34,0xf8,0x47,0xab,0x1,0x35,0xa0,0x6,0xd4,0x80,0x1a,0x50,0x3,0x6a,0xc0,0x7f,0x9,0x90,0x8a,0x4f,0xe0,0x3d,0x67,0x60,0xf7,0xe1,0x6b,0x53,0x80,0x5,0x22,0x63,0x4c,0x6c,0x93,0x5d,0x78,0x25,0x60,0x8c,0x89,0x81,0x8,0xb0,0xd,0xbf,0xca,0xae,0x47,0xf1,0x70,0x79,0xad,0xb7,0xca,0x34,0x88,0x4d,0x60,0xad,0xb7,0x4a,0x14,0xf,0x97,0x81,0x75,0xc0,0xa4,0x9b,0xeb,0x1c,0x70,0xa1,0xd3,0xee,0x3e,0x6d,0x35,0x67,0xcf,0x5,0x41,0x50,0x29,0xae,0x31,0xc6,0x46,0xf1,0xf0,0xc3,0x60,0xb3,0x7f,0x13,0x78,0x7,0x6c,0x48,0x6e,0x85,0xeb,0x0,0x27,0x80,0x23,0x40,0x73,0xc2,0xf2,0x1d,0x3,0x3f,0x81,0x6f,0x7e,0x8f,0x36,0x52,0x12,0x34,0x4c,0xf7,0xc1,0x9,0x55,0xa8,0x2f,0x39,0xd9,0xa7,0xf0,0xe3,0xf6,0x17,0x4c,0x97,0x1d,0x24,0x5b,0x8,0x8b,0x95,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + +static const unsigned char graph_port_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xa,0x0,0x0,0x0,0xa,0x8,0x6,0x0,0x0,0x0,0x8d,0x32,0xcf,0xbd,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x0,0x0,0x0,0x0,0x0,0xf9,0x43,0xbb,0x7f,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,0xde,0xc,0x14,0x17,0x20,0x3,0xeb,0x8f,0x3a,0xdb,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x65,0x49,0x44,0x41,0x54,0x18,0xd3,0x4d,0xd0,0x4f,0x6b,0xda,0x70,0x1c,0x7,0xe0,0xcf,0x37,0x7f,0x7e,0x49,0x66,0xd2,0x64,0x61,0x5,0x61,0x76,0x47,0xf1,0xa4,0x2d,0xdb,0x75,0x5,0x11,0x84,0xb0,0x5e,0xeb,0xd9,0xeb,0xf4,0x6d,0xec,0x2d,0xf8,0x26,0xb6,0x77,0xe0,0x45,0xba,0xa3,0x6c,0xa0,0x3b,0xad,0x39,0xb6,0x36,0x8,0x1b,0x4b,0x32,0xd2,0xc6,0x6c,0x9a,0x4f,0x4f,0x85,0x3e,0x2f,0xe1,0x11,0x0,0x20,0x29,0xd3,0xe9,0xd4,0xda,0x6e,0xb7,0x23,0xdf,0xf7,0xbb,0x0,0x90,0xe7,0xf9,0x8f,0x66,0xb3,0xf9,0x79,0x36,0x9b,0x55,0x22,0x42,0x83,0xa4,0x44,0x51,0xf4,0xea,0xe2,0xe2,0xc3,0xf7,0xf1,0x78,0xdc,0xa,0x82,0x40,0x8,0x20,0xcf,0x32,0x2e,0x97,0xcb,0x4f,0x51,0x14,0xbd,0x25,0xf9,0x5b,0x26,0x93,0x89,0xdd,0xe9,0x74,0xe2,0xf7,0xe7,0xe7,0x27,0x59,0xfa,0x87,0x65,0xb9,0x13,0x0,0xb0,0x1d,0x9b,0xe1,0xcb,0x50,0xbe,0x5e,0x5d,0xdd,0xfe,0xbc,0xbe,0x6e,0x6b,0x49,0x92,0x8c,0x4e,0x7b,0xa7,0xad,0xbf,0x79,0x4e,0xd3,0x54,0x12,0x86,0x21,0xc2,0x30,0x84,0x32,0x95,0xe4,0x79,0xc6,0xde,0xd9,0x59,0x2b,0x49,0xee,0x46,0x86,0xeb,0xba,0x5d,0xfb,0x85,0x23,0x87,0xfd,0x1e,0xb6,0xed,0x40,0xd7,0x35,0x0,0x40,0x7d,0x38,0xa0,0xdc,0xed,0x44,0x37,0x74,0xb8,0xae,0xd7,0x35,0x48,0x62,0xff,0xff,0x1f,0xfc,0x20,0x80,0xae,0xe9,0x78,0x42,0x0,0xca,0xb2,0x90,0x65,0x19,0x58,0xd7,0xd0,0x8a,0xa2,0x58,0xa7,0x69,0x56,0x6b,0xa2,0x51,0x29,0x5,0xcb,0x52,0xb0,0x94,0x5,0x4b,0x29,0x88,0x8,0xd3,0x34,0xad,0x8b,0xfb,0x62,0xad,0xf,0x6,0x83,0xb8,0xaa,0xaa,0xb1,0xe7,0x79,0xbe,0x77,0x74,0x44,0xb7,0xe1,0x89,0x69,0x1a,0x28,0xcb,0x92,0x9b,0xcd,0x46,0x56,0xab,0xd5,0x86,0xe4,0x47,0x21,0x29,0xc3,0xe1,0xf0,0xb8,0xdf,0xef,0x7f,0x6b,0xb7,0xdb,0xaf,0x1b,0x8d,0x86,0x46,0x10,0xf,0xf7,0xf,0x75,0x1c,0xc7,0x77,0x8b,0xc5,0xe2,0xdd,0x7c,0x3e,0xff,0x25,0xcf,0xc3,0x6f,0x6e,0x6f,0x2e,0x1d,0xdb,0xe9,0x9,0x80,0xb2,0x2a,0xd7,0x27,0xad,0x37,0x5f,0x9e,0xc2,0x1f,0x1,0x3a,0xe6,0xa5,0x7b,0xef,0xf2,0xf3,0xcd,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + static const unsigned char hscroll_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,0x6,0x62,0x4b,0x47,0x44,0x0,0x49,0x0,0x42,0x0,0x4e,0x4e,0xda,0xb4,0x7e,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,0x1b,0x12,0x30,0x1c,0x3c,0x99,0xa,0x1c,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x53,0x49,0x44,0x41,0x54,0x18,0xd3,0x7d,0x8f,0xc9,0xd,0x80,0x20,0x0,0xc0,0xca,0x21,0xe8,0x5f,0x12,0x89,0x84,0xfd,0x5c,0x48,0x26,0x34,0x3e,0x74,0x2,0xa2,0xe8,0x2,0x40,0xbf,0xed,0xa7,0xc2,0xbb,0xb0,0x3,0x1b,0x75,0x92,0xf0,0x2e,0x7c,0x46,0x9b,0xaa,0xcd,0x4f,0x46,0x3,0x8c,0x76,0xea,0x7,0x4a,0x29,0x5a,0x68,0x0,0x29,0x65,0x3f,0x30,0x83,0xed,0x6,0xe9,0xbc,0x8e,0xf6,0x45,0x79,0xb,0xc0,0x5c,0xb3,0xeb,0x12,0xef,0x1f,0xc6,0x6f,0x12,0x2,0xa,0xbd,0xc9,0x5d,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 2c278f4fed..e3427cbe2c 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -458,6 +458,8 @@ FixedMaterial::~FixedMaterial() { } + + bool ShaderMaterial::_set(const StringName& p_name, const Variant& p_value) { if (p_name==SceneStringNames::get_singleton()->shader_shader) { @@ -558,7 +560,21 @@ void ShaderMaterial::_bind_methods() { } +void ShaderMaterial::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const { + + String f = p_function.operator String(); + if ((f=="get_shader_param" || f=="set_shader_param") && p_idx==0) { + if (shader.is_valid()) { + List<PropertyInfo> pl; + shader->get_param_list(&pl); + for (List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) { + r_options->push_back(E->get().name); + } + } + } + Material::get_argument_options(p_function,p_idx,r_options); +} ShaderMaterial::ShaderMaterial() :Material(VisualServer::get_singleton()->material_create()){ diff --git a/scene/resources/material.h b/scene/resources/material.h index 9c3feede08..2b10078e16 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -243,6 +243,7 @@ public: void set_shader_param(const StringName& p_param,const Variant& p_value); Variant get_shader_param(const StringName& p_param) const; + void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const; ShaderMaterial(); }; diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp index afb0ae1815..9f691d6ad3 100644 --- a/scene/resources/polygon_path_finder.cpp +++ b/scene/resources/polygon_path_finder.cpp @@ -142,6 +142,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2& p_from, const Vector if (d<closest_dist) { ignore_from_edge=E->get(); closest_dist=d; + closest_point=closest; } } @@ -168,6 +169,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2& p_from, const Vector if (d<closest_dist) { ignore_to_edge=E->get(); closest_dist=d; + closest_point=closest; } } @@ -529,7 +531,7 @@ Vector2 PolygonPathFinder::get_closest_point(const Vector2& p_point) const { float d = p_point.distance_squared_to(points[i].pos); if (d<closest_dist) { - d=closest_dist; + closest_dist=d; closest_idx=i; } diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 6d65da3782..cc6bed3148 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -120,6 +120,13 @@ Dictionary Shader::_get_code() { c["vertex_ofs"]=0; c["light"]=ls; c["light_ofs"]=0; + Array arr; + for(const Map<StringName,Ref<Texture> >::Element *E=default_textures.front();E;E=E->next()) { + arr.push_back(E->key()); + arr.push_back(E->get()); + } + if (arr.size()) + c["default_tex"]=arr; return c; } @@ -132,8 +139,41 @@ void Shader::_set_code(const Dictionary& p_string) { light=p_string["light"]; set_code(p_string["vertex"],p_string["fragment"],light); + if (p_string.has("default_tex")) { + Array arr=p_string["default_tex"]; + if ((arr.size()&1)==0) { + for(int i=0;i<arr.size();i+=2) + set_default_texture_param(arr[i],arr[i+1]); + } + } +} + +void Shader::set_default_texture_param(const StringName& p_param,const Ref<Texture>& p_texture) { + + if (p_texture.is_valid()) + default_textures[p_param]=p_texture; + else + default_textures.erase(p_param); +} + +Ref<Texture> Shader::get_default_texture_param(const StringName& p_param) const{ + + if (default_textures.has(p_param)) + return default_textures[p_param]; + else + return Ref<Texture>(); } +void Shader::get_default_texture_param_list(List<StringName>* r_textures) const{ + + for(const Map<StringName,Ref<Texture> >::Element *E=default_textures.front();E;E=E->next()) { + + r_textures->push_back(E->key()); + } + +} + + void Shader::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_mode","mode"),&Shader::set_mode); @@ -144,6 +184,9 @@ void Shader::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_fragment_code"),&Shader::get_fragment_code); ObjectTypeDB::bind_method(_MD("get_light_code"),&Shader::get_light_code); + ObjectTypeDB::bind_method(_MD("set_default_texture_param","param","texture:Texture"),&Shader::set_default_texture_param); + ObjectTypeDB::bind_method(_MD("get_default_texture_param:Texture","param"),&Shader::get_default_texture_param); + ObjectTypeDB::bind_method(_MD("has_param","name"),&Shader::has_param); ObjectTypeDB::bind_method(_MD("_set_code","code"),&Shader::_set_code); diff --git a/scene/resources/shader.h b/scene/resources/shader.h index fff6f1d28a..e1b8288c51 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -31,7 +31,7 @@ #include "resource.h" #include "io/resource_loader.h" - +#include "scene/resources/texture.h" class Shader : public Resource { OBJ_TYPE(Shader,Resource); @@ -48,6 +48,7 @@ class Shader : public Resource { // convertion fast and save memory. mutable bool params_cache_dirty; mutable Map<StringName,StringName> params_cache; //map a shader param to a material param.. + Map<StringName,Ref<Texture> > default_textures; protected: @@ -72,6 +73,10 @@ public: void get_param_list(List<PropertyInfo> *p_params) const; bool has_param(const StringName& p_param) const; + void set_default_texture_param(const StringName& p_param, const Ref<Texture> &p_texture); + Ref<Texture> get_default_texture_param(const StringName& p_param) const; + void get_default_texture_param_list(List<StringName>* r_textures) const; + virtual RID get_rid() const; Shader(); |