mirror of https://github.com/godotengine/godot
Refactor process of animation to retrive keys more exactly
This commit is contained in:
parent
0bb1e89fb7
commit
1fc3833617
|
|
@ -616,5 +616,14 @@
|
||||||
<constant name="LOOP_PINGPONG" value="2" enum="LoopMode">
|
<constant name="LOOP_PINGPONG" value="2" enum="LoopMode">
|
||||||
Repeats playback and reverse playback at both ends of the animation.
|
Repeats playback and reverse playback at both ends of the animation.
|
||||||
</constant>
|
</constant>
|
||||||
|
<constant name="LOOPED_FLAG_NONE" value="0" enum="LoopedFlag">
|
||||||
|
This flag indicates that the animation proceeds without any looping.
|
||||||
|
</constant>
|
||||||
|
<constant name="LOOPED_FLAG_END" value="1" enum="LoopedFlag">
|
||||||
|
This flag indicates that the animation has reached the end of the animation and just after loop processed.
|
||||||
|
</constant>
|
||||||
|
<constant name="LOOPED_FLAG_START" value="2" enum="LoopedFlag">
|
||||||
|
This flag indicates that the animation has reached the start of the animation and just after loop processed.
|
||||||
|
</constant>
|
||||||
</constants>
|
</constants>
|
||||||
</class>
|
</class>
|
||||||
|
|
|
||||||
|
|
@ -75,9 +75,10 @@
|
||||||
<param index="3" name="seeked" type="bool" />
|
<param index="3" name="seeked" type="bool" />
|
||||||
<param index="4" name="is_external_seeking" type="bool" />
|
<param index="4" name="is_external_seeking" type="bool" />
|
||||||
<param index="5" name="blend" type="float" />
|
<param index="5" name="blend" type="float" />
|
||||||
<param index="6" name="pingponged" type="int" default="0" />
|
<param index="6" name="looped_flag" type="int" enum="Animation.LoopedFlag" default="0" />
|
||||||
<description>
|
<description>
|
||||||
Blend an animation by [param blend] amount (name must be valid in the linked [AnimationPlayer]). A [param time] and [param delta] may be passed, as well as whether [param seeked] happened.
|
Blend an animation by [param blend] amount (name must be valid in the linked [AnimationPlayer]). A [param time] and [param delta] may be passed, as well as whether [param seeked] happened.
|
||||||
|
A [param looped_flag] is used by internal processing immediately after the loop. See also [enum Animation.LoopedFlag].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="blend_input">
|
<method name="blend_input">
|
||||||
|
|
|
||||||
|
|
@ -87,36 +87,38 @@ double AnimationNodeAnimation::process(double p_time, bool p_seek, bool p_is_ext
|
||||||
double anim_size = (double)anim->get_length();
|
double anim_size = (double)anim->get_length();
|
||||||
double step = 0.0;
|
double step = 0.0;
|
||||||
double prev_time = cur_time;
|
double prev_time = cur_time;
|
||||||
int pingponged = 0;
|
Animation::LoopedFlag looped_flag = Animation::LOOPED_FLAG_NONE;
|
||||||
bool current_backward = signbit(p_time);
|
bool node_backward = play_mode == PLAY_MODE_BACKWARD;
|
||||||
|
|
||||||
if (p_seek) {
|
if (p_seek) {
|
||||||
step = p_time - cur_time;
|
step = p_time - cur_time;
|
||||||
cur_time = p_time;
|
cur_time = p_time;
|
||||||
} else {
|
} else {
|
||||||
p_time *= backward ? -1.0 : 1.0;
|
p_time *= backward ? -1.0 : 1.0;
|
||||||
if (!(cur_time == anim_size && !current_backward) && !(cur_time == 0 && current_backward)) {
|
cur_time = cur_time + p_time;
|
||||||
cur_time = cur_time + p_time;
|
step = p_time;
|
||||||
step = p_time;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (anim->get_loop_mode() == Animation::LOOP_PINGPONG) {
|
if (anim->get_loop_mode() == Animation::LOOP_PINGPONG) {
|
||||||
if (!Math::is_zero_approx(anim_size)) {
|
if (!Math::is_zero_approx(anim_size)) {
|
||||||
if ((int)Math::floor(abs(cur_time - prev_time) / anim_size) % 2 == 0) {
|
if (prev_time >= 0 && cur_time < 0) {
|
||||||
if (prev_time >= 0 && cur_time < 0) {
|
backward = !backward;
|
||||||
backward = !backward;
|
looped_flag = node_backward ? Animation::LOOPED_FLAG_END : Animation::LOOPED_FLAG_START;
|
||||||
pingponged = -1;
|
}
|
||||||
}
|
if (prev_time <= anim_size && cur_time > anim_size) {
|
||||||
if (prev_time <= anim_size && cur_time > anim_size) {
|
backward = !backward;
|
||||||
backward = !backward;
|
looped_flag = node_backward ? Animation::LOOPED_FLAG_START : Animation::LOOPED_FLAG_END;
|
||||||
pingponged = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cur_time = Math::pingpong(cur_time, anim_size);
|
cur_time = Math::pingpong(cur_time, anim_size);
|
||||||
}
|
}
|
||||||
} else if (anim->get_loop_mode() == Animation::LOOP_LINEAR) {
|
} else if (anim->get_loop_mode() == Animation::LOOP_LINEAR) {
|
||||||
if (!Math::is_zero_approx(anim_size)) {
|
if (!Math::is_zero_approx(anim_size)) {
|
||||||
|
if (prev_time >= 0 && cur_time < 0) {
|
||||||
|
looped_flag = node_backward ? Animation::LOOPED_FLAG_END : Animation::LOOPED_FLAG_START;
|
||||||
|
}
|
||||||
|
if (prev_time <= anim_size && cur_time > anim_size) {
|
||||||
|
looped_flag = node_backward ? Animation::LOOPED_FLAG_START : Animation::LOOPED_FLAG_END;
|
||||||
|
}
|
||||||
cur_time = Math::fposmod(cur_time, anim_size);
|
cur_time = Math::fposmod(cur_time, anim_size);
|
||||||
}
|
}
|
||||||
backward = false;
|
backward = false;
|
||||||
|
|
@ -145,9 +147,9 @@ double AnimationNodeAnimation::process(double p_time, bool p_seek, bool p_is_ext
|
||||||
}
|
}
|
||||||
|
|
||||||
if (play_mode == PLAY_MODE_FORWARD) {
|
if (play_mode == PLAY_MODE_FORWARD) {
|
||||||
blend_animation(animation, cur_time, step, p_seek, p_is_external_seeking, 1.0, pingponged);
|
blend_animation(animation, cur_time, step, p_seek, p_is_external_seeking, 1.0, looped_flag);
|
||||||
} else {
|
} else {
|
||||||
blend_animation(animation, anim_size - cur_time, -step, p_seek, p_is_external_seeking, 1.0, pingponged);
|
blend_animation(animation, anim_size - cur_time, -step, p_seek, p_is_external_seeking, 1.0, looped_flag);
|
||||||
}
|
}
|
||||||
set_parameter(time, cur_time);
|
set_parameter(time, cur_time);
|
||||||
|
|
||||||
|
|
@ -309,9 +311,7 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_is_exter
|
||||||
set_parameter(time_to_restart, cur_time_to_restart);
|
set_parameter(time_to_restart, cur_time_to_restart);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cur_active) {
|
return blend_input(0, p_time, p_seek, p_is_external_seeking, 1.0, FILTER_IGNORE, sync);
|
||||||
return blend_input(0, p_time, p_seek, p_is_external_seeking, 1.0, FILTER_IGNORE, sync);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool os_seek = p_seek;
|
bool os_seek = p_seek;
|
||||||
|
|
@ -349,10 +349,9 @@ double AnimationNodeOneShot::process(double p_time, bool p_seek, bool p_is_exter
|
||||||
if (mix == MIX_MODE_ADD) {
|
if (mix == MIX_MODE_ADD) {
|
||||||
main_rem = blend_input(0, p_time, p_seek, p_is_external_seeking, 1.0, FILTER_IGNORE, sync);
|
main_rem = blend_input(0, p_time, p_seek, p_is_external_seeking, 1.0, FILTER_IGNORE, sync);
|
||||||
} else {
|
} else {
|
||||||
main_rem = blend_input(0, p_time, p_seek, p_is_external_seeking, 1.0 - blend, FILTER_BLEND, sync);
|
main_rem = blend_input(0, p_time, p_seek, p_is_external_seeking, 1.0 - blend, FILTER_BLEND, sync); // Unlike below, processing this edge is a corner case.
|
||||||
}
|
}
|
||||||
|
double os_rem = blend_input(1, os_seek ? cur_time : p_time, os_seek, p_is_external_seeking, MAX(CMP_EPSILON, blend), FILTER_PASS, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge.
|
||||||
double os_rem = blend_input(1, os_seek ? cur_time : p_time, os_seek, p_is_external_seeking, blend, FILTER_PASS, true);
|
|
||||||
|
|
||||||
if (do_start) {
|
if (do_start) {
|
||||||
cur_remaining = os_rem;
|
cur_remaining = os_rem;
|
||||||
|
|
@ -769,17 +768,18 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_is_ex
|
||||||
blend = xfade_curve->sample(blend);
|
blend = xfade_curve->sample(blend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Blend values must be more than CMP_EPSILON to process discrete keys in edge.
|
||||||
if (from_start && !p_seek && switched) { //just switched, seek to start of current
|
if (from_start && !p_seek && switched) { //just switched, seek to start of current
|
||||||
rem = blend_input(cur_current, 0, true, p_is_external_seeking, 1.0 - blend, FILTER_IGNORE, true);
|
rem = blend_input(cur_current, 0, true, p_is_external_seeking, MAX(CMP_EPSILON, 1.0 - blend), FILTER_IGNORE, true);
|
||||||
} else {
|
} else {
|
||||||
rem = blend_input(cur_current, p_time, p_seek, p_is_external_seeking, 1.0 - blend, FILTER_IGNORE, true);
|
rem = blend_input(cur_current, p_time, p_seek, p_is_external_seeking, MAX(CMP_EPSILON, 1.0 - blend), FILTER_IGNORE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_seek) {
|
if (p_seek) {
|
||||||
blend_input(cur_prev, p_time, true, p_is_external_seeking, blend, FILTER_IGNORE, true);
|
blend_input(cur_prev, p_time, true, p_is_external_seeking, MAX(CMP_EPSILON, blend), FILTER_IGNORE, true);
|
||||||
cur_time = p_time;
|
cur_time = p_time;
|
||||||
} else {
|
} else {
|
||||||
blend_input(cur_prev, p_time, false, p_is_external_seeking, blend, FILTER_IGNORE, true);
|
blend_input(cur_prev, p_time, false, p_is_external_seeking, MAX(CMP_EPSILON, blend), FILTER_IGNORE, true);
|
||||||
cur_time += p_time;
|
cur_time += p_time;
|
||||||
cur_prev_xfading -= p_time;
|
cur_prev_xfading -= p_time;
|
||||||
if (cur_prev_xfading < 0) {
|
if (cur_prev_xfading < 0) {
|
||||||
|
|
|
||||||
|
|
@ -433,10 +433,10 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
|
||||||
if (current_curve.is_valid()) {
|
if (current_curve.is_valid()) {
|
||||||
fade_blend = current_curve->sample(fade_blend);
|
fade_blend = current_curve->sample(fade_blend);
|
||||||
}
|
}
|
||||||
float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_is_external_seeking, fade_blend, AnimationNode::FILTER_IGNORE, true);
|
float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_is_external_seeking, MAX(CMP_EPSILON, fade_blend), AnimationNode::FILTER_IGNORE, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge.
|
||||||
|
|
||||||
if (fading_from != StringName()) {
|
if (fading_from != StringName()) {
|
||||||
p_state_machine->blend_node(fading_from, p_state_machine->states[fading_from].node, p_time, p_seek, p_is_external_seeking, 1.0 - fade_blend, AnimationNode::FILTER_IGNORE, true);
|
p_state_machine->blend_node(fading_from, p_state_machine->states[fading_from].node, p_time, p_seek, p_is_external_seeking, MAX(CMP_EPSILON, 1.0 - fade_blend), AnimationNode::FILTER_IGNORE, true); // Blend values must be more than CMP_EPSILON to process discrete keys in edge.
|
||||||
}
|
}
|
||||||
|
|
||||||
//guess playback position
|
//guess playback position
|
||||||
|
|
@ -599,13 +599,11 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
|
||||||
|
|
||||||
current = next;
|
current = next;
|
||||||
|
|
||||||
|
len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_is_external_seeking, CMP_EPSILON, AnimationNode::FILTER_IGNORE, true); // Process next node's first key in here.
|
||||||
if (switch_mode == AnimationNodeStateMachineTransition::SWITCH_MODE_SYNC) {
|
if (switch_mode == AnimationNodeStateMachineTransition::SWITCH_MODE_SYNC) {
|
||||||
len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_is_external_seeking, 0, AnimationNode::FILTER_IGNORE, true);
|
|
||||||
pos_current = MIN(pos_current, len_current);
|
pos_current = MIN(pos_current, len_current);
|
||||||
p_state_machine->blend_node(current, p_state_machine->states[current].node, pos_current, true, p_is_external_seeking, 0, AnimationNode::FILTER_IGNORE, true);
|
p_state_machine->blend_node(current, p_state_machine->states[current].node, pos_current, true, p_is_external_seeking, 0, AnimationNode::FILTER_IGNORE, true);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
len_current = p_state_machine->blend_node(current, p_state_machine->states[current].node, 0, true, p_is_external_seeking, 0, AnimationNode::FILTER_IGNORE, true);
|
|
||||||
pos_current = 0;
|
pos_current = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -468,7 +468,7 @@ Variant AnimationPlayer::_post_process_key_value(const Ref<Animation> &p_anim, i
|
||||||
return p_value;
|
return p_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_prev_time, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started, Animation::LoopedFlag p_looped_flag) {
|
||||||
_ensure_node_caches(p_anim);
|
_ensure_node_caches(p_anim);
|
||||||
ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count());
|
ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count());
|
||||||
|
|
||||||
|
|
@ -683,7 +683,13 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
|
||||||
|
|
||||||
} else if (p_is_current && p_delta != 0) {
|
} else if (p_is_current && p_delta != 0) {
|
||||||
List<int> indices;
|
List<int> indices;
|
||||||
a->track_get_key_indices_in_range(i, p_time, p_delta, &indices, p_pingponged);
|
if (p_started) {
|
||||||
|
int first_key = a->track_find_key(i, p_prev_time, true);
|
||||||
|
if (first_key >= 0) {
|
||||||
|
indices.push_back(first_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a->track_get_key_indices_in_range(i, p_time, p_delta, &indices, p_looped_flag);
|
||||||
|
|
||||||
for (int &F : indices) {
|
for (int &F : indices) {
|
||||||
Variant value = a->track_get_key_value(i, F);
|
Variant value = a->track_get_key_value(i, F);
|
||||||
|
|
@ -742,7 +748,13 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
|
||||||
}
|
}
|
||||||
|
|
||||||
List<int> indices;
|
List<int> indices;
|
||||||
a->track_get_key_indices_in_range(i, p_time, p_delta, &indices, p_pingponged);
|
if (p_started) {
|
||||||
|
int first_key = a->track_find_key(i, p_prev_time, true);
|
||||||
|
if (first_key >= 0) {
|
||||||
|
indices.push_back(first_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a->track_get_key_indices_in_range(i, p_time, p_delta, &indices, p_looped_flag);
|
||||||
|
|
||||||
for (int &E : indices) {
|
for (int &E : indices) {
|
||||||
StringName method = a->method_track_get_name(i, E);
|
StringName method = a->method_track_get_name(i, E);
|
||||||
|
|
@ -832,7 +844,13 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
|
||||||
} else {
|
} else {
|
||||||
//find stuff to play
|
//find stuff to play
|
||||||
List<int> to_play;
|
List<int> to_play;
|
||||||
a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_pingponged);
|
if (p_started) {
|
||||||
|
int first_key = a->track_find_key(i, p_prev_time, true);
|
||||||
|
if (first_key >= 0) {
|
||||||
|
to_play.push_back(first_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_looped_flag);
|
||||||
if (to_play.size()) {
|
if (to_play.size()) {
|
||||||
int idx = to_play.back()->get();
|
int idx = to_play.back()->get();
|
||||||
|
|
||||||
|
|
@ -939,7 +957,13 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
|
||||||
} else {
|
} else {
|
||||||
//find stuff to play
|
//find stuff to play
|
||||||
List<int> to_play;
|
List<int> to_play;
|
||||||
a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_pingponged);
|
if (p_started) {
|
||||||
|
int first_key = a->track_find_key(i, p_prev_time, true);
|
||||||
|
if (first_key >= 0) {
|
||||||
|
to_play.push_back(first_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_looped_flag);
|
||||||
if (to_play.size()) {
|
if (to_play.size()) {
|
||||||
int idx = to_play.back()->get();
|
int idx = to_play.back()->get();
|
||||||
|
|
||||||
|
|
@ -969,7 +993,7 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, double p_delta,
|
||||||
double next_pos = cd.pos + delta;
|
double next_pos = cd.pos + delta;
|
||||||
|
|
||||||
real_t len = cd.from->animation->get_length();
|
real_t len = cd.from->animation->get_length();
|
||||||
int pingponged = 0;
|
Animation::LoopedFlag looped_flag = Animation::LOOPED_FLAG_NONE;
|
||||||
|
|
||||||
switch (cd.from->animation->get_loop_mode()) {
|
switch (cd.from->animation->get_loop_mode()) {
|
||||||
case Animation::LOOP_NONE: {
|
case Animation::LOOP_NONE: {
|
||||||
|
|
@ -998,44 +1022,33 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, double p_delta,
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Animation::LOOP_LINEAR: {
|
case Animation::LOOP_LINEAR: {
|
||||||
double looped_next_pos = Math::fposmod(next_pos, (double)len);
|
if (next_pos < 0 && cd.pos >= 0) {
|
||||||
if (looped_next_pos == 0 && next_pos != 0) {
|
looped_flag = Animation::LOOPED_FLAG_START;
|
||||||
// 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 (next_pos > len && cd.pos <= len) {
|
||||||
|
looped_flag = Animation::LOOPED_FLAG_END;
|
||||||
|
}
|
||||||
|
next_pos = Math::fposmod(next_pos, (double)len);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Animation::LOOP_PINGPONG: {
|
case Animation::LOOP_PINGPONG: {
|
||||||
if ((int)Math::floor(abs(next_pos - cd.pos) / len) % 2 == 0) {
|
if (next_pos < 0 && cd.pos >= 0) {
|
||||||
if (next_pos < 0 && cd.pos >= 0) {
|
cd.speed_scale *= -1.0;
|
||||||
cd.speed_scale *= -1.0;
|
looped_flag = Animation::LOOPED_FLAG_START;
|
||||||
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 (next_pos > len && cd.pos <= len) {
|
||||||
if (looped_next_pos == 0 && next_pos != 0) {
|
cd.speed_scale *= -1.0;
|
||||||
// Loop multiples of the length to it, rather than 0
|
looped_flag = Animation::LOOPED_FLAG_END;
|
||||||
// so state at time=length is previewable in the editor
|
|
||||||
next_pos = len;
|
|
||||||
} else {
|
|
||||||
next_pos = looped_next_pos;
|
|
||||||
}
|
}
|
||||||
|
next_pos = Math::pingpong(next_pos, (double)len);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_animation_process_animation(cd.from, cd.pos, next_pos, delta, p_blend, &cd == &playback.current, p_seeked, p_started, looped_flag);
|
||||||
cd.pos = next_pos;
|
cd.pos = next_pos;
|
||||||
|
|
||||||
_animation_process_animation(cd.from, cd.pos, delta, p_blend, &cd == &playback.current, p_seeked, p_started, pingponged);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationPlayer::_animation_process2(double p_delta, bool p_started) {
|
void AnimationPlayer::_animation_process2(double p_delta, bool p_started) {
|
||||||
|
|
|
||||||
|
|
@ -268,7 +268,7 @@ private:
|
||||||
|
|
||||||
NodePath root;
|
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_prev_time, double p_time, double p_delta, float p_interp, bool p_is_current = true, bool p_seeked = false, bool p_started = false, Animation::LoopedFlag p_looped_flag = Animation::LOOPED_FLAG_NONE);
|
||||||
|
|
||||||
void _ensure_node_caches(AnimationData *p_anim, Node *p_root_override = nullptr);
|
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);
|
void _animation_process_data(PlaybackData &cd, double p_delta, float p_blend, bool p_seeked, bool p_started);
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ void AnimationNode::get_child_nodes(List<ChildNode> *r_child_nodes) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationNode::blend_animation(const StringName &p_animation, double p_time, double p_delta, bool p_seeked, bool p_is_external_seeking, real_t p_blend, int p_pingponged) {
|
void AnimationNode::blend_animation(const StringName &p_animation, double p_time, double p_delta, bool p_seeked, bool p_is_external_seeking, real_t p_blend, Animation::LoopedFlag p_looped_flag) {
|
||||||
ERR_FAIL_COND(!state);
|
ERR_FAIL_COND(!state);
|
||||||
ERR_FAIL_COND(!state->player->has_animation(p_animation));
|
ERR_FAIL_COND(!state->player->has_animation(p_animation));
|
||||||
|
|
||||||
|
|
@ -112,7 +112,7 @@ void AnimationNode::blend_animation(const StringName &p_animation, double p_time
|
||||||
anim_state.time = p_time;
|
anim_state.time = p_time;
|
||||||
anim_state.animation = animation;
|
anim_state.animation = animation;
|
||||||
anim_state.seeked = p_seeked;
|
anim_state.seeked = p_seeked;
|
||||||
anim_state.pingponged = p_pingponged;
|
anim_state.looped_flag = p_looped_flag;
|
||||||
anim_state.is_external_seeking = p_is_external_seeking;
|
anim_state.is_external_seeking = p_is_external_seeking;
|
||||||
|
|
||||||
state->animation_states.push_back(anim_state);
|
state->animation_states.push_back(anim_state);
|
||||||
|
|
@ -413,7 +413,7 @@ void AnimationNode::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("_set_filters", "filters"), &AnimationNode::_set_filters);
|
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("_get_filters"), &AnimationNode::_get_filters);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("blend_animation", "animation", "time", "delta", "seeked", "is_external_seeking", "blend", "pingponged"), &AnimationNode::blend_animation, DEFVAL(0));
|
ClassDB::bind_method(D_METHOD("blend_animation", "animation", "time", "delta", "seeked", "is_external_seeking", "blend", "looped_flag"), &AnimationNode::blend_animation, DEFVAL(Animation::LOOPED_FLAG_NONE));
|
||||||
ClassDB::bind_method(D_METHOD("blend_node", "name", "node", "time", "seek", "is_external_seeking", "blend", "filter", "sync"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true));
|
ClassDB::bind_method(D_METHOD("blend_node", "name", "node", "time", "seek", "is_external_seeking", "blend", "filter", "sync"), &AnimationNode::blend_node, DEFVAL(FILTER_IGNORE), DEFVAL(true));
|
||||||
ClassDB::bind_method(D_METHOD("blend_input", "input_index", "time", "seek", "is_external_seeking", "blend", "filter", "sync"), &AnimationNode::blend_input, DEFVAL(FILTER_IGNORE), DEFVAL(true));
|
ClassDB::bind_method(D_METHOD("blend_input", "input_index", "time", "seek", "is_external_seeking", "blend", "filter", "sync"), &AnimationNode::blend_input, DEFVAL(FILTER_IGNORE), DEFVAL(true));
|
||||||
|
|
||||||
|
|
@ -1019,7 +1019,7 @@ void AnimationTree::_process_graph(double p_delta) {
|
||||||
double delta = as.delta;
|
double delta = as.delta;
|
||||||
real_t weight = as.blend;
|
real_t weight = as.blend;
|
||||||
bool seeked = as.seeked;
|
bool seeked = as.seeked;
|
||||||
int pingponged = as.pingponged;
|
Animation::LoopedFlag looped_flag = as.looped_flag;
|
||||||
bool is_external_seeking = as.is_external_seeking;
|
bool is_external_seeking = as.is_external_seeking;
|
||||||
#ifndef _3D_DISABLED
|
#ifndef _3D_DISABLED
|
||||||
bool backward = signbit(delta); // This flag is required only for the root motion since it calculates the difference between the previous and current frames.
|
bool backward = signbit(delta); // This flag is required only for the root motion since it calculates the difference between the previous and current frames.
|
||||||
|
|
@ -1391,7 +1391,7 @@ void AnimationTree::_process_graph(double p_delta) {
|
||||||
t->object->set_indexed(t->subpath, value);
|
t->object->set_indexed(t->subpath, value);
|
||||||
} else {
|
} else {
|
||||||
List<int> indices;
|
List<int> indices;
|
||||||
a->track_get_key_indices_in_range(i, time, delta, &indices, pingponged);
|
a->track_get_key_indices_in_range(i, time, delta, &indices, looped_flag);
|
||||||
for (int &F : indices) {
|
for (int &F : indices) {
|
||||||
Variant value = a->track_get_key_value(i, F);
|
Variant value = a->track_get_key_value(i, F);
|
||||||
value = _post_process_key_value(a, i, value, t->object);
|
value = _post_process_key_value(a, i, value, t->object);
|
||||||
|
|
@ -1416,7 +1416,7 @@ void AnimationTree::_process_graph(double p_delta) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
List<int> indices;
|
List<int> indices;
|
||||||
a->track_get_key_indices_in_range(i, time, delta, &indices, pingponged);
|
a->track_get_key_indices_in_range(i, time, delta, &indices, looped_flag);
|
||||||
for (int &F : indices) {
|
for (int &F : indices) {
|
||||||
StringName method = a->method_track_get_name(i, F);
|
StringName method = a->method_track_get_name(i, F);
|
||||||
Vector<Variant> params = a->method_track_get_params(i, F);
|
Vector<Variant> params = a->method_track_get_params(i, F);
|
||||||
|
|
@ -1479,7 +1479,7 @@ void AnimationTree::_process_graph(double p_delta) {
|
||||||
} else {
|
} else {
|
||||||
//find stuff to play
|
//find stuff to play
|
||||||
List<int> 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, looped_flag);
|
||||||
if (to_play.size()) {
|
if (to_play.size()) {
|
||||||
int idx = to_play.back()->get();
|
int idx = to_play.back()->get();
|
||||||
|
|
||||||
|
|
@ -1594,7 +1594,7 @@ void AnimationTree::_process_graph(double p_delta) {
|
||||||
} else {
|
} else {
|
||||||
//find stuff to play
|
//find stuff to play
|
||||||
List<int> 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, looped_flag);
|
||||||
if (to_play.size()) {
|
if (to_play.size()) {
|
||||||
int idx = to_play.back()->get();
|
int idx = to_play.back()->get();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ public:
|
||||||
real_t blend = 0.0;
|
real_t blend = 0.0;
|
||||||
bool seeked = false;
|
bool seeked = false;
|
||||||
bool is_external_seeking = false;
|
bool is_external_seeking = false;
|
||||||
int pingponged = 0;
|
Animation::LoopedFlag looped_flag = Animation::LOOPED_FLAG_NONE;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
|
|
@ -102,7 +102,7 @@ public:
|
||||||
double _blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_is_external_seeking, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_sync = true, real_t *r_max = nullptr);
|
double _blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_is_external_seeking, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_sync = true, real_t *r_max = nullptr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void blend_animation(const StringName &p_animation, double p_time, double p_delta, bool p_seeked, bool p_is_external_seeking, real_t p_blend, int p_pingponged = 0);
|
void blend_animation(const StringName &p_animation, double p_time, double p_delta, bool p_seeked, bool p_is_external_seeking, real_t p_blend, Animation::LoopedFlag p_looped_flag = Animation::LOOPED_FLAG_NONE);
|
||||||
double blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_is_external_seeking, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_sync = true);
|
double blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, double p_time, bool p_seek, bool p_is_external_seeking, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_sync = true);
|
||||||
double blend_input(int p_input, double p_time, bool p_seek, bool p_is_external_seeking, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_sync = true);
|
double blend_input(int p_input, double p_time, bool p_seek, bool p_is_external_seeking, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_sync = true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2726,40 +2726,60 @@ Animation::UpdateMode Animation::value_track_get_update_mode(int p_track) const
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void Animation::_track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices) const {
|
void Animation::_track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices, bool p_is_backward) const {
|
||||||
if (to_time == length) {
|
int len = p_array.size();
|
||||||
to_time = length + CMP_EPSILON; //include a little more if at the end
|
if (len == 0) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int to = _find(p_array, to_time);
|
int from = 0;
|
||||||
|
int to = len - 1;
|
||||||
|
|
||||||
// can't really send the events == time, will be sent in the next frame.
|
if (!p_is_backward) {
|
||||||
// if event>=len then it will probably never be requested by the anim player.
|
while (p_array[from].time < from_time || Math::is_equal_approx(p_array[from].time, from_time)) {
|
||||||
|
from++;
|
||||||
if (to >= 0 && p_array[to].time >= to_time) {
|
if (to < from) {
|
||||||
to--;
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (p_array[to].time > to_time && !Math::is_equal_approx(p_array[to].time, to_time)) {
|
||||||
|
to--;
|
||||||
|
if (to < from) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (p_array[from].time < from_time && !Math::is_equal_approx(p_array[from].time, from_time)) {
|
||||||
|
from++;
|
||||||
|
if (to < from) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (p_array[to].time > to_time || Math::is_equal_approx(p_array[to].time, to_time)) {
|
||||||
|
to--;
|
||||||
|
if (to < from) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (to < 0) {
|
if (from == to) {
|
||||||
return; // not bother
|
p_indices->push_back(from);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int from = _find(p_array, from_time);
|
if (!p_is_backward) {
|
||||||
|
for (int i = from; i <= to; i++) {
|
||||||
// position in the right first event.+
|
p_indices->push_back(i);
|
||||||
if (from < 0 || p_array[from].time < from_time) {
|
}
|
||||||
from++;
|
} else {
|
||||||
}
|
for (int i = to; i >= to; i--) {
|
||||||
|
p_indices->push_back(i);
|
||||||
int max = p_array.size();
|
}
|
||||||
|
|
||||||
for (int i = from; i <= to; i++) {
|
|
||||||
ERR_CONTINUE(i < 0 || i >= max); // shouldn't happen
|
|
||||||
p_indices->push_back(i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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, Animation::LoopedFlag p_looped_flag) const {
|
||||||
ERR_FAIL_INDEX(p_track, tracks.size());
|
ERR_FAIL_INDEX(p_track, tracks.size());
|
||||||
|
|
||||||
if (p_delta == 0) {
|
if (p_delta == 0) {
|
||||||
|
|
@ -2771,7 +2791,9 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
|
||||||
double from_time = p_time - p_delta;
|
double from_time = p_time - p_delta;
|
||||||
double to_time = p_time;
|
double to_time = p_time;
|
||||||
|
|
||||||
|
bool is_backward = false;
|
||||||
if (from_time > to_time) {
|
if (from_time > to_time) {
|
||||||
|
is_backward = true;
|
||||||
SWAP(from_time, to_time);
|
SWAP(from_time, to_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2800,7 +2822,10 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from_time > to_time) {
|
if (from_time > to_time) {
|
||||||
// handle loop by splitting
|
// Handle loop by splitting.
|
||||||
|
double anim_end = length + CMP_EPSILON;
|
||||||
|
double anim_start = -CMP_EPSILON;
|
||||||
|
|
||||||
switch (t->type) {
|
switch (t->type) {
|
||||||
case TYPE_POSITION_3D: {
|
case TYPE_POSITION_3D: {
|
||||||
const PositionTrack *tt = static_cast<const PositionTrack *>(t);
|
const PositionTrack *tt = static_cast<const PositionTrack *>(t);
|
||||||
|
|
@ -2808,8 +2833,13 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
|
||||||
_get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, p_indices);
|
_get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, p_indices);
|
||||||
_get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, to_time, p_indices);
|
_get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, to_time, p_indices);
|
||||||
} else {
|
} else {
|
||||||
_track_get_key_indices_in_range(tt->positions, from_time, length, p_indices);
|
if (!is_backward) {
|
||||||
_track_get_key_indices_in_range(tt->positions, 0, to_time, p_indices);
|
_track_get_key_indices_in_range(tt->positions, from_time, anim_end, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(tt->positions, anim_start, to_time, p_indices, is_backward);
|
||||||
|
} else {
|
||||||
|
_track_get_key_indices_in_range(tt->positions, anim_start, to_time, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(tt->positions, from_time, anim_end, p_indices, is_backward);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case TYPE_ROTATION_3D: {
|
case TYPE_ROTATION_3D: {
|
||||||
|
|
@ -2818,8 +2848,13 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
|
||||||
_get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, length, p_indices);
|
_get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, length, p_indices);
|
||||||
_get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, to_time, p_indices);
|
_get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, to_time, p_indices);
|
||||||
} else {
|
} else {
|
||||||
_track_get_key_indices_in_range(rt->rotations, from_time, length, p_indices);
|
if (!is_backward) {
|
||||||
_track_get_key_indices_in_range(rt->rotations, 0, to_time, p_indices);
|
_track_get_key_indices_in_range(rt->rotations, from_time, anim_end, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(rt->rotations, anim_start, to_time, p_indices, is_backward);
|
||||||
|
} else {
|
||||||
|
_track_get_key_indices_in_range(rt->rotations, anim_start, to_time, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(rt->rotations, from_time, anim_end, p_indices, is_backward);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case TYPE_SCALE_3D: {
|
case TYPE_SCALE_3D: {
|
||||||
|
|
@ -2828,8 +2863,13 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
|
||||||
_get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, length, p_indices);
|
_get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, length, p_indices);
|
||||||
_get_compressed_key_indices_in_range<3>(st->compressed_track, 0, to_time, p_indices);
|
_get_compressed_key_indices_in_range<3>(st->compressed_track, 0, to_time, p_indices);
|
||||||
} else {
|
} else {
|
||||||
_track_get_key_indices_in_range(st->scales, from_time, length, p_indices);
|
if (!is_backward) {
|
||||||
_track_get_key_indices_in_range(st->scales, 0, to_time, p_indices);
|
_track_get_key_indices_in_range(st->scales, from_time, anim_end, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(st->scales, anim_start, to_time, p_indices, is_backward);
|
||||||
|
} else {
|
||||||
|
_track_get_key_indices_in_range(st->scales, anim_start, to_time, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(st->scales, from_time, anim_end, p_indices, is_backward);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case TYPE_BLEND_SHAPE: {
|
case TYPE_BLEND_SHAPE: {
|
||||||
|
|
@ -2838,38 +2878,83 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
|
||||||
_get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, length, p_indices);
|
_get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, length, p_indices);
|
||||||
_get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, to_time, p_indices);
|
_get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, to_time, p_indices);
|
||||||
} else {
|
} else {
|
||||||
_track_get_key_indices_in_range(bst->blend_shapes, from_time, length, p_indices);
|
if (!is_backward) {
|
||||||
_track_get_key_indices_in_range(bst->blend_shapes, 0, to_time, p_indices);
|
_track_get_key_indices_in_range(bst->blend_shapes, from_time, anim_end, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(bst->blend_shapes, anim_start, to_time, p_indices, is_backward);
|
||||||
|
} else {
|
||||||
|
_track_get_key_indices_in_range(bst->blend_shapes, anim_start, to_time, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(bst->blend_shapes, from_time, anim_end, p_indices, is_backward);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case TYPE_VALUE: {
|
case TYPE_VALUE: {
|
||||||
const ValueTrack *vt = static_cast<const ValueTrack *>(t);
|
const ValueTrack *vt = static_cast<const ValueTrack *>(t);
|
||||||
_track_get_key_indices_in_range(vt->values, from_time, length, p_indices);
|
if (!is_backward) {
|
||||||
_track_get_key_indices_in_range(vt->values, 0, to_time, p_indices);
|
_track_get_key_indices_in_range(vt->values, from_time, anim_end, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(vt->values, anim_start, to_time, p_indices, is_backward);
|
||||||
|
} else {
|
||||||
|
_track_get_key_indices_in_range(vt->values, anim_start, to_time, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(vt->values, from_time, anim_end, p_indices, is_backward);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case TYPE_METHOD: {
|
case TYPE_METHOD: {
|
||||||
const MethodTrack *mt = static_cast<const MethodTrack *>(t);
|
const MethodTrack *mt = static_cast<const MethodTrack *>(t);
|
||||||
_track_get_key_indices_in_range(mt->methods, from_time, length, p_indices);
|
if (!is_backward) {
|
||||||
_track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices);
|
_track_get_key_indices_in_range(mt->methods, from_time, anim_end, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(mt->methods, anim_start, to_time, p_indices, is_backward);
|
||||||
|
} else {
|
||||||
|
_track_get_key_indices_in_range(mt->methods, anim_start, to_time, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(mt->methods, from_time, anim_end, p_indices, is_backward);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case TYPE_BEZIER: {
|
case TYPE_BEZIER: {
|
||||||
const BezierTrack *bz = static_cast<const BezierTrack *>(t);
|
const BezierTrack *bz = static_cast<const BezierTrack *>(t);
|
||||||
_track_get_key_indices_in_range(bz->values, from_time, length, p_indices);
|
if (!is_backward) {
|
||||||
_track_get_key_indices_in_range(bz->values, 0, to_time, p_indices);
|
_track_get_key_indices_in_range(bz->values, from_time, anim_end, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(bz->values, anim_start, to_time, p_indices, is_backward);
|
||||||
|
} else {
|
||||||
|
_track_get_key_indices_in_range(bz->values, anim_start, to_time, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(bz->values, from_time, anim_end, p_indices, is_backward);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case TYPE_AUDIO: {
|
case TYPE_AUDIO: {
|
||||||
const AudioTrack *ad = static_cast<const AudioTrack *>(t);
|
const AudioTrack *ad = static_cast<const AudioTrack *>(t);
|
||||||
_track_get_key_indices_in_range(ad->values, from_time, length, p_indices);
|
if (!is_backward) {
|
||||||
_track_get_key_indices_in_range(ad->values, 0, to_time, p_indices);
|
_track_get_key_indices_in_range(ad->values, from_time, anim_end, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(ad->values, anim_start, to_time, p_indices, is_backward);
|
||||||
|
} else {
|
||||||
|
_track_get_key_indices_in_range(ad->values, anim_start, to_time, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(ad->values, from_time, anim_end, p_indices, is_backward);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case TYPE_ANIMATION: {
|
case TYPE_ANIMATION: {
|
||||||
const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
|
const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
|
||||||
_track_get_key_indices_in_range(an->values, from_time, length, p_indices);
|
if (!is_backward) {
|
||||||
_track_get_key_indices_in_range(an->values, 0, to_time, p_indices);
|
_track_get_key_indices_in_range(an->values, from_time, anim_end, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(an->values, anim_start, to_time, p_indices, is_backward);
|
||||||
|
} else {
|
||||||
|
_track_get_key_indices_in_range(an->values, anim_start, to_time, p_indices, is_backward);
|
||||||
|
_track_get_key_indices_in_range(an->values, from_time, anim_end, p_indices, is_backward);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Not from_time > to_time but most recent of looping...
|
||||||
|
if (p_looped_flag != Animation::LOOPED_FLAG_NONE) {
|
||||||
|
if (!is_backward && Math::is_equal_approx(from_time, 0)) {
|
||||||
|
int edge = track_find_key(p_track, 0, true);
|
||||||
|
if (edge >= 0) {
|
||||||
|
p_indices->push_back(edge);
|
||||||
|
}
|
||||||
|
} else if (is_backward && Math::is_equal_approx(to_time, length)) {
|
||||||
|
int edge = track_find_key(p_track, length, true);
|
||||||
|
if (edge >= 0) {
|
||||||
|
p_indices->push_back(edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case LOOP_PINGPONG: {
|
case LOOP_PINGPONG: {
|
||||||
if (from_time > length || from_time < 0) {
|
if (from_time > length || from_time < 0) {
|
||||||
|
|
@ -2879,162 +2964,164 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
|
||||||
to_time = Math::pingpong(to_time, length);
|
to_time = Math::pingpong(to_time, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((int)Math::floor(abs(p_delta) / length) % 2 == 0) {
|
if (p_looped_flag == Animation::LOOPED_FLAG_START) {
|
||||||
if (p_pingponged == -1) {
|
// Handle loop by splitting.
|
||||||
// handle loop by splitting
|
switch (t->type) {
|
||||||
to_time = MAX(CMP_EPSILON, to_time); // To avoid overlapping keys at the turnaround point, one of the point will needs to be shifted slightly.
|
case TYPE_POSITION_3D: {
|
||||||
switch (t->type) {
|
const PositionTrack *tt = static_cast<const PositionTrack *>(t);
|
||||||
case TYPE_POSITION_3D: {
|
if (tt->compressed_track >= 0) {
|
||||||
const PositionTrack *tt = static_cast<const PositionTrack *>(t);
|
_get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, from_time, p_indices);
|
||||||
if (tt->compressed_track >= 0) {
|
_get_compressed_key_indices_in_range<3>(tt->compressed_track, CMP_EPSILON, to_time, p_indices);
|
||||||
_get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, from_time, p_indices);
|
} else {
|
||||||
_get_compressed_key_indices_in_range<3>(tt->compressed_track, CMP_EPSILON, to_time, p_indices);
|
_track_get_key_indices_in_range(tt->positions, 0, from_time, p_indices, true);
|
||||||
} else {
|
_track_get_key_indices_in_range(tt->positions, 0, to_time, p_indices, false);
|
||||||
_track_get_key_indices_in_range(tt->positions, 0, from_time, p_indices);
|
}
|
||||||
_track_get_key_indices_in_range(tt->positions, CMP_EPSILON, to_time, p_indices);
|
} break;
|
||||||
}
|
case TYPE_ROTATION_3D: {
|
||||||
} break;
|
const RotationTrack *rt = static_cast<const RotationTrack *>(t);
|
||||||
case TYPE_ROTATION_3D: {
|
if (rt->compressed_track >= 0) {
|
||||||
const RotationTrack *rt = static_cast<const RotationTrack *>(t);
|
_get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, from_time, p_indices);
|
||||||
if (rt->compressed_track >= 0) {
|
_get_compressed_key_indices_in_range<3>(rt->compressed_track, CMP_EPSILON, to_time, p_indices);
|
||||||
_get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, from_time, p_indices);
|
} else {
|
||||||
_get_compressed_key_indices_in_range<3>(rt->compressed_track, CMP_EPSILON, to_time, p_indices);
|
_track_get_key_indices_in_range(rt->rotations, 0, from_time, p_indices, true);
|
||||||
} else {
|
_track_get_key_indices_in_range(rt->rotations, 0, to_time, p_indices, false);
|
||||||
_track_get_key_indices_in_range(rt->rotations, 0, from_time, p_indices);
|
}
|
||||||
_track_get_key_indices_in_range(rt->rotations, CMP_EPSILON, to_time, p_indices);
|
} break;
|
||||||
}
|
case TYPE_SCALE_3D: {
|
||||||
} break;
|
const ScaleTrack *st = static_cast<const ScaleTrack *>(t);
|
||||||
case TYPE_SCALE_3D: {
|
if (st->compressed_track >= 0) {
|
||||||
const ScaleTrack *st = static_cast<const ScaleTrack *>(t);
|
_get_compressed_key_indices_in_range<3>(st->compressed_track, 0, from_time, p_indices);
|
||||||
if (st->compressed_track >= 0) {
|
_get_compressed_key_indices_in_range<3>(st->compressed_track, 0, to_time, p_indices);
|
||||||
_get_compressed_key_indices_in_range<3>(st->compressed_track, 0, from_time, p_indices);
|
} else {
|
||||||
_get_compressed_key_indices_in_range<3>(st->compressed_track, CMP_EPSILON, to_time, p_indices);
|
_track_get_key_indices_in_range(st->scales, 0, from_time, p_indices, true);
|
||||||
} else {
|
_track_get_key_indices_in_range(st->scales, 0, to_time, p_indices, false);
|
||||||
_track_get_key_indices_in_range(st->scales, 0, from_time, p_indices);
|
}
|
||||||
_track_get_key_indices_in_range(st->scales, CMP_EPSILON, to_time, p_indices);
|
} break;
|
||||||
}
|
case TYPE_BLEND_SHAPE: {
|
||||||
} break;
|
const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t);
|
||||||
case TYPE_BLEND_SHAPE: {
|
if (bst->compressed_track >= 0) {
|
||||||
const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t);
|
_get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, from_time, p_indices);
|
||||||
if (bst->compressed_track >= 0) {
|
_get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, to_time, p_indices);
|
||||||
_get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, from_time, p_indices);
|
} else {
|
||||||
_get_compressed_key_indices_in_range<1>(bst->compressed_track, CMP_EPSILON, to_time, p_indices);
|
_track_get_key_indices_in_range(bst->blend_shapes, 0, from_time, p_indices, true);
|
||||||
} else {
|
_track_get_key_indices_in_range(bst->blend_shapes, 0, to_time, p_indices, false);
|
||||||
_track_get_key_indices_in_range(bst->blend_shapes, 0, from_time, p_indices);
|
}
|
||||||
_track_get_key_indices_in_range(bst->blend_shapes, CMP_EPSILON, to_time, p_indices);
|
} break;
|
||||||
}
|
case TYPE_VALUE: {
|
||||||
} break;
|
const ValueTrack *vt = static_cast<const ValueTrack *>(t);
|
||||||
case TYPE_VALUE: {
|
_track_get_key_indices_in_range(vt->values, 0, from_time, p_indices, true);
|
||||||
const ValueTrack *vt = static_cast<const ValueTrack *>(t);
|
_track_get_key_indices_in_range(vt->values, 0, to_time, p_indices, false);
|
||||||
_track_get_key_indices_in_range(vt->values, 0, from_time, p_indices);
|
} break;
|
||||||
_track_get_key_indices_in_range(vt->values, CMP_EPSILON, to_time, p_indices);
|
case TYPE_METHOD: {
|
||||||
} break;
|
const MethodTrack *mt = static_cast<const MethodTrack *>(t);
|
||||||
case TYPE_METHOD: {
|
_track_get_key_indices_in_range(mt->methods, 0, from_time, p_indices, true);
|
||||||
const MethodTrack *mt = static_cast<const MethodTrack *>(t);
|
_track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices, false);
|
||||||
_track_get_key_indices_in_range(mt->methods, 0, from_time, p_indices);
|
} break;
|
||||||
_track_get_key_indices_in_range(mt->methods, CMP_EPSILON, to_time, p_indices);
|
case TYPE_BEZIER: {
|
||||||
} break;
|
const BezierTrack *bz = static_cast<const BezierTrack *>(t);
|
||||||
case TYPE_BEZIER: {
|
_track_get_key_indices_in_range(bz->values, 0, from_time, p_indices, true);
|
||||||
const BezierTrack *bz = static_cast<const BezierTrack *>(t);
|
_track_get_key_indices_in_range(bz->values, 0, to_time, p_indices, false);
|
||||||
_track_get_key_indices_in_range(bz->values, 0, from_time, p_indices);
|
} break;
|
||||||
_track_get_key_indices_in_range(bz->values, CMP_EPSILON, to_time, p_indices);
|
case TYPE_AUDIO: {
|
||||||
} break;
|
const AudioTrack *ad = static_cast<const AudioTrack *>(t);
|
||||||
case TYPE_AUDIO: {
|
_track_get_key_indices_in_range(ad->values, 0, from_time, p_indices, true);
|
||||||
const AudioTrack *ad = static_cast<const AudioTrack *>(t);
|
_track_get_key_indices_in_range(ad->values, 0, to_time, p_indices, false);
|
||||||
_track_get_key_indices_in_range(ad->values, 0, from_time, p_indices);
|
} break;
|
||||||
_track_get_key_indices_in_range(ad->values, CMP_EPSILON, to_time, p_indices);
|
case TYPE_ANIMATION: {
|
||||||
} break;
|
const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
|
||||||
case TYPE_ANIMATION: {
|
_track_get_key_indices_in_range(an->values, 0, from_time, p_indices, true);
|
||||||
const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
|
_track_get_key_indices_in_range(an->values, 0, to_time, p_indices, false);
|
||||||
_track_get_key_indices_in_range(an->values, 0, from_time, p_indices);
|
} break;
|
||||||
_track_get_key_indices_in_range(an->values, CMP_EPSILON, to_time, p_indices);
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (p_pingponged == 1) {
|
return;
|
||||||
// handle loop by splitting
|
}
|
||||||
to_time = MIN(length - CMP_EPSILON, to_time);
|
if (p_looped_flag == Animation::LOOPED_FLAG_END) {
|
||||||
switch (t->type) {
|
// Handle loop by splitting.
|
||||||
case TYPE_POSITION_3D: {
|
switch (t->type) {
|
||||||
const PositionTrack *tt = static_cast<const PositionTrack *>(t);
|
case TYPE_POSITION_3D: {
|
||||||
if (tt->compressed_track >= 0) {
|
const PositionTrack *tt = static_cast<const PositionTrack *>(t);
|
||||||
_get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, p_indices);
|
if (tt->compressed_track >= 0) {
|
||||||
_get_compressed_key_indices_in_range<3>(tt->compressed_track, to_time, length - CMP_EPSILON, p_indices);
|
_get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, p_indices);
|
||||||
} else {
|
_get_compressed_key_indices_in_range<3>(tt->compressed_track, to_time, length, p_indices);
|
||||||
_track_get_key_indices_in_range(tt->positions, from_time, length, p_indices);
|
} else {
|
||||||
_track_get_key_indices_in_range(tt->positions, to_time, length - CMP_EPSILON, p_indices);
|
_track_get_key_indices_in_range(tt->positions, from_time, length, p_indices, false);
|
||||||
}
|
_track_get_key_indices_in_range(tt->positions, to_time, length, p_indices, true);
|
||||||
} break;
|
}
|
||||||
case TYPE_ROTATION_3D: {
|
} break;
|
||||||
const RotationTrack *rt = static_cast<const RotationTrack *>(t);
|
case TYPE_ROTATION_3D: {
|
||||||
if (rt->compressed_track >= 0) {
|
const RotationTrack *rt = static_cast<const RotationTrack *>(t);
|
||||||
_get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, length, p_indices);
|
if (rt->compressed_track >= 0) {
|
||||||
_get_compressed_key_indices_in_range<3>(rt->compressed_track, to_time, length, p_indices);
|
_get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, length, p_indices);
|
||||||
} else {
|
_get_compressed_key_indices_in_range<3>(rt->compressed_track, to_time, length, p_indices);
|
||||||
_track_get_key_indices_in_range(rt->rotations, from_time, length, p_indices);
|
} else {
|
||||||
_track_get_key_indices_in_range(rt->rotations, to_time, length - CMP_EPSILON, p_indices);
|
_track_get_key_indices_in_range(rt->rotations, from_time, length, p_indices, false);
|
||||||
}
|
_track_get_key_indices_in_range(rt->rotations, to_time, length, p_indices, true);
|
||||||
} break;
|
}
|
||||||
case TYPE_SCALE_3D: {
|
} break;
|
||||||
const ScaleTrack *st = static_cast<const ScaleTrack *>(t);
|
case TYPE_SCALE_3D: {
|
||||||
if (st->compressed_track >= 0) {
|
const ScaleTrack *st = static_cast<const ScaleTrack *>(t);
|
||||||
_get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, length, p_indices);
|
if (st->compressed_track >= 0) {
|
||||||
_get_compressed_key_indices_in_range<3>(st->compressed_track, to_time, length, p_indices);
|
_get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, length, p_indices);
|
||||||
} else {
|
_get_compressed_key_indices_in_range<3>(st->compressed_track, to_time, length, p_indices);
|
||||||
_track_get_key_indices_in_range(st->scales, from_time, length, p_indices);
|
} else {
|
||||||
_track_get_key_indices_in_range(st->scales, to_time, length - CMP_EPSILON, p_indices);
|
_track_get_key_indices_in_range(st->scales, from_time, length, p_indices, false);
|
||||||
}
|
_track_get_key_indices_in_range(st->scales, to_time, length, p_indices, true);
|
||||||
} break;
|
}
|
||||||
case TYPE_BLEND_SHAPE: {
|
} break;
|
||||||
const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t);
|
case TYPE_BLEND_SHAPE: {
|
||||||
if (bst->compressed_track >= 0) {
|
const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t);
|
||||||
_get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, length, p_indices);
|
if (bst->compressed_track >= 0) {
|
||||||
_get_compressed_key_indices_in_range<1>(bst->compressed_track, to_time, length - CMP_EPSILON, p_indices);
|
_get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, length, p_indices);
|
||||||
} else {
|
_get_compressed_key_indices_in_range<1>(bst->compressed_track, to_time, length - CMP_EPSILON, p_indices);
|
||||||
_track_get_key_indices_in_range(bst->blend_shapes, from_time, length, p_indices);
|
} else {
|
||||||
_track_get_key_indices_in_range(bst->blend_shapes, to_time, length - CMP_EPSILON, p_indices);
|
_track_get_key_indices_in_range(bst->blend_shapes, from_time, length, p_indices, false);
|
||||||
}
|
_track_get_key_indices_in_range(bst->blend_shapes, to_time, length, p_indices, true);
|
||||||
} break;
|
}
|
||||||
case TYPE_VALUE: {
|
} break;
|
||||||
const ValueTrack *vt = static_cast<const ValueTrack *>(t);
|
case TYPE_VALUE: {
|
||||||
_track_get_key_indices_in_range(vt->values, from_time, length, p_indices);
|
const ValueTrack *vt = static_cast<const ValueTrack *>(t);
|
||||||
_track_get_key_indices_in_range(vt->values, to_time, length - CMP_EPSILON, p_indices);
|
_track_get_key_indices_in_range(vt->values, from_time, length, p_indices, false);
|
||||||
} break;
|
_track_get_key_indices_in_range(vt->values, to_time, length, p_indices, true);
|
||||||
case TYPE_METHOD: {
|
} break;
|
||||||
const MethodTrack *mt = static_cast<const MethodTrack *>(t);
|
case TYPE_METHOD: {
|
||||||
_track_get_key_indices_in_range(mt->methods, from_time, length, p_indices);
|
const MethodTrack *mt = static_cast<const MethodTrack *>(t);
|
||||||
_track_get_key_indices_in_range(mt->methods, to_time, length - CMP_EPSILON, p_indices);
|
_track_get_key_indices_in_range(mt->methods, from_time, length, p_indices, false);
|
||||||
} break;
|
_track_get_key_indices_in_range(mt->methods, to_time, length, p_indices, true);
|
||||||
case TYPE_BEZIER: {
|
} break;
|
||||||
const BezierTrack *bz = static_cast<const BezierTrack *>(t);
|
case TYPE_BEZIER: {
|
||||||
_track_get_key_indices_in_range(bz->values, from_time, length, p_indices);
|
const BezierTrack *bz = static_cast<const BezierTrack *>(t);
|
||||||
_track_get_key_indices_in_range(bz->values, to_time, length - CMP_EPSILON, p_indices);
|
_track_get_key_indices_in_range(bz->values, from_time, length, p_indices, false);
|
||||||
} break;
|
_track_get_key_indices_in_range(bz->values, to_time, length, p_indices, true);
|
||||||
case TYPE_AUDIO: {
|
} break;
|
||||||
const AudioTrack *ad = static_cast<const AudioTrack *>(t);
|
case TYPE_AUDIO: {
|
||||||
_track_get_key_indices_in_range(ad->values, from_time, length, p_indices);
|
const AudioTrack *ad = static_cast<const AudioTrack *>(t);
|
||||||
_track_get_key_indices_in_range(ad->values, to_time, length - CMP_EPSILON, p_indices);
|
_track_get_key_indices_in_range(ad->values, from_time, length, p_indices, false);
|
||||||
} break;
|
_track_get_key_indices_in_range(ad->values, to_time, length, p_indices, true);
|
||||||
case TYPE_ANIMATION: {
|
} break;
|
||||||
const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
|
case TYPE_ANIMATION: {
|
||||||
_track_get_key_indices_in_range(an->values, from_time, length, p_indices);
|
const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
|
||||||
_track_get_key_indices_in_range(an->values, to_time, length - CMP_EPSILON, p_indices);
|
_track_get_key_indices_in_range(an->values, from_time, length, p_indices, false);
|
||||||
} break;
|
_track_get_key_indices_in_range(an->values, to_time, length, p_indices, true);
|
||||||
}
|
} break;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The edge will be pingponged in the next frame and processed there, so let's ignore it now...
|
||||||
|
if (!is_backward && Math::is_equal_approx(to_time, length)) {
|
||||||
|
to_time = length - CMP_EPSILON;
|
||||||
|
} else if (is_backward && Math::is_equal_approx(from_time, 0)) {
|
||||||
|
from_time = CMP_EPSILON;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (t->type) {
|
switch (t->type) {
|
||||||
case TYPE_POSITION_3D: {
|
case TYPE_POSITION_3D: {
|
||||||
const PositionTrack *tt = static_cast<const PositionTrack *>(t);
|
const PositionTrack *tt = static_cast<const PositionTrack *>(t);
|
||||||
if (tt->compressed_track >= 0) {
|
if (tt->compressed_track >= 0) {
|
||||||
_get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, to_time - from_time, p_indices);
|
_get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, to_time - from_time, p_indices);
|
||||||
} else {
|
} else {
|
||||||
_track_get_key_indices_in_range(tt->positions, from_time, to_time, p_indices);
|
_track_get_key_indices_in_range(tt->positions, from_time, to_time, p_indices, is_backward);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case TYPE_ROTATION_3D: {
|
case TYPE_ROTATION_3D: {
|
||||||
|
|
@ -3042,7 +3129,7 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
|
||||||
if (rt->compressed_track >= 0) {
|
if (rt->compressed_track >= 0) {
|
||||||
_get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, to_time - from_time, p_indices);
|
_get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, to_time - from_time, p_indices);
|
||||||
} else {
|
} else {
|
||||||
_track_get_key_indices_in_range(rt->rotations, from_time, to_time, p_indices);
|
_track_get_key_indices_in_range(rt->rotations, from_time, to_time, p_indices, is_backward);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case TYPE_SCALE_3D: {
|
case TYPE_SCALE_3D: {
|
||||||
|
|
@ -3050,7 +3137,7 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
|
||||||
if (st->compressed_track >= 0) {
|
if (st->compressed_track >= 0) {
|
||||||
_get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, to_time - from_time, p_indices);
|
_get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, to_time - from_time, p_indices);
|
||||||
} else {
|
} else {
|
||||||
_track_get_key_indices_in_range(st->scales, from_time, to_time, p_indices);
|
_track_get_key_indices_in_range(st->scales, from_time, to_time, p_indices, is_backward);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case TYPE_BLEND_SHAPE: {
|
case TYPE_BLEND_SHAPE: {
|
||||||
|
|
@ -3058,28 +3145,28 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
|
||||||
if (bst->compressed_track >= 0) {
|
if (bst->compressed_track >= 0) {
|
||||||
_get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, to_time - from_time, p_indices);
|
_get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, to_time - from_time, p_indices);
|
||||||
} else {
|
} else {
|
||||||
_track_get_key_indices_in_range(bst->blend_shapes, from_time, to_time, p_indices);
|
_track_get_key_indices_in_range(bst->blend_shapes, from_time, to_time, p_indices, is_backward);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case TYPE_VALUE: {
|
case TYPE_VALUE: {
|
||||||
const ValueTrack *vt = static_cast<const ValueTrack *>(t);
|
const ValueTrack *vt = static_cast<const ValueTrack *>(t);
|
||||||
_track_get_key_indices_in_range(vt->values, from_time, to_time, p_indices);
|
_track_get_key_indices_in_range(vt->values, from_time, to_time, p_indices, is_backward);
|
||||||
} break;
|
} break;
|
||||||
case TYPE_METHOD: {
|
case TYPE_METHOD: {
|
||||||
const MethodTrack *mt = static_cast<const MethodTrack *>(t);
|
const MethodTrack *mt = static_cast<const MethodTrack *>(t);
|
||||||
_track_get_key_indices_in_range(mt->methods, from_time, to_time, p_indices);
|
_track_get_key_indices_in_range(mt->methods, from_time, to_time, p_indices, is_backward);
|
||||||
} break;
|
} break;
|
||||||
case TYPE_BEZIER: {
|
case TYPE_BEZIER: {
|
||||||
const BezierTrack *bz = static_cast<const BezierTrack *>(t);
|
const BezierTrack *bz = static_cast<const BezierTrack *>(t);
|
||||||
_track_get_key_indices_in_range(bz->values, from_time, to_time, p_indices);
|
_track_get_key_indices_in_range(bz->values, from_time, to_time, p_indices, is_backward);
|
||||||
} break;
|
} break;
|
||||||
case TYPE_AUDIO: {
|
case TYPE_AUDIO: {
|
||||||
const AudioTrack *ad = static_cast<const AudioTrack *>(t);
|
const AudioTrack *ad = static_cast<const AudioTrack *>(t);
|
||||||
_track_get_key_indices_in_range(ad->values, from_time, to_time, p_indices);
|
_track_get_key_indices_in_range(ad->values, from_time, to_time, p_indices, is_backward);
|
||||||
} break;
|
} break;
|
||||||
case TYPE_ANIMATION: {
|
case TYPE_ANIMATION: {
|
||||||
const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
|
const AnimationTrack *an = static_cast<const AnimationTrack *>(t);
|
||||||
_track_get_key_indices_in_range(an->values, from_time, to_time, p_indices);
|
_track_get_key_indices_in_range(an->values, from_time, to_time, p_indices, is_backward);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3815,6 +3902,10 @@ void Animation::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(LOOP_NONE);
|
BIND_ENUM_CONSTANT(LOOP_NONE);
|
||||||
BIND_ENUM_CONSTANT(LOOP_LINEAR);
|
BIND_ENUM_CONSTANT(LOOP_LINEAR);
|
||||||
BIND_ENUM_CONSTANT(LOOP_PINGPONG);
|
BIND_ENUM_CONSTANT(LOOP_PINGPONG);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(LOOPED_FLAG_NONE);
|
||||||
|
BIND_ENUM_CONSTANT(LOOPED_FLAG_END);
|
||||||
|
BIND_ENUM_CONSTANT(LOOPED_FLAG_START);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::clear() {
|
void Animation::clear() {
|
||||||
|
|
@ -5798,7 +5889,8 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Animation::Animation() {}
|
Animation::Animation() {
|
||||||
|
}
|
||||||
|
|
||||||
Animation::~Animation() {
|
Animation::~Animation() {
|
||||||
for (int i = 0; i < tracks.size(); i++) {
|
for (int i = 0; i < tracks.size(); i++) {
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,12 @@ public:
|
||||||
LOOP_PINGPONG,
|
LOOP_PINGPONG,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum LoopedFlag {
|
||||||
|
LOOPED_FLAG_NONE,
|
||||||
|
LOOPED_FLAG_END,
|
||||||
|
LOOPED_FLAG_START,
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
enum HandleMode {
|
enum HandleMode {
|
||||||
HANDLE_MODE_FREE,
|
HANDLE_MODE_FREE,
|
||||||
|
|
@ -250,12 +256,11 @@ private:
|
||||||
_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, bool p_backward = false) const;
|
||||||
|
|
||||||
template <class T>
|
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;
|
_FORCE_INLINE_ void _track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices, bool p_is_backward) const;
|
||||||
|
|
||||||
double length = 1.0;
|
double length = 1.0;
|
||||||
real_t step = 0.1;
|
real_t step = 0.1;
|
||||||
LoopMode loop_mode = LOOP_NONE;
|
LoopMode loop_mode = LOOP_NONE;
|
||||||
int pingponged = 0;
|
|
||||||
|
|
||||||
/* Animation compression page format (version 1):
|
/* Animation compression page format (version 1):
|
||||||
*
|
*
|
||||||
|
|
@ -454,7 +459,7 @@ public:
|
||||||
|
|
||||||
void copy_track(int p_track, Ref<Animation> p_to_animation);
|
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, Animation::LoopedFlag p_looped_flag = Animation::LOOPED_FLAG_NONE) const;
|
||||||
|
|
||||||
void set_length(real_t p_length);
|
void set_length(real_t p_length);
|
||||||
real_t get_length() const;
|
real_t get_length() const;
|
||||||
|
|
@ -484,6 +489,7 @@ VARIANT_ENUM_CAST(Animation::TrackType);
|
||||||
VARIANT_ENUM_CAST(Animation::InterpolationType);
|
VARIANT_ENUM_CAST(Animation::InterpolationType);
|
||||||
VARIANT_ENUM_CAST(Animation::UpdateMode);
|
VARIANT_ENUM_CAST(Animation::UpdateMode);
|
||||||
VARIANT_ENUM_CAST(Animation::LoopMode);
|
VARIANT_ENUM_CAST(Animation::LoopMode);
|
||||||
|
VARIANT_ENUM_CAST(Animation::LoopedFlag);
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
VARIANT_ENUM_CAST(Animation::HandleMode);
|
VARIANT_ENUM_CAST(Animation::HandleMode);
|
||||||
VARIANT_ENUM_CAST(Animation::HandleSetMode);
|
VARIANT_ENUM_CAST(Animation::HandleSetMode);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue