Skip to content

Commit

Permalink
Merge pull request #94554 from TokageItLab/approx-animation-compare
Browse files Browse the repository at this point in the history
Add approximate comparing static methods to Animation and make Animation code use them
  • Loading branch information
akien-mga committed Jul 24, 2024
2 parents 27daf3b + 88e590c commit 2966199
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 72 deletions.
57 changes: 29 additions & 28 deletions scene/animation/animation_blend_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,40 +144,40 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(const AnimationMixe
if (cur_loop_mode != Animation::LOOP_NONE) {
if (cur_loop_mode == Animation::LOOP_LINEAR) {
if (!Math::is_zero_approx(cur_len)) {
if (prev_time <= cur_len && cur_time > cur_len) {
if (Animation::is_less_or_equal_approx(prev_time, cur_len) && Animation::is_greater_approx(cur_time, cur_len)) {
is_just_looped = true; // Don't break with negative timescale since remain will not be 0.
}
cur_time = Math::fposmod(cur_time, cur_len);
}
backward = false;
} else {
if (!Math::is_zero_approx(cur_len)) {
if (prev_time >= 0 && cur_time < 0) {
if (Animation::is_greater_or_equal_approx(prev_time, 0) && Animation::is_less_approx(cur_time, 0)) {
backward = !backward;
} else if (prev_time <= cur_len && cur_time > cur_len) {
} else if (Animation::is_less_or_equal_approx(prev_time, cur_len) && Animation::is_greater_approx(cur_time, cur_len)) {
backward = !backward;
is_just_looped = true; // Don't break with negative timescale since remain will not be 0.
}
cur_time = Math::pingpong(cur_time, cur_len);
}
}
} else {
if (cur_time < 0) {
if (Animation::is_less_approx(cur_time, 0)) {
cur_delta += cur_time;
cur_time = 0;
} else if (cur_time > cur_len) {
} else if (Animation::is_greater_approx(cur_time, cur_len)) {
cur_delta += cur_time - cur_len;
cur_time = cur_len;
}
backward = false;
// If ended, don't progress AnimationNode. So set delta to 0.
if (!Math::is_zero_approx(cur_delta)) {
if (play_mode == PLAY_MODE_FORWARD) {
if (prev_time >= cur_len) {
if (Animation::is_greater_or_equal_approx(prev_time, cur_len)) {
cur_delta = 0;
}
} else {
if (prev_time <= 0) {
if (Animation::is_less_or_equal_approx(prev_time, 0)) {
cur_delta = 0;
}
}
Expand All @@ -197,50 +197,51 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(const AnimationMixe
double cur_playback_time = cur_time + start_offset;
if (stretch_time_scale) {
double mlt = anim_size / cur_len;
prev_playback_time *= mlt;
cur_playback_time *= mlt;
cur_delta *= mlt;
}
if (cur_loop_mode == Animation::LOOP_LINEAR) {
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 (prev_playback_time >= 0 && cur_playback_time < 0) {
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 (prev_playback_time <= anim_size && cur_playback_time > anim_size) {
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(anim_size)) {
if (Math::fposmod(cur_playback_time, anim_size * 2.0) >= 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, anim_size);
cur_playback_time = Math::pingpong(cur_playback_time, anim_size);
if (prev_playback_time >= 0 && cur_playback_time < 0) {
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 (prev_playback_time <= anim_size && cur_playback_time > anim_size) {
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_playback_time < 0) {
if (Animation::is_less_approx(cur_playback_time, 0)) {
cur_playback_time = 0;
} else if (cur_playback_time > anim_size) {
} 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.
// We should use call_deferred since the track keys are still being processed.
if (process_state->tree && !p_test_only) {
// AnimationTree uses seek to 0 "internally" to process the first key of the animation, which is used as the start detection.
if (p_seek && !p_is_external_seeking && cur_playback_time == 0) {
if (p_seek && !p_is_external_seeking && Math::is_zero_approx(cur_playback_time)) {
process_state->tree->call_deferred(SNAME("emit_signal"), SceneStringName(animation_started), animation);
}
// Finished.
if (prev_time + start_offset < anim_size && cur_playback_time >= anim_size) {
if (Animation::is_less_approx(prev_playback_time, anim_size) && Animation::is_greater_or_equal_approx(cur_playback_time, anim_size)) {
process_state->tree->call_deferred(SNAME("emit_signal"), SceneStringName(animation_finished), animation);
}
}
Expand Down Expand Up @@ -522,7 +523,7 @@ AnimationNode::NodeTimeInfo AnimationNodeOneShot::_process(const AnimationMixer:
bool p_seek = p_playback_info.seeked;
bool p_is_external_seeking = p_playback_info.is_external_seeking;

if (p_time == 0 && p_seek && !p_is_external_seeking) {
if (Math::is_zero_approx(p_time) && p_seek && !p_is_external_seeking) {
clear_remaining_fade = true; // Reset occurs.
}

Expand All @@ -545,9 +546,9 @@ AnimationNode::NodeTimeInfo AnimationNodeOneShot::_process(const AnimationMixer:
set_parameter(internal_active, false);
set_parameter(time_to_restart, -1);
} else if (!do_start && !cur_active) {
if (cur_time_to_restart >= 0.0 && !p_seek) {
if (Animation::is_greater_or_equal_approx(cur_time_to_restart, 0) && !p_seek) {
cur_time_to_restart -= abs_delta;
if (cur_time_to_restart < 0) {
if (Animation::is_less_approx(cur_time_to_restart, 0)) {
do_start = true; // Restart.
}
set_parameter(time_to_restart, cur_time_to_restart);
Expand Down Expand Up @@ -590,8 +591,8 @@ AnimationNode::NodeTimeInfo AnimationNodeOneShot::_process(const AnimationMixer:
real_t blend = 1.0;
bool use_blend = sync;

if (cur_fade_in_remaining > 0) {
if (fade_in > 0) {
if (Animation::is_greater_approx(cur_fade_in_remaining, 0)) {
if (Animation::is_greater_approx(fade_in, 0)) {
use_blend = true;
blend = (fade_in - cur_fade_in_remaining) / fade_in;
if (fade_in_curve.is_valid()) {
Expand All @@ -604,7 +605,7 @@ AnimationNode::NodeTimeInfo AnimationNodeOneShot::_process(const AnimationMixer:

if (is_fading_out) {
use_blend = true;
if (fade_out > 0) {
if (Animation::is_greater_approx(fade_out, 0)) {
blend = cur_fade_out_remaining / fade_out;
if (fade_out_curve.is_valid()) {
blend = 1.0 - fade_out_curve->sample(1.0 - blend);
Expand Down Expand Up @@ -636,15 +637,15 @@ AnimationNode::NodeTimeInfo AnimationNodeOneShot::_process(const AnimationMixer:

NodeTimeInfo os_nti = blend_input(1, pi, FILTER_PASS, true, p_test_only); // Blend values must be more than CMP_EPSILON to process discrete keys in edge.

if (cur_fade_in_remaining <= 0 && !do_start && !is_fading_out && os_nti.get_remain(break_loop_at_end) <= fade_out) {
if (Animation::is_less_or_equal_approx(cur_fade_in_remaining, 0) && !do_start && !is_fading_out && Animation::is_less_or_equal_approx(os_nti.get_remain(break_loop_at_end), fade_out)) {
is_fading_out = true;
cur_fade_out_remaining = os_nti.get_remain(break_loop_at_end);
cur_fade_in_remaining = 0;
set_parameter(internal_active, false);
}

if (!p_seek) {
if (os_nti.get_remain(break_loop_at_end) <= 0 || (is_fading_out && cur_fade_out_remaining <= 0)) {
if (Animation::is_less_or_equal_approx(os_nti.get_remain(break_loop_at_end), 0) || (is_fading_out && Animation::is_less_or_equal_approx(cur_fade_out_remaining, 0))) {
set_parameter(internal_active, false);
set_parameter(active, false);
if (auto_restart) {
Expand Down Expand Up @@ -1007,7 +1008,7 @@ AnimationNode::NodeTimeInfo AnimationNodeTimeSeek::_process(const AnimationMixer

AnimationMixer::PlaybackInfo pi = p_playback_info;
pi.weight = 1.0;
if (cur_seek_pos >= 0) {
if (Animation::is_greater_or_equal_approx(cur_seek_pos, 0)) {
pi.time = cur_seek_pos;
pi.seeked = true;
pi.is_external_seeking = true;
Expand Down Expand Up @@ -1252,7 +1253,7 @@ AnimationNode::NodeTimeInfo AnimationNodeTransition::_process(const AnimationMix
bool p_seek = p_playback_info.seeked;
bool p_is_external_seeking = p_playback_info.is_external_seeking;

if (p_time == 0 && p_seek && !p_is_external_seeking) {
if (Math::is_zero_approx(p_time) && p_seek && !p_is_external_seeking) {
clear_remaining_fade = true; // Reset occurs.
}

Expand Down Expand Up @@ -1317,7 +1318,7 @@ AnimationNode::NodeTimeInfo AnimationNodeTransition::_process(const AnimationMix
if (cur_prev_index < 0) { // Process current animation, check for transition.
pi.weight = 1.0;
cur_nti = blend_input(cur_current_index, pi, FILTER_IGNORE, true, p_test_only);
if (input_data[cur_current_index].auto_advance && cur_nti.get_remain(input_data[cur_current_index].break_loop_at_end) <= xfade_time) {
if (input_data[cur_current_index].auto_advance && Animation::is_less_or_equal_approx(cur_nti.get_remain(input_data[cur_current_index].break_loop_at_end), xfade_time)) {
set_parameter(transition_request, get_input_name((cur_current_index + 1) % get_input_count()));
}
} else { // Cross-fading from prev to current.
Expand Down Expand Up @@ -1349,7 +1350,7 @@ AnimationNode::NodeTimeInfo AnimationNodeTransition::_process(const AnimationMix
pi.weight = blend;
blend_input(cur_prev_index, pi, FILTER_IGNORE, true, p_test_only);
if (!p_seek) {
if (cur_prev_xfading <= 0) {
if (Animation::is_less_or_equal_approx(cur_prev_xfading, 0)) {
set_parameter(prev_index, -1);
}
cur_prev_xfading -= Math::abs(p_playback_info.delta);
Expand Down
42 changes: 21 additions & 21 deletions scene/animation/animation_mixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1049,7 +1049,7 @@ void AnimationMixer::blend_capture(double p_delta) {
}

capture_cache.remain -= p_delta * capture_cache.step;
if (capture_cache.remain <= 0.0) {
if (Animation::is_less_or_equal_approx(capture_cache.remain, 0)) {
capture_cache.clear();
return;
}
Expand Down Expand Up @@ -1156,7 +1156,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
if (track->root_motion && calc_root) {
double prev_time = time - delta;
if (!backward) {
if (prev_time < 0) {
if (Animation::is_less_approx(prev_time, 0)) {
switch (a->get_loop_mode()) {
case Animation::LOOP_NONE: {
prev_time = 0;
Expand All @@ -1172,7 +1172,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
}
}
} else {
if (prev_time > a->get_length()) {
if (Animation::is_greater_approx(prev_time, (double)a->get_length())) {
switch (a->get_loop_mode()) {
case Animation::LOOP_NONE: {
prev_time = (double)a->get_length();
Expand All @@ -1190,7 +1190,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
}
Vector3 loc[2];
if (!backward) {
if (prev_time > time) {
if (Animation::is_greater_approx(prev_time, time)) {
Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
if (err != OK) {
continue;
Expand All @@ -1202,7 +1202,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
prev_time = 0;
}
} else {
if (prev_time < time) {
if (Animation::is_less_approx(prev_time, time)) {
Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
if (err != OK) {
continue;
Expand Down Expand Up @@ -1244,7 +1244,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
if (track->root_motion && calc_root) {
double prev_time = time - delta;
if (!backward) {
if (prev_time < 0) {
if (Animation::is_less_approx(prev_time, 0)) {
switch (a->get_loop_mode()) {
case Animation::LOOP_NONE: {
prev_time = 0;
Expand All @@ -1260,7 +1260,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
}
}
} else {
if (prev_time > a->get_length()) {
if (Animation::is_greater_approx(prev_time, (double)a->get_length())) {
switch (a->get_loop_mode()) {
case Animation::LOOP_NONE: {
prev_time = (double)a->get_length();
Expand All @@ -1278,7 +1278,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
}
Quaternion rot[2];
if (!backward) {
if (prev_time > time) {
if (Animation::is_greater_approx(prev_time, time)) {
Error err = a->try_rotation_track_interpolate(i, prev_time, &rot[0]);
if (err != OK) {
continue;
Expand All @@ -1290,7 +1290,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
prev_time = 0;
}
} else {
if (prev_time < time) {
if (Animation::is_less_approx(prev_time, time)) {
Error err = a->try_rotation_track_interpolate(i, prev_time, &rot[0]);
if (err != OK) {
continue;
Expand Down Expand Up @@ -1331,7 +1331,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
if (track->root_motion && calc_root) {
double prev_time = time - delta;
if (!backward) {
if (prev_time < 0) {
if (Animation::is_less_approx(prev_time, 0)) {
switch (a->get_loop_mode()) {
case Animation::LOOP_NONE: {
prev_time = 0;
Expand All @@ -1347,7 +1347,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
}
}
} else {
if (prev_time > a->get_length()) {
if (Animation::is_greater_approx(prev_time, (double)a->get_length())) {
switch (a->get_loop_mode()) {
case Animation::LOOP_NONE: {
prev_time = (double)a->get_length();
Expand All @@ -1365,7 +1365,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
}
Vector3 scale[2];
if (!backward) {
if (prev_time > time) {
if (Animation::is_greater_approx(prev_time, time)) {
Error err = a->try_scale_track_interpolate(i, prev_time, &scale[0]);
if (err != OK) {
continue;
Expand All @@ -1377,7 +1377,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
prev_time = 0;
}
} else {
if (prev_time < time) {
if (Animation::is_less_approx(prev_time, time)) {
Error err = a->try_scale_track_interpolate(i, prev_time, &scale[0]);
if (err != OK) {
continue;
Expand Down Expand Up @@ -1635,7 +1635,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
PlayingAudioStreamInfo pasi;
pasi.index = t->audio_stream_playback->play_stream(stream, start_ofs, 0, 1.0, t->playback_type, t->bus);
pasi.start = time;
if (len && end_ofs > 0) { // Force an end at a time.
if (len && Animation::is_greater_approx(end_ofs, 0)) { // Force an end at a time.
pasi.len = len - start_ofs - end_ofs;
} else {
pasi.len = 0;
Expand Down Expand Up @@ -1671,7 +1671,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
double at_anim_pos = 0.0;
switch (anim->get_loop_mode()) {
case Animation::LOOP_NONE: {
if (!is_external_seeking && ((!backward && time >= pos + (double)anim->get_length()) || (backward && time <= pos))) {
if (!is_external_seeking && ((!backward && Animation::is_greater_or_equal_approx(time, pos + (double)anim->get_length())) || (backward && Animation::is_less_or_equal_approx(time, pos)))) {
continue; // Do nothing if current time is outside of length when started.
}
at_anim_pos = MIN((double)anim->get_length(), time - pos); // Seek to end.
Expand Down Expand Up @@ -1841,23 +1841,23 @@ void AnimationMixer::_blend_apply() {
}
if (!track_info.loop) {
if (!track_info.backward) {
if (track_info.time < pasi.start) {
if (Animation::is_less_approx(track_info.time, pasi.start)) {
stop = true;
}
} else if (track_info.backward) {
if (track_info.time > pasi.start) {
if (Animation::is_greater_approx(track_info.time, pasi.start)) {
stop = true;
}
}
}
if (pasi.len > 0) {
if (Animation::is_greater_approx(pasi.len, 0)) {
double len = 0.0;
if (!track_info.backward) {
len = pasi.start > track_info.time ? (track_info.length - pasi.start) + track_info.time : track_info.time - pasi.start;
len = Animation::is_greater_approx(pasi.start, track_info.time) ? (track_info.length - pasi.start) + track_info.time : track_info.time - pasi.start;
} else {
len = pasi.start < track_info.time ? (track_info.length - track_info.time) + pasi.start : pasi.start - track_info.time;
len = Animation::is_less_approx(pasi.start, track_info.time) ? (track_info.length - track_info.time) + pasi.start : pasi.start - track_info.time;
}
if (len > pasi.len) {
if (Animation::is_greater_approx(len, pasi.len)) {
stop = true;
}
}
Expand Down
Loading

0 comments on commit 2966199

Please sign in to comment.