summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2021-10-11 19:28:34 -0300
committerGitHub <noreply@github.com>2021-10-11 19:28:34 -0300
commitf9aec342dcd51d65c5970dd395e3c7a66cac446c (patch)
tree9d5b542652e576f865abf0c97a37ee272210ae2e /scene
parent9ed4f8367b29204b89f9feaf86727b24396fb180 (diff)
parent610de0974db4feb7e50c9349a8a164b6bf0f36c8 (diff)
Merge pull request #53687 from godotengine/revert-48332-implement-ping-pong
Revert "Implement reverse playback and ping-pong loop in AnimationPlayer and NodeAnimation"
Diffstat (limited to 'scene')
-rw-r--r--scene/animation/animation_blend_space_2d.cpp7
-rw-r--r--scene/animation/animation_blend_tree.cpp79
-rw-r--r--scene/animation/animation_blend_tree.h26
-rw-r--r--scene/animation/animation_player.cpp135
-rw-r--r--scene/animation/animation_player.h2
-rw-r--r--scene/animation/animation_tree.cpp131
-rw-r--r--scene/animation/animation_tree.h4
-rw-r--r--scene/resources/animation.cpp539
-rw-r--r--scene/resources/animation.h30
-rw-r--r--scene/resources/audio_stream_sample.cpp6
-rw-r--r--scene/resources/audio_stream_sample.h2
11 files changed, 300 insertions, 661 deletions
diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp
index 6c71be8363..145e7c605b 100644
--- a/scene/animation/animation_blend_space_2d.cpp
+++ b/scene/animation/animation_blend_space_2d.cpp
@@ -30,7 +30,6 @@
#include "animation_blend_space_2d.h"
-#include "animation_blend_tree.h"
#include "core/math/geometry_2d.h"
void AnimationNodeBlendSpace2D::get_parameter_list(List<PropertyInfo> *r_list) const {
@@ -532,12 +531,6 @@ double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek) {
if (new_closest != closest && new_closest != -1) {
float from = 0.0;
if (blend_mode == BLEND_MODE_DISCRETE_CARRY && closest != -1) {
- //for ping-pong loop
- Ref<AnimationNodeAnimation> na_c = static_cast<Ref<AnimationNodeAnimation>>(blend_points[closest].node);
- Ref<AnimationNodeAnimation> na_n = static_cast<Ref<AnimationNodeAnimation>>(blend_points[new_closest].node);
- if (!na_c.is_null() && !na_n.is_null()) {
- na_n->set_backward(na_c->is_backward());
- }
//see how much animation remains
from = length_internal - blend_node(blend_points[closest].name, blend_points[closest].node, p_time, false, 0.0, FILTER_IGNORE, false);
}
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 98830bd796..10a66386eb 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -30,7 +30,6 @@
#include "animation_blend_tree.h"
-#include "scene/resources/animation.h"
#include "scene/scene_string_names.h"
void AnimationNodeAnimation::set_animation(const StringName &p_name) {
@@ -84,55 +83,30 @@ double AnimationNodeAnimation::process(double p_time, bool p_seek) {
}
Ref<Animation> anim = ap->get_animation(animation);
- double anim_size = (double)anim->get_length();
- double step = 0.0;
- double prev_time = time;
- int pingponged = 0;
- bool current_backward = signbit(p_time);
+
+ double step;
if (p_seek) {
- step = p_time - time;
time = p_time;
+ step = 0;
} else {
- p_time *= backward ? -1.0 : 1.0;
- if (!(time == anim_size && !current_backward) && !(time == 0 && current_backward)) {
- time = time + p_time;
- step = p_time;
- }
+ time = MAX(0, time + p_time);
+ step = p_time;
}
- if (anim->get_loop_mode() == Animation::LoopMode::LOOP_PINGPONG) {
+ double anim_size = anim->get_length();
+
+ if (anim->has_loop()) {
if (anim_size) {
- if ((int)Math::floor(abs(time - prev_time) / anim_size) % 2 == 0) {
- if (prev_time > 0 && time <= 0) {
- backward = !backward;
- pingponged = -1;
- }
- if (prev_time < anim_size && time >= anim_size) {
- backward = !backward;
- pingponged = 1;
- }
- }
- time = Math::pingpong(time, anim_size);
+ time = Math::fposmod(time, anim_size);
}
- } else {
- if (anim->get_loop_mode() == Animation::LoopMode::LOOP_LINEAR) {
- if (anim_size) {
- time = Math::fposmod(time, anim_size);
- }
- } else if (time < 0) {
- time = 0;
- } else if (time > anim_size) {
- time = anim_size;
- }
- backward = false;
- }
- if (play_mode == PLAY_MODE_FORWARD) {
- blend_animation(animation, time, step, p_seek, 1.0, pingponged);
- } else {
- blend_animation(animation, anim_size - time, -step, p_seek, 1.0, pingponged);
+ } else if (time > anim_size) {
+ time = anim_size;
}
+
+ blend_animation(animation, time, step, p_seek, 1.0);
+
set_parameter(this->time, time);
return anim_size - time;
@@ -142,34 +116,11 @@ String AnimationNodeAnimation::get_caption() const {
return "Animation";
}
-void AnimationNodeAnimation::set_play_mode(PlayMode p_play_mode) {
- play_mode = p_play_mode;
-}
-
-AnimationNodeAnimation::PlayMode AnimationNodeAnimation::get_play_mode() const {
- return play_mode;
-}
-
-void AnimationNodeAnimation::set_backward(bool p_backward) {
- backward = p_backward;
-}
-
-bool AnimationNodeAnimation::is_backward() const {
- return backward;
-}
-
void AnimationNodeAnimation::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_animation", "name"), &AnimationNodeAnimation::set_animation);
ClassDB::bind_method(D_METHOD("get_animation"), &AnimationNodeAnimation::get_animation);
- ClassDB::bind_method(D_METHOD("set_play_mode", "mode"), &AnimationNodeAnimation::set_play_mode);
- ClassDB::bind_method(D_METHOD("get_play_mode"), &AnimationNodeAnimation::get_play_mode);
-
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "play_mode", PROPERTY_HINT_ENUM, "Forward,Backward"), "set_play_mode", "get_play_mode");
-
- BIND_ENUM_CONSTANT(PLAY_MODE_FORWARD);
- BIND_ENUM_CONSTANT(PLAY_MODE_BACKWARD);
}
AnimationNodeAnimation::AnimationNodeAnimation() {
@@ -582,7 +533,7 @@ AnimationNodeBlend3::AnimationNodeBlend3() {
/////////////////////////////////
void AnimationNodeTimeScale::get_parameter_list(List<PropertyInfo> *r_list) const {
- r_list->push_back(PropertyInfo(Variant::FLOAT, scale, PROPERTY_HINT_RANGE, "-32,32,0.01,or_lesser,or_greater"));
+ r_list->push_back(PropertyInfo(Variant::FLOAT, scale, PROPERTY_HINT_RANGE, "0,32,0.01,or_greater"));
}
Variant AnimationNodeTimeScale::get_parameter_default_value(const StringName &p_parameter) const {
diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h
index e55dfb58ed..258443a999 100644
--- a/scene/animation/animation_blend_tree.h
+++ b/scene/animation/animation_blend_tree.h
@@ -42,12 +42,12 @@ class AnimationNodeAnimation : public AnimationRootNode {
uint64_t last_version = 0;
bool skip = false;
-public:
- enum PlayMode {
- PLAY_MODE_FORWARD,
- PLAY_MODE_BACKWARD
- };
+protected:
+ void _validate_property(PropertyInfo &property) const override;
+ static void _bind_methods();
+
+public:
void get_parameter_list(List<PropertyInfo> *r_list) const override;
static Vector<String> (*get_editable_animation_list)();
@@ -58,25 +58,9 @@ public:
void set_animation(const StringName &p_name);
StringName get_animation() const;
- void set_play_mode(PlayMode p_play_mode);
- PlayMode get_play_mode() const;
-
- void set_backward(bool p_backward);
- bool is_backward() const;
-
AnimationNodeAnimation();
-
-protected:
- void _validate_property(PropertyInfo &property) const override;
- static void _bind_methods();
-
-private:
- PlayMode play_mode = PLAY_MODE_FORWARD;
- bool backward = false;
};
-VARIANT_ENUM_CAST(AnimationNodeAnimation::PlayMode)
-
class AnimationNodeOneShot : public AnimationNode {
GDCLASS(AnimationNodeOneShot, AnimationNode);
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 8fd1602e8b..2c8c4ee788 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -340,13 +340,12 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
}
}
-void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started, int p_pingponged) {
+void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started) {
_ensure_node_caches(p_anim);
ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count());
Animation *a = p_anim->animation.operator->();
bool can_call = is_inside_tree() && !Engine::get_singleton()->is_editor_hint();
- bool backward = signbit(p_delta);
for (int i = 0; i < a->get_track_count(); i++) {
// If an animation changes this animation (or it animates itself)
@@ -426,8 +425,8 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
continue; //eeh not worth it
}
- double first_key_time = a->track_get_key_time(i, 0);
- double transition = 1.0;
+ float first_key_time = a->track_get_key_time(i, 0);
+ float transition = 1.0;
int first_key = 0;
if (first_key_time == 0.0) {
@@ -435,13 +434,13 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (key_count == 1) {
continue; //with one key we can't do anything
}
- transition = (double)a->track_get_key_transition(i, 0);
+ transition = a->track_get_key_transition(i, 0);
first_key_time = a->track_get_key_time(i, 1);
first_key = 1;
}
if (p_time < first_key_time) {
- double c = Math::ease(p_time / first_key_time, transition);
+ float c = Math::ease(p_time / first_key_time, transition);
Variant first_value = a->track_get_key_value(i, first_key);
Variant interp_value;
Variant::interpolate(pa->capture, first_value, c, interp_value);
@@ -483,7 +482,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
} else if (p_is_current && p_delta != 0) {
List<int> indices;
- a->value_track_get_key_indices(i, p_time, p_delta, &indices, p_pingponged);
+ a->value_track_get_key_indices(i, p_time, p_delta, &indices);
for (int &F : indices) {
Variant value = a->track_get_key_value(i, F);
@@ -542,7 +541,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
List<int> indices;
- a->method_track_get_key_indices(i, p_time, p_delta, &indices, p_pingponged);
+ a->method_track_get_key_indices(i, p_time, p_delta, &indices);
for (int &E : indices) {
StringName method = a->method_track_get_name(i, E);
@@ -597,7 +596,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
TrackNodeCache::BezierAnim *ba = &E->get();
- real_t bezier = a->bezier_track_interpolate(i, p_time);
+ float bezier = a->bezier_track_interpolate(i, p_time);
if (ba->accum_pass != accum_pass) {
ERR_CONTINUE(cache_update_bezier_size >= NODE_CACHE_UPDATE_MAX);
cache_update_bezier[cache_update_bezier_size++] = ba;
@@ -658,7 +657,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
} else {
//find stuff to play
List<int> to_play;
- a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_pingponged);
+ a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play);
if (to_play.size()) {
int idx = to_play.back()->get();
@@ -686,14 +685,12 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
nc->audio_start = p_time;
}
} else if (nc->audio_playing) {
- bool loop = a->get_loop_mode() != Animation::LoopMode::LOOP_NONE;
+ bool loop = a->has_loop();
bool stop = false;
- if (!loop) {
- if ((p_time < nc->audio_start && !backward) || (p_time > nc->audio_start && backward)) {
- stop = true;
- }
+ if (!loop && p_time < nc->audio_start) {
+ stop = true;
} else if (nc->audio_len > 0) {
float len = nc->audio_start > p_time ? (a->get_length() - nc->audio_start) + p_time : p_time - nc->audio_start;
@@ -734,23 +731,12 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
Ref<Animation> anim = player->get_animation(anim_name);
- double at_anim_pos = 0.0;
-
- switch (anim->get_loop_mode()) {
- case Animation::LoopMode::LOOP_NONE: {
- at_anim_pos = MIN((double)anim->get_length(), p_time - pos); //seek to end
- } break;
-
- case Animation::LoopMode::LOOP_LINEAR: {
- at_anim_pos = Math::fposmod(p_time - pos, (double)anim->get_length()); //seek to loop
- } break;
+ double at_anim_pos;
- case Animation::LoopMode::LOOP_PINGPONG: {
- at_anim_pos = Math::pingpong(p_time - pos, (double)anim->get_length());
- } break;
-
- default:
- break;
+ if (anim->has_loop()) {
+ at_anim_pos = Math::fposmod(p_time - pos, (double)anim->get_length()); //seek to loop
+ } else {
+ at_anim_pos = MIN((double)anim->get_length(), p_time - pos); //seek to end
}
if (player->is_playing() || p_seeked) {
@@ -765,7 +751,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
} else {
//find stuff to play
List<int> to_play;
- a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_pingponged);
+ a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play);
if (to_play.size()) {
int idx = to_play.back()->get();
@@ -795,73 +781,46 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, double p_delta,
double next_pos = cd.pos + delta;
real_t len = cd.from->animation->get_length();
- int pingponged = 0;
-
- switch (cd.from->animation->get_loop_mode()) {
- case Animation::LoopMode::LOOP_NONE: {
- if (next_pos < 0) {
- next_pos = 0;
- } else if (next_pos > len) {
- next_pos = len;
- }
+ bool loop = cd.from->animation->has_loop();
- bool backwards = signbit(delta); // Negative zero means playing backwards too
- delta = next_pos - cd.pos; // Fix delta (after determination of backwards because negative zero is lost here)
+ if (!loop) {
+ if (next_pos < 0) {
+ next_pos = 0;
+ } else if (next_pos > len) {
+ next_pos = len;
+ }
- if (&cd == &playback.current) {
- if (!backwards && cd.pos <= len && next_pos == len) {
- //playback finished
- end_reached = true;
- end_notify = cd.pos < len; // Notify only if not already at the end
- }
+ bool backwards = signbit(delta); // Negative zero means playing backwards too
+ delta = next_pos - cd.pos; // Fix delta (after determination of backwards because negative zero is lost here)
- if (backwards && cd.pos >= 0 && next_pos == 0) {
- //playback finished
- end_reached = true;
- end_notify = cd.pos > 0; // Notify only if not already at the beginning
- }
+ if (&cd == &playback.current) {
+ if (!backwards && cd.pos <= len && next_pos == len) {
+ //playback finished
+ end_reached = true;
+ end_notify = cd.pos < len; // Notify only if not already at the end
}
- } break;
- case Animation::LoopMode::LOOP_LINEAR: {
- double looped_next_pos = Math::fposmod(next_pos, (double)len);
- if (looped_next_pos == 0 && next_pos != 0) {
- // Loop multiples of the length to it, rather than 0
- // so state at time=length is previewable in the editor
- next_pos = len;
- } else {
- next_pos = looped_next_pos;
+ if (backwards && cd.pos >= 0 && next_pos == 0) {
+ //playback finished
+ end_reached = true;
+ end_notify = cd.pos > 0; // Notify only if not already at the beginning
}
- } break;
-
- case Animation::LoopMode::LOOP_PINGPONG: {
- if ((int)Math::floor(abs(next_pos - cd.pos) / len) % 2 == 0) {
- if (next_pos < 0 && cd.pos >= 0) {
- cd.speed_scale *= -1.0;
- pingponged = -1;
- }
- if (next_pos > len && cd.pos <= len) {
- cd.speed_scale *= -1.0;
- pingponged = 1;
- }
- }
- double looped_next_pos = Math::pingpong(next_pos, (double)len);
- if (looped_next_pos == 0 && next_pos != 0) {
- // Loop multiples of the length to it, rather than 0
- // so state at time=length is previewable in the editor
- next_pos = len;
- } else {
- next_pos = looped_next_pos;
- }
- } break;
+ }
- default:
- break;
+ } else {
+ double looped_next_pos = Math::fposmod(next_pos, (double)len);
+ if (looped_next_pos == 0 && next_pos != 0) {
+ // Loop multiples of the length to it, rather than 0
+ // so state at time=length is previewable in the editor
+ next_pos = len;
+ } else {
+ next_pos = looped_next_pos;
+ }
}
cd.pos = next_pos;
- _animation_process_animation(cd.from, cd.pos, delta, p_blend, &cd == &playback.current, p_seeked, p_started, pingponged);
+ _animation_process_animation(cd.from, cd.pos, delta, p_blend, &cd == &playback.current, p_seeked, p_started);
}
void AnimationPlayer::_animation_process2(double p_delta, bool p_started) {
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index df041de026..b693e29bdf 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -215,7 +215,7 @@ private:
NodePath root;
- void _animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current = true, bool p_seeked = false, bool p_started = false, int p_pingponged = 0);
+ void _animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current = true, bool p_seeked = false, bool p_started = false);
void _ensure_node_caches(AnimationData *p_anim, Node *p_root_override = nullptr);
void _animation_process_data(PlaybackData &cd, double p_delta, float p_blend, bool p_seeked, bool p_started);
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 7ea42e6df2..9ca8d478b1 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -32,7 +32,6 @@
#include "animation_blend_tree.h"
#include "core/config/engine.h"
-#include "scene/resources/animation.h"
#include "scene/scene_string_names.h"
#include "servers/audio/audio_stream.h"
@@ -88,7 +87,7 @@ void AnimationNode::get_child_nodes(List<ChildNode> *r_child_nodes) {
}
}
-void AnimationNode::blend_animation(const StringName &p_animation, real_t p_time, real_t p_delta, bool p_seeked, real_t p_blend, int p_pingponged) {
+void AnimationNode::blend_animation(const StringName &p_animation, real_t p_time, real_t p_delta, bool p_seeked, real_t p_blend) {
ERR_FAIL_COND(!state);
ERR_FAIL_COND(!state->player->has_animation(p_animation));
@@ -114,7 +113,6 @@ void AnimationNode::blend_animation(const StringName &p_animation, real_t p_time
anim_state.time = p_time;
anim_state.animation = animation;
anim_state.seeked = p_seeked;
- anim_state.pingponged = p_pingponged;
state->animation_states.push_back(anim_state);
}
@@ -420,7 +418,7 @@ void AnimationNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_filters", "filters"), &AnimationNode::_set_filters);
ClassDB::bind_method(D_METHOD("_get_filters"), &AnimationNode::_get_filters);
- ClassDB::bind_method(D_METHOD("blend_animation", "animation", "time", "delta", "seeked", "blend", "pingponged"), &AnimationNode::blend_animation, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("blend_animation", "animation", "time", "delta", "seeked", "blend"), &AnimationNode::blend_animation);
ClassDB::bind_method(D_METHOD("blend_node", "name", "node", "time", "seek", "blend", "filter", "optimize"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true));
ClassDB::bind_method(D_METHOD("blend_input", "input_index", "time", "seek", "blend", "filter", "optimize"), &AnimationNode::blend_input, DEFVAL(FILTER_IGNORE), DEFVAL(true));
@@ -826,8 +824,6 @@ void AnimationTree::_process_graph(real_t p_delta) {
double delta = as.delta;
real_t weight = as.blend;
bool seeked = as.seeked;
- int pingponged = as.pingponged;
- bool backward = signbit(delta);
for (int i = 0; i < a->get_track_count(); i++) {
NodePath path = a->track_get_path(i);
@@ -866,38 +862,12 @@ void AnimationTree::_process_graph(real_t p_delta) {
t->scale = Vector3(1, 1, 1);
}
- double prev_time = time - delta;
- if (!backward) {
- if (prev_time < 0) {
- switch (a->get_loop_mode()) {
- case Animation::LoopMode::LOOP_NONE: {
- prev_time = 0;
- } break;
- case Animation::LoopMode::LOOP_LINEAR: {
- prev_time = Math::fposmod(prev_time, (double)a->get_length());
- } break;
- case Animation::LoopMode::LOOP_PINGPONG: {
- prev_time = Math::pingpong(prev_time, (double)a->get_length());
- } break;
- default:
- break;
- }
- }
- } else {
- if (prev_time > a->get_length()) {
- switch (a->get_loop_mode()) {
- case Animation::LoopMode::LOOP_NONE: {
- prev_time = (double)a->get_length();
- } break;
- case Animation::LoopMode::LOOP_LINEAR: {
- prev_time = Math::fposmod(prev_time, (double)a->get_length());
- } break;
- case Animation::LoopMode::LOOP_PINGPONG: {
- prev_time = Math::pingpong(prev_time, (double)a->get_length());
- } break;
- default:
- break;
- }
+ real_t prev_time = time - delta;
+ if (prev_time < 0) {
+ if (!a->has_loop()) {
+ prev_time = 0;
+ } else {
+ prev_time = a->get_length() + prev_time;
}
}
@@ -905,38 +875,20 @@ void AnimationTree::_process_graph(real_t p_delta) {
Quaternion rot[2];
Vector3 scale[2];
- if (!backward) {
- if (prev_time > time) {
- Error err = a->transform_track_interpolate(i, prev_time, &loc[0], &rot[0], &scale[0]);
- if (err != OK) {
- continue;
- }
-
- a->transform_track_interpolate(i, (double)a->get_length(), &loc[1], &rot[1], &scale[1]);
-
- t->loc += (loc[1] - loc[0]) * blend;
- t->scale += (scale[1] - scale[0]) * blend;
- Quaternion q = Quaternion().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
- t->rot = (t->rot * q).normalized();
-
- prev_time = 0;
+ if (prev_time > time) {
+ Error err = a->transform_track_interpolate(i, prev_time, &loc[0], &rot[0], &scale[0]);
+ if (err != OK) {
+ continue;
}
- } else {
- if (prev_time < time) {
- Error err = a->transform_track_interpolate(i, prev_time, &loc[0], &rot[0], &scale[0]);
- if (err != OK) {
- continue;
- }
- a->transform_track_interpolate(i, 0, &loc[1], &rot[1], &scale[1]);
+ a->transform_track_interpolate(i, a->get_length(), &loc[1], &rot[1], &scale[1]);
- t->loc += (loc[1] - loc[0]) * blend;
- t->scale += (scale[1] - scale[0]) * blend;
- Quaternion q = Quaternion().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
- t->rot = (t->rot * q).normalized();
+ t->loc += (loc[1] - loc[0]) * blend;
+ t->scale += (scale[1] - scale[0]) * blend;
+ Quaternion q = Quaternion().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
+ t->rot = (t->rot * q).normalized();
- prev_time = 0;
- }
+ prev_time = 0;
}
Error err = a->transform_track_interpolate(i, prev_time, &loc[0], &rot[0], &scale[0]);
@@ -951,7 +903,8 @@ void AnimationTree::_process_graph(real_t p_delta) {
Quaternion q = Quaternion().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
t->rot = (t->rot * q).normalized();
- prev_time = !backward ? 0 : (double)a->get_length();
+ prev_time = 0;
+
} else {
Vector3 loc;
Quaternion rot;
@@ -1007,7 +960,7 @@ void AnimationTree::_process_graph(real_t p_delta) {
} else {
List<int> indices;
- a->value_track_get_key_indices(i, time, delta, &indices, pingponged);
+ a->value_track_get_key_indices(i, time, delta, &indices);
for (int &F : indices) {
Variant value = a->track_get_key_value(i, F);
@@ -1024,7 +977,7 @@ void AnimationTree::_process_graph(real_t p_delta) {
List<int> indices;
- a->method_track_get_key_indices(i, time, delta, &indices, pingponged);
+ a->method_track_get_key_indices(i, time, delta, &indices);
for (int &F : indices) {
StringName method = a->method_track_get_name(i, F);
@@ -1107,7 +1060,7 @@ void AnimationTree::_process_graph(real_t p_delta) {
} else {
//find stuff to play
List<int> to_play;
- a->track_get_key_indices_in_range(i, time, delta, &to_play, pingponged);
+ a->track_get_key_indices_in_range(i, time, delta, &to_play);
if (to_play.size()) {
int idx = to_play.back()->get();
@@ -1135,20 +1088,12 @@ void AnimationTree::_process_graph(real_t p_delta) {
t->start = time;
}
} else if (t->playing) {
- bool loop = a->get_loop_mode() != Animation::LoopMode::LOOP_NONE;
+ bool loop = a->has_loop();
bool stop = false;
- if (!loop) {
- if (delta > 0) {
- if (time < t->start) {
- stop = true;
- }
- } else if (delta < 0) {
- if (time > t->start) {
- stop = true;
- }
- }
+ if (!loop && time < t->start) {
+ stop = true;
} else if (t->len > 0) {
real_t len = t->start > time ? (a->get_length() - t->start) + time : time - t->start;
@@ -1182,7 +1127,7 @@ void AnimationTree::_process_graph(real_t p_delta) {
continue;
}
- if (seeked) {
+ if (delta == 0 || seeked) {
//seek
int idx = a->track_find_key(i, time);
if (idx < 0) {
@@ -1198,20 +1143,12 @@ void AnimationTree::_process_graph(real_t p_delta) {
Ref<Animation> anim = player2->get_animation(anim_name);
- real_t at_anim_pos = 0.0;
-
- switch (anim->get_loop_mode()) {
- case Animation::LoopMode::LOOP_NONE: {
- at_anim_pos = MAX((double)anim->get_length(), time - pos); //seek to end
- } break;
- case Animation::LoopMode::LOOP_LINEAR: {
- at_anim_pos = Math::fposmod(time - pos, (double)anim->get_length()); //seek to loop
- } break;
- case Animation::LoopMode::LOOP_PINGPONG: {
- at_anim_pos = Math::pingpong(time - pos, (double)a->get_length());
- } break;
- default:
- break;
+ real_t at_anim_pos;
+
+ if (anim->has_loop()) {
+ at_anim_pos = Math::fposmod(time - pos, (double)anim->get_length()); //seek to loop
+ } else {
+ at_anim_pos = MAX(anim->get_length(), time - pos); //seek to end
}
if (player2->is_playing() || seeked) {
@@ -1226,7 +1163,7 @@ void AnimationTree::_process_graph(real_t p_delta) {
} else {
//find stuff to play
List<int> to_play;
- a->track_get_key_indices_in_range(i, time, delta, &to_play, pingponged);
+ a->track_get_key_indices_in_range(i, time, delta, &to_play);
if (to_play.size()) {
int idx = to_play.back()->get();
diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h
index 7482de7ee1..1e0267682e 100644
--- a/scene/animation/animation_tree.h
+++ b/scene/animation/animation_tree.h
@@ -68,7 +68,6 @@ public:
const Vector<real_t> *track_blends = nullptr;
real_t blend = 0.0;
bool seeked = false;
- int pingponged = 0;
};
struct State {
@@ -102,10 +101,9 @@ public:
real_t _blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, real_t p_time, bool p_seek, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true, real_t *r_max = nullptr);
protected:
- void blend_animation(const StringName &p_animation, real_t p_time, real_t p_delta, bool p_seeked, real_t p_blend, int p_pingponged = 0);
+ void blend_animation(const StringName &p_animation, real_t p_time, real_t p_delta, bool p_seeked, real_t p_blend);
real_t blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, real_t p_time, bool p_seek, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true);
real_t blend_input(int p_input, real_t p_time, bool p_seek, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true);
-
void make_invalid(const String &p_reason);
static void _bind_methods();
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 4382674470..b4eec2530b 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -309,8 +309,8 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
if (name == "length") {
r_ret = length;
- } else if (name == "loop_mode") {
- r_ret = loop_mode;
+ } else if (name == "loop") {
+ r_ret = loop;
} else if (name == "step") {
r_ret = step;
} else if (name.begins_with("tracks/")) {
@@ -1413,7 +1413,7 @@ void Animation::track_set_key_transition(int p_track, int p_key_idx, real_t p_tr
}
template <class K>
-int Animation::_find(const Vector<K> &p_keys, double p_time, bool p_backward) const {
+int Animation::_find(const Vector<K> &p_keys, double p_time) const {
int len = p_keys.size();
if (len == 0) {
return -2;
@@ -1443,14 +1443,8 @@ int Animation::_find(const Vector<K> &p_keys, double p_time, bool p_backward) co
}
}
- if (!p_backward) {
- if (keys[middle].time > p_time) {
- middle--;
- }
- } else {
- if (keys[middle].time < p_time) {
- middle++;
- }
+ if (keys[middle].time > p_time) {
+ middle--;
}
return middle;
@@ -1591,7 +1585,7 @@ real_t Animation::_cubic_interpolate(const real_t &p_pre_a, const real_t &p_a, c
}
template <class T>
-T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok, bool p_backward) const {
+T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok) const {
int len = _find(p_keys, length) + 1; // try to find last key (there may be more past the end)
if (len <= 0) {
@@ -1609,7 +1603,7 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol
return p_keys[0].value;
}
- int idx = _find(p_keys, p_time, p_backward);
+ int idx = _find(p_keys, p_time);
ERR_FAIL_COND_V(idx == -2, T());
@@ -1618,42 +1612,24 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol
real_t c = 0.0;
// prepare for all cases of interpolation
- if ((loop_mode == LOOP_LINEAR || loop_mode == LOOP_PINGPONG) && p_loop_wrap) {
+ if (loop && p_loop_wrap) {
// loop
- if (!p_backward) {
- // no backward
- if (idx >= 0) {
- if (idx < len - 1) {
- next = idx + 1;
- real_t delta = p_keys[next].time - p_keys[idx].time;
- real_t from = p_time - p_keys[idx].time;
-
- if (Math::is_zero_approx(delta)) {
- c = 0;
- } else {
- c = from / delta;
- }
+ if (idx >= 0) {
+ if ((idx + 1) < len) {
+ next = idx + 1;
+ real_t delta = p_keys[next].time - p_keys[idx].time;
+ real_t from = p_time - p_keys[idx].time;
+
+ if (Math::is_zero_approx(delta)) {
+ c = 0;
} else {
- next = 0;
- real_t delta = (length - p_keys[idx].time) + p_keys[next].time;
- real_t from = p_time - p_keys[idx].time;
-
- if (Math::is_zero_approx(delta)) {
- c = 0;
- } else {
- c = from / delta;
- }
+ c = from / delta;
}
+
} else {
- // on loop, behind first key
- idx = len - 1;
next = 0;
- real_t endtime = (length - p_keys[idx].time);
- if (endtime < 0) { // may be keys past the end
- endtime = 0;
- }
- real_t delta = endtime + p_keys[next].time;
- real_t from = endtime + p_time;
+ real_t delta = (length - p_keys[idx].time) + p_keys[next].time;
+ real_t from = p_time - p_keys[idx].time;
if (Math::is_zero_approx(delta)) {
c = 0;
@@ -1661,81 +1637,49 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol
c = from / delta;
}
}
+
} else {
- // backward
- if (idx <= len - 1) {
- if (idx > 0) {
- next = idx - 1;
- real_t delta = (length - p_keys[next].time) - (length - p_keys[idx].time);
- real_t from = (length - p_time) - (length - p_keys[idx].time);
-
- if (Math::is_zero_approx(delta))
- c = 0;
- else
- c = from / delta;
- } else {
- next = len - 1;
- real_t delta = p_keys[idx].time + (length - p_keys[next].time);
- real_t from = (length - p_time) - (length - p_keys[idx].time);
-
- if (Math::is_zero_approx(delta))
- c = 0;
- else
- c = from / delta;
- }
+ // on loop, behind first key
+ idx = len - 1;
+ next = 0;
+ real_t endtime = (length - p_keys[idx].time);
+ if (endtime < 0) { // may be keys past the end
+ endtime = 0;
+ }
+ real_t delta = endtime + p_keys[next].time;
+ real_t from = endtime + p_time;
+
+ if (Math::is_zero_approx(delta)) {
+ c = 0;
} else {
- // on loop, in front of last key
- idx = 0;
- next = len - 1;
- real_t endtime = p_keys[idx].time;
- if (endtime > length) // may be keys past the end
- endtime = length;
- real_t delta = p_keys[next].time - endtime;
- real_t from = p_time - endtime;
-
- if (Math::is_zero_approx(delta))
- c = 0;
- else
- c = from / delta;
+ c = from / delta;
}
}
+
} else { // no loop
- if (!p_backward) {
- if (idx >= 0) {
- if (idx < len - 1) {
- next = idx + 1;
- real_t delta = p_keys[next].time - p_keys[idx].time;
- real_t from = p_time - p_keys[idx].time;
-
- if (Math::is_zero_approx(delta)) {
- c = 0;
- } else {
- c = from / delta;
- }
+
+ if (idx >= 0) {
+ if ((idx + 1) < len) {
+ next = idx + 1;
+ real_t delta = p_keys[next].time - p_keys[idx].time;
+ real_t from = p_time - p_keys[idx].time;
+
+ if (Math::is_zero_approx(delta)) {
+ c = 0;
} else {
- next = idx;
+ c = from / delta;
}
+
} else {
- idx = next = 0;
+ next = idx;
}
- } else {
- if (idx <= len - 1) {
- if (idx > 0) {
- next = idx - 1;
- real_t delta = (length - p_keys[next].time) - (length - p_keys[idx].time);
- real_t from = (length - p_time) - (length - p_keys[idx].time);
-
- if (Math::is_zero_approx(delta)) {
- c = 0;
- } else {
- c = from / delta;
- }
- } else {
- next = idx;
- }
+ } else {
+ // only allow extending first key to anim start if looping
+ if (loop) {
+ idx = next = 0;
} else {
- idx = next = len - 1;
+ result = false;
}
}
}
@@ -1785,7 +1729,7 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol
// do a barrel roll
}
-Error Animation::transform_track_interpolate(int p_track, double p_time, Vector3 *r_loc, Quaternion *r_rot, Vector3 *r_scale, bool p_backward) const {
+Error Animation::transform_track_interpolate(int p_track, double p_time, Vector3 *r_loc, Quaternion *r_rot, Vector3 *r_scale) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), ERR_INVALID_PARAMETER);
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM3D, ERR_INVALID_PARAMETER);
@@ -1794,7 +1738,7 @@ Error Animation::transform_track_interpolate(int p_track, double p_time, Vector3
bool ok = false;
- TransformKey tk = _interpolate(tt->transforms, p_time, tt->interpolation, tt->loop_wrap, &ok, p_backward);
+ TransformKey tk = _interpolate(tt->transforms, p_time, tt->interpolation, tt->loop_wrap, &ok);
if (!ok) {
return ERR_UNAVAILABLE;
@@ -1869,7 +1813,7 @@ void Animation::_value_track_get_key_indices_in_range(const ValueTrack *vt, doub
}
}
-void Animation::value_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged) const {
+void Animation::value_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices) const {
ERR_FAIL_INDEX(p_track, tracks.size());
Track *t = tracks[p_track];
ERR_FAIL_COND(t->type != TYPE_VALUE);
@@ -1883,50 +1827,30 @@ void Animation::value_track_get_key_indices(int p_track, double p_time, double p
SWAP(from_time, to_time);
}
- switch (loop_mode) {
- case LOOP_NONE: {
- if (from_time < 0) {
- from_time = 0;
- }
- if (from_time > length) {
- from_time = length;
- }
-
- if (to_time < 0) {
- to_time = 0;
- }
- if (to_time > length) {
- to_time = length;
- }
- } break;
- case LOOP_LINEAR: {
- from_time = Math::fposmod(from_time, length);
- to_time = Math::fposmod(to_time, length);
+ if (loop) {
+ from_time = Math::fposmod(from_time, length);
+ to_time = Math::fposmod(to_time, length);
- if (from_time > to_time) {
- // handle loop by splitting
- _value_track_get_key_indices_in_range(vt, from_time, length, p_indices);
- _value_track_get_key_indices_in_range(vt, 0, to_time, p_indices);
- return;
- }
- } break;
- case LOOP_PINGPONG: {
- from_time = Math::pingpong(from_time, length);
- to_time = Math::pingpong(to_time, length);
+ if (from_time > to_time) {
+ // handle loop by splitting
+ _value_track_get_key_indices_in_range(vt, from_time, length, p_indices);
+ _value_track_get_key_indices_in_range(vt, 0, to_time, p_indices);
+ return;
+ }
+ } else {
+ if (from_time < 0) {
+ from_time = 0;
+ }
+ if (from_time > length) {
+ from_time = length;
+ }
- if (p_pingponged == -1) {
- // handle loop by splitting
- _value_track_get_key_indices_in_range(vt, 0, from_time, p_indices);
- _value_track_get_key_indices_in_range(vt, 0, to_time, p_indices);
- return;
- }
- if (p_pingponged == 1) {
- // handle loop by splitting
- _value_track_get_key_indices_in_range(vt, from_time, length, p_indices);
- _value_track_get_key_indices_in_range(vt, to_time, length, p_indices);
- return;
- }
- } break;
+ if (to_time < 0) {
+ to_time = 0;
+ }
+ if (to_time > length) {
+ to_time = length;
+ }
}
_value_track_get_key_indices_in_range(vt, from_time, to_time, p_indices);
@@ -1985,7 +1909,7 @@ void Animation::_track_get_key_indices_in_range(const Vector<T> &p_array, double
}
}
-void Animation::track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged) const {
+void Animation::track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices) const {
ERR_FAIL_INDEX(p_track, tracks.size());
const Track *t = tracks[p_track];
@@ -1996,176 +1920,104 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
SWAP(from_time, to_time);
}
- switch (loop_mode) {
- case LOOP_NONE: {
- if (from_time < 0) {
- from_time = 0;
- }
- if (from_time > length) {
- from_time = length;
- }
+ if (loop) {
+ if (from_time > length || from_time < 0) {
+ from_time = Math::fposmod(from_time, length);
+ }
- if (to_time < 0) {
- to_time = 0;
- }
- if (to_time > length) {
- to_time = length;
- }
- } break;
- case LOOP_LINEAR: {
- if (from_time > length || from_time < 0) {
- from_time = Math::fposmod(from_time, length);
- }
- if (to_time > length || to_time < 0) {
- to_time = Math::fposmod(to_time, length);
- }
+ if (to_time > length || to_time < 0) {
+ to_time = Math::fposmod(to_time, length);
+ }
- if (from_time > to_time) {
- // handle loop by splitting
- switch (t->type) {
- case TYPE_TRANSFORM3D: {
- const TransformTrack *tt = static_cast<const TransformTrack *>(t);
- _track_get_key_indices_in_range(tt->transforms, from_time, length, p_indices);
- _track_get_key_indices_in_range(tt->transforms, 0, to_time, p_indices);
- } break;
- case TYPE_VALUE: {
- const ValueTrack *vt = static_cast<const ValueTrack *>(t);
- _track_get_key_indices_in_range(vt->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(vt->values, 0, to_time, p_indices);
- } break;
- case TYPE_METHOD: {
- const MethodTrack *mt = static_cast<const MethodTrack *>(t);
- _track_get_key_indices_in_range(mt->methods, from_time, length, p_indices);
- _track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices);
- } break;
- case TYPE_BEZIER: {
- const BezierTrack *bz = static_cast<const BezierTrack *>(t);
- _track_get_key_indices_in_range(bz->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(bz->values, 0, to_time, p_indices);
- } break;
- case TYPE_AUDIO: {
- const AudioTrack *ad = static_cast<const AudioTrack *>(t);
- _track_get_key_indices_in_range(ad->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(ad->values, 0, to_time, p_indices);
- } break;
- case TYPE_ANIMATION: {
- const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
- _track_get_key_indices_in_range(an->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(an->values, 0, to_time, p_indices);
- } break;
- }
- return;
- }
- } break;
- case LOOP_PINGPONG: {
- if (from_time > length || from_time < 0) {
- from_time = Math::pingpong(from_time, length);
- }
- if (to_time > length || to_time < 0) {
- to_time = Math::pingpong(to_time, length);
+ if (from_time > to_time) {
+ // handle loop by splitting
+
+ switch (t->type) {
+ case TYPE_TRANSFORM3D: {
+ const TransformTrack *tt = static_cast<const TransformTrack *>(t);
+ _track_get_key_indices_in_range(tt->transforms, from_time, length, p_indices);
+ _track_get_key_indices_in_range(tt->transforms, 0, to_time, p_indices);
+
+ } break;
+ case TYPE_VALUE: {
+ const ValueTrack *vt = static_cast<const ValueTrack *>(t);
+ _track_get_key_indices_in_range(vt->values, from_time, length, p_indices);
+ _track_get_key_indices_in_range(vt->values, 0, to_time, p_indices);
+
+ } break;
+ case TYPE_METHOD: {
+ const MethodTrack *mt = static_cast<const MethodTrack *>(t);
+ _track_get_key_indices_in_range(mt->methods, from_time, length, p_indices);
+ _track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices);
+
+ } break;
+ case TYPE_BEZIER: {
+ const BezierTrack *bz = static_cast<const BezierTrack *>(t);
+ _track_get_key_indices_in_range(bz->values, from_time, length, p_indices);
+ _track_get_key_indices_in_range(bz->values, 0, to_time, p_indices);
+
+ } break;
+ case TYPE_AUDIO: {
+ const AudioTrack *ad = static_cast<const AudioTrack *>(t);
+ _track_get_key_indices_in_range(ad->values, from_time, length, p_indices);
+ _track_get_key_indices_in_range(ad->values, 0, to_time, p_indices);
+
+ } break;
+ case TYPE_ANIMATION: {
+ const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
+ _track_get_key_indices_in_range(an->values, from_time, length, p_indices);
+ _track_get_key_indices_in_range(an->values, 0, to_time, p_indices);
+
+ } break;
}
+ return;
+ }
+ } else {
+ if (from_time < 0) {
+ from_time = 0;
+ }
+ if (from_time > length) {
+ from_time = length;
+ }
- if ((int)Math::floor(abs(p_delta) / length) % 2 == 0) {
- if (p_pingponged == -1) {
- // handle loop by splitting
- switch (t->type) {
- case TYPE_TRANSFORM3D: {
- const TransformTrack *tt = static_cast<const TransformTrack *>(t);
- _track_get_key_indices_in_range(tt->transforms, 0, from_time, p_indices);
- _track_get_key_indices_in_range(tt->transforms, 0, to_time, p_indices);
- } break;
- case TYPE_VALUE: {
- const ValueTrack *vt = static_cast<const ValueTrack *>(t);
- _track_get_key_indices_in_range(vt->values, 0, from_time, p_indices);
- _track_get_key_indices_in_range(vt->values, 0, to_time, p_indices);
- } break;
- case TYPE_METHOD: {
- const MethodTrack *mt = static_cast<const MethodTrack *>(t);
- _track_get_key_indices_in_range(mt->methods, 0, from_time, p_indices);
- _track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices);
- } break;
- case TYPE_BEZIER: {
- const BezierTrack *bz = static_cast<const BezierTrack *>(t);
- _track_get_key_indices_in_range(bz->values, 0, from_time, p_indices);
- _track_get_key_indices_in_range(bz->values, 0, to_time, p_indices);
- } break;
- case TYPE_AUDIO: {
- const AudioTrack *ad = static_cast<const AudioTrack *>(t);
- _track_get_key_indices_in_range(ad->values, 0, from_time, p_indices);
- _track_get_key_indices_in_range(ad->values, 0, to_time, p_indices);
- } break;
- case TYPE_ANIMATION: {
- const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
- _track_get_key_indices_in_range(an->values, 0, from_time, p_indices);
- _track_get_key_indices_in_range(an->values, 0, to_time, p_indices);
- } break;
- }
- return;
- }
- if (p_pingponged == 1) {
- // handle loop by splitting
- switch (t->type) {
- case TYPE_TRANSFORM3D: {
- const TransformTrack *tt = static_cast<const TransformTrack *>(t);
- _track_get_key_indices_in_range(tt->transforms, from_time, length, p_indices);
- _track_get_key_indices_in_range(tt->transforms, to_time, length, p_indices);
- } break;
- case TYPE_VALUE: {
- const ValueTrack *vt = static_cast<const ValueTrack *>(t);
- _track_get_key_indices_in_range(vt->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(vt->values, to_time, length, p_indices);
- } break;
- case TYPE_METHOD: {
- const MethodTrack *mt = static_cast<const MethodTrack *>(t);
- _track_get_key_indices_in_range(mt->methods, from_time, length, p_indices);
- _track_get_key_indices_in_range(mt->methods, to_time, length, p_indices);
- } break;
- case TYPE_BEZIER: {
- const BezierTrack *bz = static_cast<const BezierTrack *>(t);
- _track_get_key_indices_in_range(bz->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(bz->values, to_time, length, p_indices);
- } break;
- case TYPE_AUDIO: {
- const AudioTrack *ad = static_cast<const AudioTrack *>(t);
- _track_get_key_indices_in_range(ad->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(ad->values, to_time, length, p_indices);
- } break;
- case TYPE_ANIMATION: {
- const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
- _track_get_key_indices_in_range(an->values, from_time, length, p_indices);
- _track_get_key_indices_in_range(an->values, to_time, length, p_indices);
- } break;
- }
- return;
- }
- }
- } break;
+ if (to_time < 0) {
+ to_time = 0;
+ }
+ if (to_time > length) {
+ to_time = length;
+ }
}
switch (t->type) {
case TYPE_TRANSFORM3D: {
const TransformTrack *tt = static_cast<const TransformTrack *>(t);
_track_get_key_indices_in_range(tt->transforms, from_time, to_time, p_indices);
+
} break;
case TYPE_VALUE: {
const ValueTrack *vt = static_cast<const ValueTrack *>(t);
_track_get_key_indices_in_range(vt->values, from_time, to_time, p_indices);
+
} break;
case TYPE_METHOD: {
const MethodTrack *mt = static_cast<const MethodTrack *>(t);
_track_get_key_indices_in_range(mt->methods, from_time, to_time, p_indices);
+
} break;
case TYPE_BEZIER: {
const BezierTrack *bz = static_cast<const BezierTrack *>(t);
_track_get_key_indices_in_range(bz->values, from_time, to_time, p_indices);
+
} break;
case TYPE_AUDIO: {
const AudioTrack *ad = static_cast<const AudioTrack *>(t);
_track_get_key_indices_in_range(ad->values, from_time, to_time, p_indices);
+
} break;
case TYPE_ANIMATION: {
const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
_track_get_key_indices_in_range(an->values, from_time, to_time, p_indices);
+
} break;
}
}
@@ -2203,7 +2055,7 @@ void Animation::_method_track_get_key_indices_in_range(const MethodTrack *mt, do
}
}
-void Animation::method_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged) const {
+void Animation::method_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices) const {
ERR_FAIL_INDEX(p_track, tracks.size());
Track *t = tracks[p_track];
ERR_FAIL_COND(t->type != TYPE_METHOD);
@@ -2217,58 +2069,35 @@ void Animation::method_track_get_key_indices(int p_track, double p_time, double
SWAP(from_time, to_time);
}
- switch (loop_mode) {
- case LOOP_NONE: {
- if (from_time < 0) {
- from_time = 0;
- }
- if (from_time > length) {
- from_time = length;
- }
+ if (loop) {
+ if (from_time > length || from_time < 0) {
+ from_time = Math::fposmod(from_time, length);
+ }
- if (to_time < 0) {
- to_time = 0;
- }
- if (to_time > length) {
- to_time = length;
- }
- } break;
- case LOOP_LINEAR: {
- if (from_time > length || from_time < 0) {
- from_time = Math::fposmod(from_time, length);
- }
- if (to_time > length || to_time < 0) {
- to_time = Math::fposmod(to_time, length);
- }
+ if (to_time > length || to_time < 0) {
+ to_time = Math::fposmod(to_time, length);
+ }
- if (from_time > to_time) {
- // handle loop by splitting
- _method_track_get_key_indices_in_range(mt, from_time, length, p_indices);
- _method_track_get_key_indices_in_range(mt, 0, to_time, p_indices);
- return;
- }
- } break;
- case LOOP_PINGPONG: {
- if (from_time > length || from_time < 0) {
- from_time = Math::pingpong(from_time, length);
- }
- if (to_time > length || to_time < 0) {
- to_time = Math::pingpong(to_time, length);
- }
+ if (from_time > to_time) {
+ // handle loop by splitting
+ _method_track_get_key_indices_in_range(mt, from_time, length, p_indices);
+ _method_track_get_key_indices_in_range(mt, 0, to_time, p_indices);
+ return;
+ }
+ } else {
+ if (from_time < 0) {
+ from_time = 0;
+ }
+ if (from_time > length) {
+ from_time = length;
+ }
- if (p_pingponged == -1) {
- _method_track_get_key_indices_in_range(mt, 0, from_time, p_indices);
- _method_track_get_key_indices_in_range(mt, 0, to_time, p_indices);
- return;
- }
- if (p_pingponged == 1) {
- _method_track_get_key_indices_in_range(mt, from_time, length, p_indices);
- _method_track_get_key_indices_in_range(mt, to_time, length, p_indices);
- return;
- }
- } break;
- default:
- break;
+ if (to_time < 0) {
+ to_time = 0;
+ }
+ if (to_time > length) {
+ to_time = length;
+ }
}
_method_track_get_key_indices_in_range(mt, from_time, to_time, p_indices);
@@ -2654,13 +2483,13 @@ real_t Animation::get_length() const {
return length;
}
-void Animation::set_loop_mode(Animation::LoopMode p_loop_mode) {
- loop_mode = p_loop_mode;
+void Animation::set_loop(bool p_enabled) {
+ loop = p_enabled;
emit_changed();
}
-Animation::LoopMode Animation::get_loop_mode() const {
- return loop_mode;
+bool Animation::has_loop() const {
+ return loop;
}
void Animation::track_set_imported(int p_track, bool p_imported) {
@@ -2799,7 +2628,7 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("track_set_interpolation_loop_wrap", "track_idx", "interpolation"), &Animation::track_set_interpolation_loop_wrap);
ClassDB::bind_method(D_METHOD("track_get_interpolation_loop_wrap", "track_idx"), &Animation::track_get_interpolation_loop_wrap);
- ClassDB::bind_method(D_METHOD("transform_track_interpolate", "track_idx", "time_sec", "is_backward"), &Animation::_transform_track_interpolate, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("transform_track_interpolate", "track_idx", "time_sec"), &Animation::_transform_track_interpolate);
ClassDB::bind_method(D_METHOD("value_track_set_update_mode", "track_idx", "mode"), &Animation::value_track_set_update_mode);
ClassDB::bind_method(D_METHOD("value_track_get_update_mode", "track_idx"), &Animation::value_track_get_update_mode);
@@ -2837,8 +2666,8 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_length", "time_sec"), &Animation::set_length);
ClassDB::bind_method(D_METHOD("get_length"), &Animation::get_length);
- ClassDB::bind_method(D_METHOD("set_loop_mode", "loop_mode"), &Animation::set_loop_mode);
- ClassDB::bind_method(D_METHOD("get_loop_mode"), &Animation::get_loop_mode);
+ ClassDB::bind_method(D_METHOD("set_loop", "enabled"), &Animation::set_loop);
+ ClassDB::bind_method(D_METHOD("has_loop"), &Animation::has_loop);
ClassDB::bind_method(D_METHOD("set_step", "size_sec"), &Animation::set_step);
ClassDB::bind_method(D_METHOD("get_step"), &Animation::get_step);
@@ -2847,7 +2676,7 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("copy_track", "track_idx", "to_animation"), &Animation::copy_track);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0.001,99999,0.001"), "set_length", "get_length");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode"), "set_loop_mode", "get_loop_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step", PROPERTY_HINT_RANGE, "0,4096,0.001"), "set_step", "get_step");
ADD_SIGNAL(MethodInfo("tracks_changed"));
@@ -2867,10 +2696,6 @@ void Animation::_bind_methods() {
BIND_ENUM_CONSTANT(UPDATE_DISCRETE);
BIND_ENUM_CONSTANT(UPDATE_TRIGGER);
BIND_ENUM_CONSTANT(UPDATE_CAPTURE);
-
- BIND_ENUM_CONSTANT(LOOP_NONE);
- BIND_ENUM_CONSTANT(LOOP_LINEAR);
- BIND_ENUM_CONSTANT(LOOP_PINGPONG);
}
void Animation::clear() {
@@ -2878,7 +2703,7 @@ void Animation::clear() {
memdelete(tracks[i]);
}
tracks.clear();
- loop_mode = LOOP_NONE;
+ loop = false;
length = 1;
emit_changed();
emit_signal(SceneStringNames::get_singleton()->tracks_changed);
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index 032b1a9277..9a410bd566 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -60,12 +60,7 @@ public:
UPDATE_DISCRETE,
UPDATE_TRIGGER,
UPDATE_CAPTURE,
- };
- enum LoopMode {
- LOOP_NONE,
- LOOP_LINEAR,
- LOOP_PINGPONG,
};
private:
@@ -189,8 +184,7 @@ private:
int _insert(double p_time, T &p_keys, const V &p_value);
template <class K>
-
- inline int _find(const Vector<K> &p_keys, double p_time, bool p_backward = false) const;
+ inline int _find(const Vector<K> &p_keys, double p_time) const;
_FORCE_INLINE_ Animation::TransformKey _interpolate(const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, real_t p_c) const;
@@ -206,7 +200,7 @@ private:
_FORCE_INLINE_ real_t _cubic_interpolate(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c) const;
template <class T>
- _FORCE_INLINE_ T _interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok, bool p_backward = false) const;
+ _FORCE_INLINE_ T _interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok) const;
template <class T>
_FORCE_INLINE_ void _track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices) const;
@@ -216,16 +210,15 @@ private:
double length = 1.0;
real_t step = 0.1;
- LoopMode loop_mode = LOOP_NONE;
- int pingponged = 0;
+ bool loop = false;
// bind helpers
private:
- Array _transform_track_interpolate(int p_track, double p_time, bool p_backward = false) const {
+ Array _transform_track_interpolate(int p_track, double p_time) const {
Vector3 loc;
Quaternion rot;
Vector3 scale;
- transform_track_interpolate(p_track, p_time, &loc, &rot, &scale, p_backward);
+ transform_track_interpolate(p_track, p_time, &loc, &rot, &scale);
Array ret;
ret.push_back(loc);
ret.push_back(rot);
@@ -331,26 +324,26 @@ public:
void track_set_interpolation_loop_wrap(int p_track, bool p_enable);
bool track_get_interpolation_loop_wrap(int p_track) const;
- Error transform_track_interpolate(int p_track, double p_time, Vector3 *r_loc, Quaternion *r_rot, Vector3 *r_scale, bool p_backward = false) const;
+ Error transform_track_interpolate(int p_track, double p_time, Vector3 *r_loc, Quaternion *r_rot, Vector3 *r_scale) const;
Variant value_track_interpolate(int p_track, double p_time) const;
- void value_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged = 0) const;
+ void value_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices) const;
void value_track_set_update_mode(int p_track, UpdateMode p_mode);
UpdateMode value_track_get_update_mode(int p_track) const;
- void method_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged = 0) const;
+ void method_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices) const;
Vector<Variant> method_track_get_params(int p_track, int p_key_idx) const;
StringName method_track_get_name(int p_track, int p_key_idx) const;
void copy_track(int p_track, Ref<Animation> p_to_animation);
- void track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged = 0) const;
+ void track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices) const;
void set_length(real_t p_length);
real_t get_length() const;
- void set_loop_mode(LoopMode p_loop_mode);
- LoopMode get_loop_mode() const;
+ void set_loop(bool p_enabled);
+ bool has_loop() const;
void set_step(real_t p_step);
real_t get_step() const;
@@ -366,6 +359,5 @@ public:
VARIANT_ENUM_CAST(Animation::TrackType);
VARIANT_ENUM_CAST(Animation::InterpolationType);
VARIANT_ENUM_CAST(Animation::UpdateMode);
-VARIANT_ENUM_CAST(Animation::LoopMode);
#endif
diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp
index c8a10e1c2a..d018103e64 100644
--- a/scene/resources/audio_stream_sample.cpp
+++ b/scene/resources/audio_stream_sample.cpp
@@ -299,7 +299,7 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
if (loop_format != AudioStreamSample::LOOP_DISABLED && offset < loop_begin_fp) {
/* loopstart reached */
- if (loop_format == AudioStreamSample::LOOP_PINGPONG) {
+ if (loop_format == AudioStreamSample::LOOP_PING_PONG) {
/* bounce ping pong */
offset = loop_begin_fp + (loop_begin_fp - offset);
increment = -increment;
@@ -320,7 +320,7 @@ int AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int
if (loop_format != AudioStreamSample::LOOP_DISABLED && offset >= loop_end_fp) {
/* loopend reached */
- if (loop_format == AudioStreamSample::LOOP_PINGPONG) {
+ if (loop_format == AudioStreamSample::LOOP_PING_PONG) {
/* bounce ping pong */
offset = loop_end_fp - (offset - loop_end_fp);
increment = -increment;
@@ -650,7 +650,7 @@ void AudioStreamSample::_bind_methods() {
BIND_ENUM_CONSTANT(LOOP_DISABLED);
BIND_ENUM_CONSTANT(LOOP_FORWARD);
- BIND_ENUM_CONSTANT(LOOP_PINGPONG);
+ BIND_ENUM_CONSTANT(LOOP_PING_PONG);
BIND_ENUM_CONSTANT(LOOP_BACKWARD);
}
diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_sample.h
index 0eb34be9bf..24198e3c98 100644
--- a/scene/resources/audio_stream_sample.h
+++ b/scene/resources/audio_stream_sample.h
@@ -92,7 +92,7 @@ public:
enum LoopMode {
LOOP_DISABLED,
LOOP_FORWARD,
- LOOP_PINGPONG,
+ LOOP_PING_PONG,
LOOP_BACKWARD
};