diff options
Diffstat (limited to 'scene/animation')
| -rw-r--r-- | scene/animation/SCsub | 2 | ||||
| -rw-r--r-- | scene/animation/animation_cache.cpp | 2 | ||||
| -rw-r--r-- | scene/animation/animation_cache.h | 2 | ||||
| -rw-r--r-- | scene/animation/animation_player.cpp | 43 | ||||
| -rw-r--r-- | scene/animation/animation_player.h | 5 | ||||
| -rw-r--r-- | scene/animation/animation_tree_player.cpp | 107 | ||||
| -rw-r--r-- | scene/animation/animation_tree_player.h | 21 | ||||
| -rw-r--r-- | scene/animation/transitioner.cpp | 2 | ||||
| -rw-r--r-- | scene/animation/transitioner.h | 2 | ||||
| -rw-r--r-- | scene/animation/tween.cpp | 500 | ||||
| -rw-r--r-- | scene/animation/tween.h | 78 | ||||
| -rw-r--r-- | scene/animation/tween_interpolaters.cpp | 14 |
12 files changed, 628 insertions, 150 deletions
diff --git a/scene/animation/SCsub b/scene/animation/SCsub index 055d2f2474..bbe59b3054 100644 --- a/scene/animation/SCsub +++ b/scene/animation/SCsub @@ -3,5 +3,3 @@ Import('env') env.add_source_files(env.scene_sources,"*.cpp") Export('env') - - diff --git a/scene/animation/animation_cache.cpp b/scene/animation/animation_cache.cpp index 46eb8d7e88..b1d6da7294 100644 --- a/scene/animation/animation_cache.cpp +++ b/scene/animation/animation_cache.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_cache.h b/scene/animation/animation_cache.h index d00b122faa..e94530d924 100644 --- a/scene/animation/animation_cache.h +++ b/scene/animation/animation_cache.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index f9d36138a2..c2ea1c8bb6 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,10 +35,10 @@ bool AnimationPlayer::_set(const StringName& p_name, const Variant& p_value) { String name=p_name; - if (name=="playback/speed" || name=="speed") { //bw compatibility + if (p_name==SceneStringNames::get_singleton()->playback_speed || p_name==SceneStringNames::get_singleton()->speed) { //bw compatibility set_speed(p_value); - } else if (name=="playback/active") { + } else if (p_name==SceneStringNames::get_singleton()->playback_active) { set_active(p_value); } else if (name.begins_with("playback/play")) { @@ -52,16 +52,16 @@ bool AnimationPlayer::_set(const StringName& p_name, const Variant& p_value) { } else if (name.begins_with("anims/")) { - String which=name.get_slice("/",1); + String which=name.get_slicec('/',1); add_animation(which,p_value); } else if (name.begins_with("next/")) { - String which=name.get_slice("/",1); + String which=name.get_slicec('/',1); animation_set_next(which,p_value); - } else if (name=="blend_times") { + } else if (p_name==SceneStringNames::get_singleton()->blend_times) { Array array=p_value; int len = array.size(); @@ -77,7 +77,7 @@ bool AnimationPlayer::_set(const StringName& p_name, const Variant& p_value) { set_blend_time(from,to,time); } - } else if (name=="autoplay") { + } else if (p_name==SceneStringNames::get_singleton()->autoplay) { autoplay=p_value; } else @@ -106,12 +106,12 @@ bool AnimationPlayer::_get(const StringName& p_name,Variant &r_ret) const { } else if (name.begins_with("anims/")) { - String which=name.get_slice("/",1); + String which=name.get_slicec('/',1); r_ret= get_animation(which).get_ref_ptr(); } else if (name.begins_with("next/")) { - String which=name.get_slice("/",1); + String which=name.get_slicec('/',1); r_ret= animation_get_next(which); @@ -223,7 +223,7 @@ void AnimationPlayer::_notification(int p_what) { } break; case NOTIFICATION_EXIT_TREE: { - stop_all(); + //stop_all(); clear_caches(); } break; } @@ -295,7 +295,7 @@ void AnimationPlayer::_generate_node_caches(AnimationData* p_anim) { p_anim->node_cache[i]->bone_idx=p_anim->node_cache[i]->skeleton->find_bone(bone_name); if (p_anim->node_cache[i]->bone_idx<0) { - // broken track (unexisting bone) + // broken track (nonexistent bone) p_anim->node_cache[i]->skeleton=NULL; p_anim->node_cache[i]->spatial=NULL; printf("bone is %ls\n", String(bone_name).c_str()); @@ -661,8 +661,11 @@ void AnimationPlayer::_animation_process(float p_delta) { Error AnimationPlayer::add_animation(const StringName& p_name, const Ref<Animation>& p_animation) { +#ifdef DEBUG_ENABLED ERR_EXPLAIN("Invalid animation name: "+String(p_name)); ERR_FAIL_COND_V( String(p_name).find("/")!=-1 || String(p_name).find(":")!=-1 || String(p_name).find(",")!=-1 || String(p_name).find("[")!=-1, ERR_INVALID_PARAMETER ); +#endif + ERR_FAIL_COND_V( p_animation.is_null() , ERR_INVALID_PARAMETER ); //print_line("Add anim: "+String(p_name)+" name: "+p_animation->get_name()); @@ -854,6 +857,11 @@ void AnimationPlayer::clear_queue() { queued.clear(); }; +void AnimationPlayer::play_backwards(const StringName& p_name,float p_custom_blend) { + + play(p_name,p_custom_blend,-1,true); +} + void AnimationPlayer::play(const StringName& p_name, float p_custom_blend, float p_custom_scale,bool p_from_end) { //printf("animation is %ls\n", String(p_name).c_str()); @@ -967,14 +975,16 @@ String AnimationPlayer::get_current_animation() const { } -void AnimationPlayer::stop() { +void AnimationPlayer::stop(bool p_reset) { Playback &c=playback; c.blend.clear(); - c.current.from=NULL; + if (p_reset) { + c.current.from=NULL; + } _set_process(false); queued.clear(); - playing = false; + playing = false; } void AnimationPlayer::stop_all() { @@ -1211,7 +1221,8 @@ void AnimationPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_default_blend_time"),&AnimationPlayer::get_default_blend_time); ObjectTypeDB::bind_method(_MD("play","name","custom_blend","custom_speed","from_end"),&AnimationPlayer::play,DEFVAL(""),DEFVAL(-1),DEFVAL(1.0),DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("stop"),&AnimationPlayer::stop); + ObjectTypeDB::bind_method(_MD("play_backwards","name","custom_blend"),&AnimationPlayer::play_backwards,DEFVAL(""),DEFVAL(-1)); + ObjectTypeDB::bind_method(_MD("stop","reset"),&AnimationPlayer::stop,DEFVAL(true)); ObjectTypeDB::bind_method(_MD("stop_all"),&AnimationPlayer::stop_all); ObjectTypeDB::bind_method(_MD("is_playing"),&AnimationPlayer::is_playing); ObjectTypeDB::bind_method(_MD("set_current_animation","anim"),&AnimationPlayer::set_current_animation); @@ -1269,7 +1280,7 @@ AnimationPlayer::AnimationPlayer() { animation_process_mode=ANIMATION_PROCESS_IDLE; processing=false; default_blend_time=0; - root=NodePath(".."); + root=SceneStringNames::get_singleton()->path_pp; playing = false; active=true; } diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 8ac5d96bf3..1e3c37c4d6 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -258,9 +258,10 @@ public: float get_default_blend_time() const; void play(const StringName& p_name=StringName(),float p_custom_blend=-1,float p_custom_scale=1.0,bool p_from_end=false); + void play_backwards(const StringName& p_name=StringName(),float p_custom_blend=-1); void queue(const StringName& p_name); void clear_queue(); - void stop(); + void stop(bool p_reset=true); bool is_playing() const; String get_current_animation() const; void set_current_animation(const String& p_anim); diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index ec72123c98..c7e259c3c6 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,6 +29,42 @@ #include "animation_tree_player.h" #include "animation_player.h" +#include "scene/scene_string_names.h" + + +void AnimationTreePlayer::set_animation_process_mode(AnimationProcessMode p_mode) { + + if (animation_process_mode == p_mode) + return; + + bool pr = processing; + if (pr) + _set_process(false); + animation_process_mode = p_mode; + if (pr) + _set_process(true); + +} + +AnimationTreePlayer::AnimationProcessMode AnimationTreePlayer::get_animation_process_mode() const{ + + return animation_process_mode; +} + +void AnimationTreePlayer::_set_process(bool p_process, bool p_force) +{ + if (processing == p_process && !p_force) + return; + + switch (animation_process_mode) { + + case ANIMATION_PROCESS_FIXED: set_fixed_process(p_process && active); break; + case ANIMATION_PROCESS_IDLE: set_process(p_process && active); break; + } + + processing = p_process; +} + bool AnimationTreePlayer::_set(const StringName& p_name, const Variant& p_value) { @@ -42,6 +78,11 @@ bool AnimationTreePlayer::_set(const StringName& p_name, const Variant& p_value) return true; } + if(String(p_name) == SceneStringNames::get_singleton()->playback_active) { + set_active(p_value); + return true; + } + if (String(p_name)!="data") return false; @@ -83,7 +124,8 @@ bool AnimationTreePlayer::_set(const StringName& p_name, const Variant& p_value) ERR_FAIL_COND_V(nt==NODE_MAX,false); - add_node(nt,id); + if (nt!=NODE_OUTPUT) + add_node(nt,id); node_set_pos(id,pos); @@ -189,6 +231,11 @@ bool AnimationTreePlayer::_get(const StringName& p_name,Variant &r_ret) const { return true; } + if (String(p_name) == "playback/active") { + r_ret=is_active(); + return true; + } + if (String(p_name)!="data") return false; @@ -341,11 +388,24 @@ void AnimationTreePlayer::_get_property_list( List<PropertyInfo> *p_list) const p_list->push_back( PropertyInfo(Variant::DICTIONARY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_NETWORK) ); } +void AnimationTreePlayer::advance(float p_time) { + + _process_animation(p_time); +} void AnimationTreePlayer::_notification(int p_what) { switch(p_what) { + case NOTIFICATION_ENTER_TREE: { + + if (!processing) { + //make sure that a previous process state was not saved + //only process if "processing" is set + set_fixed_process(false); + set_process(false); + } + } break; case NOTIFICATION_READY: { dirty_caches=true; if (master!=NodePath()) { @@ -353,7 +413,19 @@ void AnimationTreePlayer::_notification(int p_what) { } } break; case NOTIFICATION_PROCESS: { - _process_animation(); + if (animation_process_mode==ANIMATION_PROCESS_FIXED) + break; + + if (processing) + _process_animation( get_process_delta_time() ); + } break; + case NOTIFICATION_FIXED_PROCESS: { + + if (animation_process_mode==ANIMATION_PROCESS_IDLE) + break; + + if (processing) + _process_animation(get_fixed_process_delta_time()); } break; } @@ -655,10 +727,7 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode } -void AnimationTreePlayer::_process_animation() { - - if (!active) - return; +void AnimationTreePlayer::_process_animation(float p_delta) { if (last_error!=CONNECT_OK) return; @@ -674,7 +743,7 @@ void AnimationTreePlayer::_process_animation() { _process_node(out_name,&prev, 1.0, 0, true ); reset_request=false; } else - _process_node(out_name,&prev, 1.0, get_process_delta_time(), false ); + _process_node(out_name,&prev, 1.0, p_delta, false ); if (dirty_caches) { //some animation changed.. ignore this pass @@ -1519,8 +1588,12 @@ void AnimationTreePlayer::recompute_caches() { void AnimationTreePlayer::set_active(bool p_active) { - active=p_active; - set_process(active); + if (active == p_active) + return; + + active = p_active; + processing = active; + _set_process(processing, true); } bool AnimationTreePlayer::is_active() const { @@ -1737,12 +1810,23 @@ void AnimationTreePlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_base_path","path"),&AnimationTreePlayer::set_base_path); ObjectTypeDB::bind_method(_MD("get_base_path"),&AnimationTreePlayer::get_base_path); + ObjectTypeDB::bind_method(_MD("set_master_player","nodepath"),&AnimationTreePlayer::set_master_player); + ObjectTypeDB::bind_method(_MD("get_master_player"),&AnimationTreePlayer::get_master_player); + ObjectTypeDB::bind_method(_MD("get_node_list"),&AnimationTreePlayer::_get_node_list); + ObjectTypeDB::bind_method(_MD("set_animation_process_mode","mode"),&AnimationTreePlayer::set_animation_process_mode); + ObjectTypeDB::bind_method(_MD("get_animation_process_mode"),&AnimationTreePlayer::get_animation_process_mode); + + ObjectTypeDB::bind_method(_MD("advance", "delta"), &AnimationTreePlayer::advance); + + ObjectTypeDB::bind_method(_MD("reset"),&AnimationTreePlayer::reset); ObjectTypeDB::bind_method(_MD("recompute_caches"),&AnimationTreePlayer::recompute_caches); + ADD_PROPERTY(PropertyInfo(Variant::INT, "playback/process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_animation_process_mode"), _SCS("get_animation_process_mode")); + BIND_CONSTANT( NODE_OUTPUT ); BIND_CONSTANT( NODE_ANIMATION ); BIND_CONSTANT( NODE_ONESHOT ); @@ -1763,6 +1847,9 @@ AnimationTreePlayer::AnimationTreePlayer() { out_name="out"; out->pos=Point2(40,40); node_map.insert( out_name , out); + AnimationProcessMode animation_process_mode; + animation_process_mode = ANIMATION_PROCESS_IDLE; + processing = false; active=false; dirty_caches=true; reset_request=false; diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h index 135e5f414e..9ea5ccf330 100644 --- a/scene/animation/animation_tree_player.h +++ b/scene/animation/animation_tree_player.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,6 +34,7 @@ #include "scene/3d/spatial.h" #include "scene/3d/skeleton.h" #include "scene/main/misc.h" +#include "animation_player.h" class AnimationTreePlayer : public Node { @@ -42,7 +43,10 @@ class AnimationTreePlayer : public Node { OBJ_CATEGORY("Animation Nodes"); public: - + enum AnimationProcessMode { + ANIMATION_PROCESS_FIXED, + ANIMATION_PROCESS_IDLE, + }; enum NodeType { @@ -256,13 +260,15 @@ private: ConnectError last_error; AnimationNode *active_list; + AnimationProcessMode animation_process_mode; + bool processing; bool active; bool dirty_caches; Map<StringName,NodeBase*> node_map; // return time left to finish animation float _process_node(const StringName& p_node,AnimationNode **r_prev_anim, float p_weight,float p_step, bool p_seek=false,const HashMap<NodePath,bool> *p_filter=NULL, float p_reverse_weight=0); - void _process_animation(); + void _process_animation(float p_delta); bool reset_request; ConnectError _cycle_test(const StringName &p_at_node); @@ -409,12 +415,21 @@ public: ConnectError get_last_error() const; + void set_animation_process_mode(AnimationProcessMode p_mode); + AnimationProcessMode get_animation_process_mode() const; + + void _set_process(bool p_process, bool p_force = false); + + void advance(float p_time); + AnimationTreePlayer(); ~AnimationTreePlayer(); }; VARIANT_ENUM_CAST( AnimationTreePlayer::NodeType ); +VARIANT_ENUM_CAST( AnimationTreePlayer::AnimationProcessMode ); + #endif // ANIMATION_TREE_PLAYER_H diff --git a/scene/animation/transitioner.cpp b/scene/animation/transitioner.cpp index 990f55f9cb..d210f29db0 100644 --- a/scene/animation/transitioner.cpp +++ b/scene/animation/transitioner.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/transitioner.h b/scene/animation/transitioner.h index 3cff5e6d49..dba83cddd8 100644 --- a/scene/animation/transitioner.h +++ b/scene/animation/transitioner.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 59793815f5..73d93e50ec 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,6 +29,81 @@ #include "tween.h" #include "method_bind_ext.inc" +void Tween::_add_pending_command(StringName p_key + ,const Variant& p_arg1 ,const Variant& p_arg2 ,const Variant& p_arg3 ,const Variant& p_arg4 ,const Variant& p_arg5 + ,const Variant& p_arg6 ,const Variant& p_arg7 ,const Variant& p_arg8 ,const Variant& p_arg9 ,const Variant& p_arg10 +) { + + pending_commands.push_back(PendingCommand()); + PendingCommand& cmd = pending_commands.back()->get(); + + cmd.key = p_key; + int& count = cmd.args; + if(p_arg10.get_type() != Variant::NIL) + count = 10; + else if(p_arg9.get_type() != Variant::NIL) + count = 9; + else if(p_arg8.get_type() != Variant::NIL) + count = 8; + else if(p_arg7.get_type() != Variant::NIL) + count = 7; + else if(p_arg6.get_type() != Variant::NIL) + count = 6; + else if(p_arg5.get_type() != Variant::NIL) + count = 5; + else if(p_arg4.get_type() != Variant::NIL) + count = 4; + else if(p_arg3.get_type() != Variant::NIL) + count = 3; + else if(p_arg2.get_type() != Variant::NIL) + count = 2; + else if(p_arg1.get_type() != Variant::NIL) + count = 1; + if(count > 0) + cmd.arg[0] = p_arg1; + if(count > 1) + cmd.arg[1] = p_arg2; + if(count > 2) + cmd.arg[2] = p_arg3; + if(count > 3) + cmd.arg[3] = p_arg4; + if(count > 4) + cmd.arg[4] = p_arg5; + if(count > 5) + cmd.arg[5] = p_arg6; + if(count > 6) + cmd.arg[6] = p_arg7; + if(count > 7) + cmd.arg[7] = p_arg8; + if(count > 8) + cmd.arg[8] = p_arg9; + if(count > 9) + cmd.arg[9] = p_arg10; +} + +void Tween::_process_pending_commands() { + + for(List<PendingCommand>::Element *E=pending_commands.front();E;E=E->next()) { + + PendingCommand& cmd = E->get(); + Variant::CallError err; + Variant *arg[10] = { + &cmd.arg[0], + &cmd.arg[1], + &cmd.arg[2], + &cmd.arg[3], + &cmd.arg[4], + &cmd.arg[5], + &cmd.arg[6], + &cmd.arg[7], + &cmd.arg[8], + &cmd.arg[9], + }; + this->call(cmd.key, (const Variant **) arg, cmd.args, err); + } + pending_commands.clear(); +} + bool Tween::_set(const StringName& p_name, const Variant& p_value) { String name=p_name; @@ -124,32 +199,35 @@ 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","arg1", "arg2","arg3","arg4","arg5"),&Tween::interpolate_callback, DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()) ); + ObjectTypeDB::bind_method(_MD("interpolate_deferred_callback","object","times_in_sec","callback","arg1","arg2","arg3","arg4","arg5"),&Tween::interpolate_deferred_callback, DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), 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 +259,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 +291,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 +342,11 @@ Variant Tween::_run_equation(InterpolateData& p_data) { switch(initial_val.get_type()) { + + case Variant::BOOL: + result = ( _run_equation(p_data.trans_type, p_data.ease_type, p_data.elapsed - p_data.delay, initial_val, 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 +492,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) { @@ -448,10 +531,13 @@ bool Tween::_apply_tween_value(InterpolateData& p_data, Variant& value) { void Tween::_tween_process(float p_delta) { + _process_pending_commands(); + if (speed_scale == 0) return; p_delta *= speed_scale; + pending_update ++; // if repeat and all interpolates was finished then reset all interpolates if(repeat) { bool all_finished = true; @@ -476,7 +562,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; @@ -505,11 +591,33 @@ void Tween::_tween_process(float p_delta) { if(data.finish) { Variant::CallError error; - if (data.arg.get_type() != Variant::NIL) { - Variant *arg[1] = { &data.arg }; - object->call(data.key, (const Variant **) arg, 1, error); - } else { - object->call(data.key, NULL, 0, error); + if (data.call_deferred) { + + switch (data.args) { + case 0: + object->call_deferred(data.key); break; + case 1: + object->call_deferred(data.key, data.arg[0]); break; + case 2: + object->call_deferred(data.key, data.arg[0], data.arg[1]); break; + case 3: + object->call_deferred(data.key, data.arg[0], data.arg[1], data.arg[2]); break; + case 4: + object->call_deferred(data.key, data.arg[0], data.arg[1], data.arg[2], data.arg[3]); break; + case 5: + object->call_deferred(data.key, data.arg[0], data.arg[1], data.arg[2], data.arg[3], data.arg[4]); break; + } + + } + else { + Variant *arg[5] = { + &data.arg[0], + &data.arg[1], + &data.arg[2], + &data.arg[3], + &data.arg[4], + }; + object->call(data.key, (const Variant **) arg, data.args, error); } } continue; @@ -520,9 +628,14 @@ void Tween::_tween_process(float p_delta) { _apply_tween_value(data, result); - if(data.finish) + if (data.finish) { emit_signal("tween_complete",object,data.key); + // not repeat mode, remove completed action + if (!repeat) + call_deferred("remove", object, data.key); + } } + pending_update --; } void Tween::set_tween_process_mode(TweenProcessMode p_mode) { @@ -598,16 +711,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 +729,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 +744,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 +769,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 +803,29 @@ 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) { + if(pending_update != 0) { + call_deferred("remove", p_object, p_key); + return true; + } for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) { InterpolateData& data = E->get(); - 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 +835,10 @@ bool Tween::remove(Node *p_node, String p_key) { bool Tween::remove_all() { + if(pending_update != 0) { + call_deferred("remove_all"); + return true; + } set_active(false); _set_process(false); interpolates.clear(); @@ -714,6 +847,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 +878,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 +892,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 +907,7 @@ real_t Tween::get_runtime() const { if(t > runtime) runtime = t; } + pending_update --; return runtime; } @@ -779,6 +918,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 +1018,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 +1027,24 @@ bool Tween::interpolate_property(Node *p_node , EaseType p_ease_type , real_t p_delay ) { + if(pending_update != 0) { + _add_pending_command("interpolate_property" + , p_object + , p_property + , p_initial_val + , p_final_val + , p_times_in_sec + , p_trans_type + , p_ease_type + , p_delay + ); + return true; + } // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); - 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 +1052,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 +1061,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 +1077,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 +1086,32 @@ bool Tween::interpolate_method(Node *p_node , EaseType p_ease_type , real_t p_delay ) { + if(pending_update != 0) { + _add_pending_command("interpolate_method" + , p_object + , p_method + , p_initial_val + , p_final_val + , p_times_in_sec + , p_trans_type + , p_ease_type + , p_delay + ); + return true; + } // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); - 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_EXPLAIN("Object has no method named: %s" + p_method); + ERR_FAIL_COND_V(!p_object->has_method(p_method), false); InterpolateData data; data.active = true; @@ -947,7 +1119,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,47 +1135,162 @@ bool Tween::interpolate_method(Node *p_node return true; } -bool Tween::interpolate_callback(Node *p_node +bool Tween::interpolate_callback(Object *p_object + , real_t p_times_in_sec , String p_callback + , VARIANT_ARG_DECLARE +) { + + if(pending_update != 0) { + _add_pending_command("interpolate_callback" + , p_object + , p_times_in_sec + , p_callback + , p_arg1 + , p_arg2 + , p_arg3 + , p_arg4 + , p_arg5 + ); + return true; + } + ERR_FAIL_COND_V(p_object == NULL, false); + ERR_FAIL_COND_V(p_times_in_sec < 0, false); + + ERR_EXPLAIN("Object has no callback named: %s" + p_callback); + ERR_FAIL_COND_V(!p_object->has_method(p_callback), false); + + InterpolateData data; + data.active = true; + data.type = INTER_CALLBACK; + data.finish = false; + data.call_deferred = false; + data.elapsed = 0; + + data.id = p_object->get_instance_ID(); + data.key = p_callback; + data.times_in_sec = p_times_in_sec; + data.delay = 0; + + int args=0; + if (p_arg5.get_type()!=Variant::NIL) + args=5; + else if (p_arg4.get_type()!=Variant::NIL) + args=4; + else if (p_arg3.get_type()!=Variant::NIL) + args=3; + else if (p_arg2.get_type()!=Variant::NIL) + args=2; + else if (p_arg1.get_type()!=Variant::NIL) + args=1; + else + args=0; + + data.args = args; + data.arg[0] = p_arg1; + data.arg[1] = p_arg2; + data.arg[2] = p_arg3; + data.arg[3] = p_arg4; + data.arg[4] = p_arg5; + + pending_update ++; + interpolates.push_back(data); + pending_update --; + return true; +} + +bool Tween::interpolate_deferred_callback(Object *p_object , real_t p_times_in_sec - , Variant p_arg + , String p_callback + , VARIANT_ARG_DECLARE ) { - ERR_FAIL_COND_V(p_node == NULL, false); + if(pending_update != 0) { + _add_pending_command("interpolate_deferred_callback" + , p_object + , p_times_in_sec + , p_callback + , p_arg1 + , p_arg2 + , p_arg3 + , p_arg4 + , p_arg5 + ); + return true; + } + ERR_FAIL_COND_V(p_object == NULL, false); ERR_FAIL_COND_V(p_times_in_sec < 0, false); - ERR_FAIL_COND_V(!p_node->has_method(p_callback), false); + ERR_EXPLAIN("Object has no callback named: %s" + p_callback); + ERR_FAIL_COND_V(!p_object->has_method(p_callback), false); InterpolateData data; data.active = true; data.type = INTER_CALLBACK; data.finish = false; + data.call_deferred = true; 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; + int args=0; + if (p_arg5.get_type()!=Variant::NIL) + args=5; + else if (p_arg4.get_type()!=Variant::NIL) + args=4; + else if (p_arg3.get_type()!=Variant::NIL) + args=3; + else if (p_arg2.get_type()!=Variant::NIL) + args=2; + else if (p_arg1.get_type()!=Variant::NIL) + args=1; + else + args=0; + + data.args = args; + data.arg[0] = p_arg1; + data.arg[1] = p_arg2; + data.arg[2] = p_arg3; + data.arg[3] = p_arg4; + data.arg[4] = p_arg5; + + 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 ) { + if(pending_update != 0) { + _add_pending_command("follow_property" + , p_object + , p_property + , p_initial_val + , p_target + , p_target_property + , p_times_in_sec + , p_trans_type + , p_ease_type + , p_delay + ); + return true; + } // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); - 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 +1298,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 +1315,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 +1329,43 @@ 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 ) { + if(pending_update != 0) { + _add_pending_command("follow_method" + , p_object + , p_method + , p_initial_val + , p_target + , p_target_method + , p_times_in_sec + , p_trans_type + , p_ease_type + , p_delay + ); + return true; + } // convert INT to REAL is better for interpolaters if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); - 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_EXPLAIN("Object has no method named: %s" + p_method); + ERR_FAIL_COND_V(!p_object->has_method(p_method), false); + ERR_EXPLAIN("Target has no method named: %s" + p_target_method); ERR_FAIL_COND_V(!p_target->has_method(p_target_method), false); Variant::CallError error; @@ -1079,10 +1382,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 +1396,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 +1406,24 @@ bool Tween::targeting_property(Node *p_node , EaseType p_ease_type , real_t p_delay ) { + if(pending_update != 0) { + _add_pending_command("targeting_property" + , p_object + , p_property + , p_initial + , p_initial_property + , p_final_val + , p_times_in_sec + , p_trans_type + , p_ease_type + , p_delay + ); + return true; + } // convert INT to REAL is better for interpolaters if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); - 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 +1431,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 +1448,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 +1467,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 +1477,33 @@ bool Tween::targeting_method(Node *p_node , EaseType p_ease_type , real_t p_delay ) { + if(pending_update != 0) { + _add_pending_command("targeting_method" + , p_object + , p_method + , p_initial + , p_initial_method + , p_final_val + , p_times_in_sec + , p_trans_type + , p_ease_type + , p_delay + ); + return true; + } // convert INT to REAL is better for interpolaters if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); - 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_EXPLAIN("Object has no method named: %s" + p_method); + ERR_FAIL_COND_V(!p_object->has_method(p_method), false); + ERR_EXPLAIN("Initial Object has no method named: %s" + p_initial_method); ERR_FAIL_COND_V(!p_initial->has_method(p_initial_method), false); Variant::CallError error; @@ -1187,9 +1520,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 +1546,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..d504c63d8a 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -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: @@ -81,19 +83,21 @@ private: bool active; InterpolateType type; bool finish; + bool call_deferred; 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; EaseType ease_type; real_t delay; - Variant arg; + int args; + Variant arg[5]; }; String autoplay; @@ -102,9 +106,31 @@ private: bool active; bool repeat; float speed_scale; + mutable int pending_update; List<InterpolateData> interpolates; + struct PendingCommand { + StringName key; + int args; + Variant arg[10]; + }; + List<PendingCommand> pending_commands; + + void _add_pending_command(StringName p_key + ,const Variant& p_arg1=Variant() + ,const Variant& p_arg2=Variant() + ,const Variant& p_arg3=Variant() + ,const Variant& p_arg4=Variant() + ,const Variant& p_arg5=Variant() + ,const Variant& p_arg6=Variant() + ,const Variant& p_arg7=Variant() + ,const Variant& p_arg8=Variant() + ,const Variant& p_arg9=Variant() + ,const Variant& p_arg10=Variant() + ); + void _process_pending_commands(); + typedef real_t (*interpolater)(real_t t, real_t b, real_t c, real_t d); static interpolater interpolaters[TRANS_COUNT][EASE_COUNT]; @@ -142,20 +168,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 +191,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 +201,22 @@ public: , real_t p_delay = 0 ); - bool interpolate_callback(Node *p_node + bool interpolate_callback(Object *p_object + , real_t p_times_in_sec , String p_callback + , VARIANT_ARG_DECLARE + ); + + bool interpolate_deferred_callback(Object *p_object , real_t p_times_in_sec - , Variant p_arg = Variant() + , String p_callback + , VARIANT_ARG_DECLARE ); - 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 +224,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 +235,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 +246,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/animation/tween_interpolaters.cpp b/scene/animation/tween_interpolaters.cpp index 7d0f2cd4e0..9128d220de 100644 --- a/scene/animation/tween_interpolaters.cpp +++ b/scene/animation/tween_interpolaters.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -285,18 +285,18 @@ namespace cubic { namespace circ { static real_t in(real_t t, real_t b, real_t c, real_t d) { - return -c * (sqrt(1 - (t /= d) * t) - 1) + b; + return -c * (sqrt(1 - (t /= d) * t) - 1) + b; // TODO: ehrich: operation with t is undefined } static real_t out(real_t t, real_t b, real_t c, real_t d) { - return c * sqrt(1 - (t = t / d - 1) * t) + b; + return c * sqrt(1 - (t = t / d - 1) * t) + b; // TODO: ehrich: operation with t is undefined } static real_t in_out(real_t t, real_t b, real_t c, real_t d) { if ((t /= d / 2) < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b; - return c / 2 * (sqrt(1 - t * (t -= 2)) + 1) + b; + return c / 2 * (sqrt(1 - t * (t -= 2)) + 1) + b; // TODO: ehrich: operation with t is undefined } static real_t out_in(real_t t, real_t b, real_t c, real_t d) @@ -364,15 +364,15 @@ namespace back { static real_t out(real_t t, real_t b, real_t c, real_t d) { float s = 1.70158f; - return c * ((t = t / d- 1) * t * ((s + 1) * t + s) + 1) + b; + return c * ((t = t / d- 1) * t * ((s + 1) * t + s) + 1) + b; // TODO: ehrich: operation with t is undefined } static real_t in_out(real_t t, real_t b, real_t c, real_t d) { float s = 1.70158f; - if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525f)) + 1) * t - s)) + b; + if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525f)) + 1) * t - s)) + b; // TODO: ehrich: operation with s is undefined float postFix = t -= 2; - return c / 2 * ((postFix) * t * (((s *= (1.525f)) + 1) * t + s) + 2) + b; + return c / 2 * ((postFix) * t * (((s *= (1.525f)) + 1) * t + s) + 2) + b; // TODO: ehrich: operation with s is undefined } static real_t out_in(real_t t, real_t b, real_t c, real_t d) |