summaryrefslogtreecommitdiff
path: root/scene/animation
diff options
context:
space:
mode:
Diffstat (limited to 'scene/animation')
-rw-r--r--scene/animation/animation_blend_tree.cpp15
-rw-r--r--scene/animation/animation_player.cpp3
-rw-r--r--scene/animation/animation_tree.cpp2
-rw-r--r--scene/animation/tween.cpp46
-rw-r--r--scene/animation/tween.h10
5 files changed, 48 insertions, 28 deletions
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index d11387902a..af186072ac 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -248,27 +248,26 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek) {
if (fade_in > 0) {
blend = time / fade_in;
} else {
- blend = 0; //wtf
+ blend = 0;
}
-
- } else if (!do_start && remaining < fade_out) {
- if (fade_out) {
+ } else if (!do_start && remaining <= fade_out) {
+ if (fade_out > 0) {
blend = (remaining / fade_out);
} else {
- blend = 1.0;
+ blend = 0;
}
} else {
blend = 1.0;
}
- float main_rem;
+ double main_rem;
if (mix == MIX_MODE_ADD) {
main_rem = blend_input(0, p_time, p_seek, 1.0, FILTER_IGNORE, !sync);
} else {
main_rem = blend_input(0, p_time, p_seek, 1.0 - blend, FILTER_BLEND, !sync);
}
- float os_rem = blend_input(1, os_seek ? time : p_time, os_seek, blend, FILTER_PASS, false);
+ double os_rem = blend_input(1, os_seek ? time : p_time, os_seek, blend, FILTER_PASS, false);
if (do_start) {
remaining = os_rem;
@@ -718,7 +717,7 @@ double AnimationNodeTransition::process(double p_time, bool p_seek) {
} else { // cross-fading from prev to current
- float blend = xfade ? (prev_xfading / xfade) : 1;
+ float blend = xfade == 0 ? 0 : (prev_xfading / xfade);
if (!p_seek && switched) { //just switched, seek to start of current
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index f6091f224c..5825a35030 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -737,7 +737,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (anim->has_loop()) {
at_anim_pos = Math::fposmod(p_time - pos, (double)anim->get_length()); //seek to loop
} else {
- at_anim_pos = MAX((double)anim->get_length(), p_time - pos); //seek to end
+ at_anim_pos = MIN((double)anim->get_length(), p_time - pos); //seek to end
}
if (player->is_playing() || p_seeked) {
@@ -765,6 +765,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
}
} else {
player->play(anim_name);
+ player->seek(0.0, true);
nc->animation_playing = true;
playing_caches.insert(nc);
}
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 88fb960164..9ca8d478b1 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -958,7 +958,7 @@ void AnimationTree::_process_graph(real_t p_delta) {
Variant::interpolate(t->value, value, blend, t->value);
- } else if (delta != 0) {
+ } else {
List<int> indices;
a->value_track_get_key_indices(i, time, delta, &indices);
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 542011618d..2847031375 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -36,6 +36,10 @@ void Tweener::set_tween(Ref<Tween> p_tween) {
tween = p_tween;
}
+void Tweener::clear_tween() {
+ tween.unref();
+}
+
void Tweener::_bind_methods() {
ADD_SIGNAL(MethodInfo("finished"));
}
@@ -53,16 +57,21 @@ void Tween::start_tweeners() {
Ref<PropertyTweener> Tween::tween_property(Object *p_target, NodePath p_property, Variant p_to, float p_duration) {
ERR_FAIL_NULL_V(p_target, nullptr);
- ERR_FAIL_COND_V_MSG(invalid, nullptr, "Tween was created outside the scene tree, can't use Tweeners.");
+ ERR_FAIL_COND_V_MSG(!valid, nullptr, "Tween invalid. Either finished or created outside scene tree.");
ERR_FAIL_COND_V_MSG(started, nullptr, "Can't append to a Tween that has started. Use stop() first.");
+#ifdef DEBUG_ENABLED
+ Variant::Type property_type = p_target->get_indexed(p_property.get_as_property_path().get_subnames()).get_type();
+ ERR_FAIL_COND_V_MSG(property_type != p_to.get_type(), Ref<PropertyTweener>(), "Type mismatch between property and final value: " + Variant::get_type_name(property_type) + " and " + Variant::get_type_name(p_to.get_type()));
+#endif
+
Ref<PropertyTweener> tweener = memnew(PropertyTweener(p_target, p_property, p_to, p_duration));
append(tweener);
return tweener;
}
Ref<IntervalTweener> Tween::tween_interval(float p_time) {
- ERR_FAIL_COND_V_MSG(invalid, nullptr, "Tween was created outside the scene tree, can't use Tweeners.");
+ ERR_FAIL_COND_V_MSG(!valid, nullptr, "Tween invalid. Either finished or created outside scene tree.");
ERR_FAIL_COND_V_MSG(started, nullptr, "Can't append to a Tween that has started. Use stop() first.");
Ref<IntervalTweener> tweener = memnew(IntervalTweener(p_time));
@@ -71,7 +80,7 @@ Ref<IntervalTweener> Tween::tween_interval(float p_time) {
}
Ref<CallbackTweener> Tween::tween_callback(Callable p_callback) {
- ERR_FAIL_COND_V_MSG(invalid, nullptr, "Tween was created outside the scene tree, can't use Tweeners.");
+ ERR_FAIL_COND_V_MSG(!valid, nullptr, "Tween invalid. Either finished or created outside scene tree.");
ERR_FAIL_COND_V_MSG(started, nullptr, "Can't append to a Tween that has started. Use stop() first.");
Ref<CallbackTweener> tweener = memnew(CallbackTweener(p_callback));
@@ -79,8 +88,8 @@ Ref<CallbackTweener> Tween::tween_callback(Callable p_callback) {
return tweener;
}
-Ref<MethodTweener> Tween::tween_method(Callable p_callback, float p_from, float p_to, float p_duration) {
- ERR_FAIL_COND_V_MSG(invalid, nullptr, "Tween was created outside the scene tree, can't use Tweeners.");
+Ref<MethodTweener> Tween::tween_method(Callable p_callback, Variant p_from, Variant p_to, float p_duration) {
+ ERR_FAIL_COND_V_MSG(!valid, nullptr, "Tween invalid. Either finished or created outside scene tree.");
ERR_FAIL_COND_V_MSG(started, nullptr, "Can't append to a Tween that has started. Use stop() first.");
Ref<MethodTweener> tweener = memnew(MethodTweener(p_callback, p_from, p_to, p_duration));
@@ -88,9 +97,7 @@ Ref<MethodTweener> Tween::tween_method(Callable p_callback, float p_from, float
return tweener;
}
-Ref<Tween> Tween::append(Ref<Tweener> p_tweener) {
- ERR_FAIL_COND_V_MSG(invalid, nullptr, "Tween was created outside the scene tree, can't use Tweeners.");
- ERR_FAIL_COND_V_MSG(started, nullptr, "Can't append to a Tween that has started. Use stop() first.");
+void Tween::append(Ref<Tweener> p_tweener) {
p_tweener->set_tween(this);
if (parallel_enabled) {
@@ -102,8 +109,6 @@ Ref<Tween> Tween::append(Ref<Tweener> p_tweener) {
tweeners.resize(current_step + 1);
tweeners.write[current_step].push_back(p_tweener);
-
- return this;
}
void Tween::stop() {
@@ -117,7 +122,7 @@ void Tween::pause() {
}
void Tween::play() {
- ERR_FAIL_COND_MSG(invalid, "Tween invalid, can't play.");
+ ERR_FAIL_COND_MSG(!valid, "Tween invalid. Either finished or created outside scene tree.");
ERR_FAIL_COND_MSG(dead, "Can't play finished Tween, use stop() first to reset its state.");
running = true;
}
@@ -132,11 +137,22 @@ bool Tween::is_running() {
}
void Tween::set_valid(bool p_valid) {
- invalid = !p_valid;
+ valid = p_valid;
}
bool Tween::is_valid() {
- return invalid;
+ return valid;
+}
+
+void Tween::clear() {
+ valid = false;
+
+ for (List<Ref<Tweener>> &step : tweeners) {
+ for (Ref<Tweener> &tweener : step) {
+ tweener->clear_tween();
+ }
+ }
+ tweeners.clear();
}
Ref<Tween> Tween::bind_node(Node *p_node) {
@@ -485,6 +501,8 @@ Variant Tween::interpolate_variant(Variant p_initial_val, Variant p_delta_val, f
}
Variant Tween::calculate_delta_value(Variant p_intial_val, Variant p_final_val) {
+ ERR_FAIL_COND_V_MSG(p_intial_val.get_type() != p_final_val.get_type(), p_intial_val, "Type mismatch between initial and final value: " + Variant::get_type_name(p_intial_val.get_type()) + " and " + Variant::get_type_name(p_final_val.get_type()));
+
switch (p_intial_val.get_type()) {
case Variant::BOOL: {
return (int)p_final_val - (int)p_intial_val;
@@ -877,7 +895,7 @@ void MethodTweener::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_ease", "ease"), &MethodTweener::set_ease);
}
-MethodTweener::MethodTweener(Callable p_callback, float p_from, float p_to, float p_duration) {
+MethodTweener::MethodTweener(Callable p_callback, Variant p_from, Variant p_to, float p_duration) {
callback = p_callback;
initial_val = p_from;
delta_val = tween->calculate_delta_value(p_from, p_to);
diff --git a/scene/animation/tween.h b/scene/animation/tween.h
index 947cdb7c2d..6a48d332b8 100644
--- a/scene/animation/tween.h
+++ b/scene/animation/tween.h
@@ -43,6 +43,7 @@ public:
virtual void set_tween(Ref<Tween> p_tween);
virtual void start() = 0;
virtual bool step(float &r_delta) = 0;
+ void clear_tween();
protected:
static void _bind_methods();
@@ -111,7 +112,7 @@ private:
bool started = false;
bool running = true;
bool dead = false;
- bool invalid = true;
+ bool valid = false;
bool default_parallel = false;
bool parallel_enabled = false;
@@ -127,8 +128,8 @@ public:
Ref<PropertyTweener> tween_property(Object *p_target, NodePath p_property, Variant p_to, float p_duration);
Ref<IntervalTweener> tween_interval(float p_time);
Ref<CallbackTweener> tween_callback(Callable p_callback);
- Ref<MethodTweener> tween_method(Callable p_callback, float p_from, float p_to, float p_duration);
- Ref<Tween> append(Ref<Tweener> p_tweener);
+ Ref<MethodTweener> tween_method(Callable p_callback, Variant p_from, Variant p_to, float p_duration);
+ void append(Ref<Tweener> p_tweener);
bool custom_step(float p_delta);
void stop();
@@ -139,6 +140,7 @@ public:
bool is_running();
void set_valid(bool p_valid);
bool is_valid();
+ void clear();
Ref<Tween> bind_node(Node *p_node);
Ref<Tween> set_process_mode(TweenProcessMode p_mode);
@@ -256,7 +258,7 @@ public:
void start() override;
bool step(float &r_delta) override;
- MethodTweener(Callable p_callback, float p_from, float p_to, float p_duration);
+ MethodTweener(Callable p_callback, Variant p_from, Variant p_to, float p_duration);
MethodTweener();
protected: