summaryrefslogtreecommitdiff
path: root/scene/animation
diff options
context:
space:
mode:
Diffstat (limited to 'scene/animation')
-rw-r--r--scene/animation/SCsub2
-rw-r--r--scene/animation/animation_cache.cpp2
-rw-r--r--scene/animation/animation_cache.h2
-rw-r--r--scene/animation/animation_player.cpp43
-rw-r--r--scene/animation/animation_player.h5
-rw-r--r--scene/animation/animation_tree_player.cpp107
-rw-r--r--scene/animation/animation_tree_player.h21
-rw-r--r--scene/animation/transitioner.cpp2
-rw-r--r--scene/animation/transitioner.h2
-rw-r--r--scene/animation/tween.cpp500
-rw-r--r--scene/animation/tween.h78
-rw-r--r--scene/animation/tween_interpolaters.cpp14
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)