Merge pull request #120241 from TokageItLab/anim-stretch
Fix stretch mode in `custom_timeline` on `AnimationNodeAnimation`
This commit is contained in:
@@ -111,18 +111,20 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(ProcessState &p_pro
|
||||
double anim_size = anim->get_length();
|
||||
|
||||
double cur_len; // The animation length seen in NodeTimeInfo, propagated throughout the tree.
|
||||
|
||||
// The start/end section passed to AnimationMixer, to trim for Discrete/Method/Audio key section.
|
||||
double playback_start; // Start of the current section in AnimationMixer.
|
||||
double playback_end; // End of the current section in AnimationMixer.
|
||||
Animation::LoopMode cur_loop_mode;
|
||||
if (use_custom_timeline) {
|
||||
if (stretch_time_scale) {
|
||||
// When time scale is stretched, the entire animation is played anyway using a time scale based on the timeline length.
|
||||
cur_len = timeline_length;
|
||||
cur_loop_mode = loop_mode;
|
||||
if (stretch_time_scale || cur_loop_mode != Animation::LOOP_NONE) {
|
||||
// When time scale is stretched or looped, the entire animation is played anyway using a time scale based on the timeline length.
|
||||
// Therefore, the end of the animation section is the animation length.
|
||||
cur_len = anim_size;
|
||||
playback_start = 0.0;
|
||||
playback_end = anim_size;
|
||||
} else {
|
||||
cur_len = timeline_length;
|
||||
if (play_mode == PLAY_MODE_FORWARD) {
|
||||
playback_start = start_offset;
|
||||
playback_end = playback_start + timeline_length;
|
||||
@@ -131,7 +133,6 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(ProcessState &p_pro
|
||||
playback_start = playback_end - timeline_length;
|
||||
}
|
||||
}
|
||||
cur_loop_mode = loop_mode;
|
||||
} else {
|
||||
cur_len = anim_size;
|
||||
playback_start = 0.0;
|
||||
@@ -139,8 +140,6 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(ProcessState &p_pro
|
||||
cur_loop_mode = anim->get_loop_mode();
|
||||
}
|
||||
|
||||
// AnimationNodeAnimation always uses times relative to the start of the section. ([0, cur_len])
|
||||
// When creating the next PlaybackInfo, the relative time is converted back to absolute time. ([playback_start, playback_end])
|
||||
double cur_time = p_playback_info.time;
|
||||
double cur_delta = p_playback_info.delta;
|
||||
bool cur_backward = p_instance.get_parameter_backward();
|
||||
@@ -211,42 +210,46 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(ProcessState &p_pro
|
||||
// 3. Progress for Animation.
|
||||
double prev_playback_time = prev_time;
|
||||
double cur_playback_time = cur_time;
|
||||
if (use_custom_timeline && stretch_time_scale) {
|
||||
double mlt = anim_size / timeline_length;
|
||||
prev_playback_time *= mlt;
|
||||
cur_playback_time *= mlt;
|
||||
cur_delta *= mlt;
|
||||
if (use_custom_timeline) {
|
||||
prev_playback_time += start_offset;
|
||||
cur_playback_time += start_offset;
|
||||
if (stretch_time_scale) {
|
||||
double mlt = anim_size / timeline_length;
|
||||
prev_playback_time *= mlt;
|
||||
cur_playback_time *= mlt;
|
||||
cur_delta *= mlt;
|
||||
}
|
||||
}
|
||||
if (cur_loop_mode == Animation::LOOP_LINEAR) {
|
||||
if (!Math::is_zero_approx(cur_len)) {
|
||||
prev_playback_time = Math::fposmod(prev_playback_time, cur_len);
|
||||
cur_playback_time = Math::fposmod(cur_playback_time, cur_len);
|
||||
if (!Math::is_zero_approx(anim_size)) {
|
||||
prev_playback_time = Math::fposmod(prev_playback_time, anim_size);
|
||||
cur_playback_time = Math::fposmod(cur_playback_time, anim_size);
|
||||
if (Animation::is_greater_or_equal_approx(prev_playback_time, 0) && Animation::is_less_approx(cur_playback_time, 0)) {
|
||||
looped_flag = node_backward ? Animation::LOOPED_FLAG_END : Animation::LOOPED_FLAG_START;
|
||||
}
|
||||
if (Animation::is_less_or_equal_approx(prev_playback_time, cur_len) && Animation::is_greater_approx(cur_playback_time, cur_len)) {
|
||||
if (Animation::is_less_or_equal_approx(prev_playback_time, anim_size) && Animation::is_greater_approx(cur_playback_time, anim_size)) {
|
||||
looped_flag = node_backward ? Animation::LOOPED_FLAG_START : Animation::LOOPED_FLAG_END;
|
||||
}
|
||||
}
|
||||
} else if (cur_loop_mode == Animation::LOOP_PINGPONG) {
|
||||
if (!Math::is_zero_approx(cur_len)) {
|
||||
if (Animation::is_greater_or_equal_approx(Math::fposmod(cur_playback_time, cur_len * 2.0), cur_len)) {
|
||||
if (!Math::is_zero_approx(anim_size)) {
|
||||
if (Animation::is_greater_or_equal_approx(Math::fposmod(cur_playback_time, anim_size * 2.0), anim_size)) {
|
||||
cur_delta = -cur_delta; // Needed for retrieving discrete keys correctly.
|
||||
}
|
||||
prev_playback_time = Math::pingpong(prev_playback_time, cur_len);
|
||||
cur_playback_time = Math::pingpong(cur_playback_time, cur_len);
|
||||
prev_playback_time = Math::pingpong(prev_playback_time, anim_size);
|
||||
cur_playback_time = Math::pingpong(cur_playback_time, anim_size);
|
||||
if (Animation::is_greater_or_equal_approx(prev_playback_time, 0) && Animation::is_less_approx(cur_playback_time, 0)) {
|
||||
looped_flag = node_backward ? Animation::LOOPED_FLAG_END : Animation::LOOPED_FLAG_START;
|
||||
}
|
||||
if (Animation::is_less_or_equal_approx(prev_playback_time, cur_len) && Animation::is_greater_approx(cur_playback_time, cur_len)) {
|
||||
if (Animation::is_less_or_equal_approx(prev_playback_time, anim_size) && Animation::is_greater_approx(cur_playback_time, anim_size)) {
|
||||
looped_flag = node_backward ? Animation::LOOPED_FLAG_START : Animation::LOOPED_FLAG_END;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Animation::is_less_approx(cur_playback_time, 0)) {
|
||||
cur_playback_time = 0;
|
||||
} else if (Animation::is_greater_approx(cur_playback_time, cur_len)) {
|
||||
cur_playback_time = cur_len;
|
||||
} else if (Animation::is_greater_approx(cur_playback_time, anim_size)) {
|
||||
cur_playback_time = anim_size;
|
||||
}
|
||||
|
||||
// Emit start & finish signal. Internally, the detections are the same for backward.
|
||||
@@ -257,8 +260,8 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(ProcessState &p_pro
|
||||
p_process_state.tree->call_deferred(SNAME("emit_signal"), SceneStringName(animation_started), animation);
|
||||
}
|
||||
// Finished.
|
||||
if (Animation::is_less_approx(prev_playback_time, cur_len) && Animation::is_greater_or_equal_approx(cur_playback_time, cur_len)) {
|
||||
cur_playback_time = cur_len;
|
||||
if (Animation::is_less_approx(prev_playback_time, anim_size) && Animation::is_greater_or_equal_approx(cur_playback_time, anim_size)) {
|
||||
cur_playback_time = anim_size;
|
||||
p_process_state.tree->call_deferred(SNAME("emit_signal"), SceneStringName(animation_finished), animation);
|
||||
}
|
||||
}
|
||||
@@ -284,9 +287,9 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(ProcessState &p_pro
|
||||
pi.start = playback_start;
|
||||
pi.end = playback_end;
|
||||
if (play_mode == PLAY_MODE_FORWARD) {
|
||||
pi.time = playback_start + cur_playback_time;
|
||||
pi.time = cur_playback_time;
|
||||
} else {
|
||||
pi.time = playback_start + cur_len - cur_playback_time;
|
||||
pi.time = anim_size - cur_playback_time;
|
||||
}
|
||||
if (node_backward ? cur_backward : !cur_backward) {
|
||||
pi.delta = cur_delta;
|
||||
|
||||
Reference in New Issue
Block a user