Expose interpolation methods for 3D track in Animation class

This commit is contained in:
Silc Renew 2023-02-21 11:26:23 +09:00 committed by Silc Lizard (Tokage) Renew
parent 14c582bca8
commit fac8a918f9
11 changed files with 193 additions and 116 deletions

View file

@ -228,6 +228,14 @@
Inserts a key in a given blend shape track. Returns the key index.
</description>
</method>
<method name="blend_shape_track_interpolate" qualifiers="const">
<return type="float" />
<param index="0" name="track_idx" type="int" />
<param index="1" name="time_sec" type="float" />
<description>
Returns the interpolated blend shape value at the given time (in seconds). The [param track_idx] must be the index of a blend shape track.
</description>
</method>
<method name="clear">
<return type="void" />
<description>
@ -291,6 +299,14 @@
Inserts a key in a given 3D position track. Returns the key index.
</description>
</method>
<method name="position_track_interpolate" qualifiers="const">
<return type="Vector3" />
<param index="0" name="track_idx" type="int" />
<param index="1" name="time_sec" type="float" />
<description>
Returns the interpolated position value at the given time (in seconds). The [param track_idx] must be the index of a 3D position track.
</description>
</method>
<method name="remove_track">
<return type="void" />
<param index="0" name="track_idx" type="int" />
@ -307,6 +323,14 @@
Inserts a key in a given 3D rotation track. Returns the key index.
</description>
</method>
<method name="rotation_track_interpolate" qualifiers="const">
<return type="Quaternion" />
<param index="0" name="track_idx" type="int" />
<param index="1" name="time_sec" type="float" />
<description>
Returns the interpolated rotation value at the given time (in seconds). The [param track_idx] must be the index of a 3D rotation track.
</description>
</method>
<method name="scale_track_insert_key">
<return type="int" />
<param index="0" name="track_idx" type="int" />
@ -316,6 +340,14 @@
Inserts a key in a given 3D scale track. Returns the key index.
</description>
</method>
<method name="scale_track_interpolate" qualifiers="const">
<return type="Vector3" />
<param index="0" name="track_idx" type="int" />
<param index="1" name="time_sec" type="float" />
<description>
Returns the interpolated scale value at the given time (in seconds). The [param track_idx] must be the index of a 3D scale track.
</description>
</method>
<method name="track_find_key" qualifiers="const">
<return type="int" />
<param index="0" name="track_idx" type="int" />

View file

@ -300,7 +300,7 @@
<member name="animate_physical_bones" type="bool" setter="set_animate_physical_bones" getter="get_animate_physical_bones" default="true">
</member>
<member name="motion_scale" type="float" setter="set_motion_scale" getter="get_motion_scale" default="1.0">
Multiplies the position 3D track animation.
Multiplies the 3D position track animation.
[b]Note:[/b] Unless this value is [code]1.0[/code], the key value in animation will not match the actual position value.
</member>
<member name="show_rest_only" type="bool" setter="set_show_rest_only" getter="is_show_rest_only" default="false">

View file

@ -6084,7 +6084,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
Pair<real_t, Variant> keydata;
keydata.first = delta_t;
Vector3 v;
animation->position_track_interpolate(i, delta_t, &v);
animation->try_position_track_interpolate(i, delta_t, &v);
keydata.second = v;
insert_queue_new.append(keydata);
}
@ -6094,7 +6094,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
Pair<real_t, Variant> keydata;
keydata.first = delta_t;
Quaternion v;
animation->rotation_track_interpolate(i, delta_t, &v);
animation->try_rotation_track_interpolate(i, delta_t, &v);
keydata.second = v;
insert_queue_new.append(keydata);
}
@ -6104,7 +6104,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
Pair<real_t, Variant> keydata;
keydata.first = delta_t;
Vector3 v;
animation->scale_track_interpolate(i, delta_t, &v);
animation->try_scale_track_interpolate(i, delta_t, &v);
keydata.second = v;
insert_queue_new.append(keydata);
}
@ -6114,7 +6114,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
Pair<real_t, Variant> keydata;
keydata.first = delta_t;
float v;
animation->blend_shape_track_interpolate(i, delta_t, &v);
animation->try_blend_shape_track_interpolate(i, delta_t, &v);
keydata.second = v;
insert_queue_new.append(keydata);
}
@ -6760,7 +6760,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
bake_fps->set_max(999);
bake_fps->set_step(1);
bake_fps->set_value(30); // Default
bake_grid->add_child(memnew(Label(TTR("Pos/Rot/Scl3D Track:"))));
bake_grid->add_child(memnew(Label(TTR("3D Pos/Rot/Scl Track:"))));
bake_grid->add_child(bake_trs);
bake_grid->add_child(memnew(Label(TTR("Blendshape Track:"))));
bake_grid->add_child(bake_blendshape);

View file

@ -1455,22 +1455,22 @@ void ResourceImporterScene::_create_slices(AnimationPlayer *ap, Ref<Animation> a
if (kt > (from + 0.01) && k > 0) {
if (anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
Vector3 p;
anim->position_track_interpolate(j, from, &p);
anim->try_position_track_interpolate(j, from, &p);
new_anim->position_track_insert_key(dtrack, 0, p);
} else if (anim->track_get_type(j) == Animation::TYPE_ROTATION_3D) {
Quaternion r;
anim->rotation_track_interpolate(j, from, &r);
anim->try_rotation_track_interpolate(j, from, &r);
new_anim->rotation_track_insert_key(dtrack, 0, r);
} else if (anim->track_get_type(j) == Animation::TYPE_SCALE_3D) {
Vector3 s;
anim->scale_track_interpolate(j, from, &s);
anim->try_scale_track_interpolate(j, from, &s);
new_anim->scale_track_insert_key(dtrack, 0, s);
} else if (anim->track_get_type(j) == Animation::TYPE_VALUE) {
Variant var = anim->value_track_interpolate(j, from);
new_anim->track_insert_key(dtrack, 0, var);
} else if (anim->track_get_type(j) == Animation::TYPE_BLEND_SHAPE) {
float interp;
anim->blend_shape_track_interpolate(j, from, &interp);
anim->try_blend_shape_track_interpolate(j, from, &interp);
new_anim->blend_shape_track_insert_key(dtrack, 0, interp);
}
}
@ -1501,22 +1501,22 @@ void ResourceImporterScene::_create_slices(AnimationPlayer *ap, Ref<Animation> a
if (dtrack != -1 && kt >= to) {
if (anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
Vector3 p;
anim->position_track_interpolate(j, to, &p);
anim->try_position_track_interpolate(j, to, &p);
new_anim->position_track_insert_key(dtrack, to - from, p);
} else if (anim->track_get_type(j) == Animation::TYPE_ROTATION_3D) {
Quaternion r;
anim->rotation_track_interpolate(j, to, &r);
anim->try_rotation_track_interpolate(j, to, &r);
new_anim->rotation_track_insert_key(dtrack, to - from, r);
} else if (anim->track_get_type(j) == Animation::TYPE_SCALE_3D) {
Vector3 s;
anim->scale_track_interpolate(j, to, &s);
anim->try_scale_track_interpolate(j, to, &s);
new_anim->scale_track_insert_key(dtrack, to - from, s);
} else if (anim->track_get_type(j) == Animation::TYPE_VALUE) {
Variant var = anim->value_track_interpolate(j, to);
new_anim->track_insert_key(dtrack, to - from, var);
} else if (anim->track_get_type(j) == Animation::TYPE_BLEND_SHAPE) {
float interp;
anim->blend_shape_track_interpolate(j, to, &interp);
anim->try_blend_shape_track_interpolate(j, to, &interp);
new_anim->blend_shape_track_insert_key(dtrack, to - from, interp);
}
}
@ -1528,21 +1528,21 @@ void ResourceImporterScene::_create_slices(AnimationPlayer *ap, Ref<Animation> a
new_anim->track_set_path(dtrack, anim->track_get_path(j));
if (anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
Vector3 p;
anim->position_track_interpolate(j, from, &p);
anim->try_position_track_interpolate(j, from, &p);
new_anim->position_track_insert_key(dtrack, 0, p);
anim->position_track_interpolate(j, to, &p);
anim->try_position_track_interpolate(j, to, &p);
new_anim->position_track_insert_key(dtrack, to - from, p);
} else if (anim->track_get_type(j) == Animation::TYPE_ROTATION_3D) {
Quaternion r;
anim->rotation_track_interpolate(j, from, &r);
anim->try_rotation_track_interpolate(j, from, &r);
new_anim->rotation_track_insert_key(dtrack, 0, r);
anim->rotation_track_interpolate(j, to, &r);
anim->try_rotation_track_interpolate(j, to, &r);
new_anim->rotation_track_insert_key(dtrack, to - from, r);
} else if (anim->track_get_type(j) == Animation::TYPE_SCALE_3D) {
Vector3 s;
anim->scale_track_interpolate(j, from, &s);
anim->try_scale_track_interpolate(j, from, &s);
new_anim->scale_track_insert_key(dtrack, 0, s);
anim->scale_track_interpolate(j, to, &s);
anim->try_scale_track_interpolate(j, to, &s);
new_anim->scale_track_insert_key(dtrack, to - from, s);
} else if (anim->track_get_type(j) == Animation::TYPE_VALUE) {
Variant var = anim->value_track_interpolate(j, from);
@ -1551,9 +1551,9 @@ void ResourceImporterScene::_create_slices(AnimationPlayer *ap, Ref<Animation> a
new_anim->track_insert_key(dtrack, to - from, to_var);
} else if (anim->track_get_type(j) == Animation::TYPE_BLEND_SHAPE) {
float interp;
anim->blend_shape_track_interpolate(j, from, &interp);
anim->try_blend_shape_track_interpolate(j, from, &interp);
new_anim->blend_shape_track_insert_key(dtrack, 0, interp);
anim->blend_shape_track_interpolate(j, to, &interp);
anim->try_blend_shape_track_interpolate(j, to, &interp);
new_anim->blend_shape_track_insert_key(dtrack, to - from, interp);
}
}

View file

@ -1607,7 +1607,7 @@ bool AnimationPlayerEditor::_validate_tracks(const Ref<Animation> p_anim) {
for (int j = 0; j < key_len; j++) {
Quaternion q;
p_anim->rotation_track_get_key(i, j, &q);
ERR_BREAK_EDMSG(!q.is_normalized(), "AnimationPlayer: '" + player->get_name() + "', Animation: '" + player->get_current_animation() + "', rotation track: '" + p_anim->track_get_path(i) + "' contains unnormalized Quaternion key.");
ERR_BREAK_EDMSG(!q.is_normalized(), "AnimationPlayer: '" + player->get_name() + "', Animation: '" + player->get_current_animation() + "', 3D Rotation Track: '" + p_anim->track_get_path(i) + "' contains unnormalized Quaternion key.");
}
} else if (ttype == Animation::TYPE_VALUE) {
int key_len = p_anim->track_get_key_count(i);
@ -1620,7 +1620,7 @@ bool AnimationPlayerEditor::_validate_tracks(const Ref<Animation> p_anim) {
Quaternion q = Quaternion(p_anim->track_get_key_value(i, j));
if (!q.is_normalized()) {
is_valid = false;
ERR_BREAK_EDMSG(true, "AnimationPlayer: '" + player->get_name() + "', Animation: '" + player->get_current_animation() + "', value track: '" + p_anim->track_get_path(i) + "' contains unnormalized Quaternion key.");
ERR_BREAK_EDMSG(true, "AnimationPlayer: '" + player->get_name() + "', Animation: '" + player->get_current_animation() + "', Value Track: '" + p_anim->track_get_path(i) + "' contains unnormalized Quaternion key.");
}
}
} break;
@ -1629,7 +1629,7 @@ bool AnimationPlayerEditor::_validate_tracks(const Ref<Animation> p_anim) {
Transform3D t = Transform3D(p_anim->track_get_key_value(i, j));
if (!t.basis.orthonormalized().is_rotation()) {
is_valid = false;
ERR_BREAK_EDMSG(true, "AnimationPlayer: '" + player->get_name() + "', Animation: '" + player->get_current_animation() + "', value track: '" + p_anim->track_get_path(i) + "' contains corrupted basis (some axes are too close other axis or scaled by zero) Transform3D key.");
ERR_BREAK_EDMSG(true, "AnimationPlayer: '" + player->get_name() + "', Animation: '" + player->get_current_animation() + "', Value Track: '" + p_anim->track_get_path(i) + "' contains corrupted basis (some axes are too close other axis or scaled by zero) Transform3D key.");
}
}
} break;

View file

@ -6478,7 +6478,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
bool last = false;
while (true) {
Vector3 scale;
Error err = p_animation->scale_track_interpolate(p_track_i, time, &scale);
Error err = p_animation->try_scale_track_interpolate(p_track_i, time, &scale);
ERR_CONTINUE(err != OK);
p_track.scale_track.values.push_back(scale);
p_track.scale_track.times.push_back(time);
@ -6513,7 +6513,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
bool last = false;
while (true) {
Vector3 scale;
Error err = p_animation->position_track_interpolate(p_track_i, time, &scale);
Error err = p_animation->try_position_track_interpolate(p_track_i, time, &scale);
ERR_CONTINUE(err != OK);
p_track.position_track.values.push_back(scale);
p_track.position_track.times.push_back(time);
@ -6548,7 +6548,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
bool last = false;
while (true) {
Quaternion rotation;
Error err = p_animation->rotation_track_interpolate(p_track_i, time, &rotation);
Error err = p_animation->try_rotation_track_interpolate(p_track_i, time, &rotation);
ERR_CONTINUE(err != OK);
p_track.rotation_track.values.push_back(rotation);
p_track.rotation_track.times.push_back(time);
@ -6588,7 +6588,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
bool last = false;
while (true) {
Vector3 position;
Error err = p_animation->position_track_interpolate(p_track_i, time, &position);
Error err = p_animation->try_position_track_interpolate(p_track_i, time, &position);
ERR_CONTINUE(err != OK);
p_track.position_track.values.push_back(position);
p_track.position_track.times.push_back(time);
@ -6621,7 +6621,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
bool last = false;
while (true) {
Quaternion rotation;
Error err = p_animation->rotation_track_interpolate(p_track_i, time, &rotation);
Error err = p_animation->try_rotation_track_interpolate(p_track_i, time, &rotation);
ERR_CONTINUE(err != OK);
p_track.rotation_track.values.push_back(rotation);
p_track.rotation_track.times.push_back(time);
@ -6657,7 +6657,7 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
bool last = false;
while (true) {
Vector3 scale;
Error err = p_animation->scale_track_interpolate(p_track_i, time, &scale);
Error err = p_animation->try_scale_track_interpolate(p_track_i, time, &scale);
ERR_CONTINUE(err != OK);
p_track.scale_track.values.push_back(scale);
p_track.scale_track.times.push_back(time);

View file

@ -528,7 +528,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
Vector3 loc;
Error err = a->position_track_interpolate(i, p_time, &loc);
Error err = a->try_position_track_interpolate(i, p_time, &loc);
//ERR_CONTINUE(err!=OK); //used for testing, should be removed
if (err != OK) {
@ -556,7 +556,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
Quaternion rot;
Error err = a->rotation_track_interpolate(i, p_time, &rot);
Error err = a->try_rotation_track_interpolate(i, p_time, &rot);
//ERR_CONTINUE(err!=OK); //used for testing, should be removed
if (err != OK) {
@ -584,7 +584,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
Vector3 scale;
Error err = a->scale_track_interpolate(i, p_time, &scale);
Error err = a->try_scale_track_interpolate(i, p_time, &scale);
//ERR_CONTINUE(err!=OK); //used for testing, should be removed
if (err != OK) {
@ -612,7 +612,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
float blend;
Error err = a->blend_shape_track_interpolate(i, p_time, &blend);
Error err = a->try_blend_shape_track_interpolate(i, p_time, &blend);
//ERR_CONTINUE(err!=OK); //used for testing, should be removed
if (err != OK) {

View file

@ -654,7 +654,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
// If a value track without a key is cached first, the initial value cannot be determined.
// It is a corner case, but which may cause problems with blending.
ERR_CONTINUE_MSG(anim->track_get_key_count(i) == 0, "AnimationTree: '" + String(E) + "', value track: '" + String(path) + "' must have at least one key to cache for blending.");
ERR_CONTINUE_MSG(anim->track_get_key_count(i) == 0, "AnimationTree: '" + String(E) + "', Value Track: '" + String(path) + "' must have at least one key to cache for blending.");
track_value->init_value = anim->track_get_key_value(i, 0);
track_value->init_value.zero();
@ -867,10 +867,10 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
track_value->is_using_angle |= anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE;
if (was_discrete != track_value->is_discrete) {
ERR_PRINT_ED("Value track: " + String(path) + " with different update modes are blended. Blending prioritizes Discrete mode, so other update mode tracks will not be blended.");
ERR_PRINT_ED("Value Track: " + String(path) + " with different update modes are blended. Blending prioritizes Discrete mode, so other update mode tracks will not be blended.");
}
if (was_using_angle != track_value->is_using_angle) {
WARN_PRINT_ED("Value track: " + String(path) + " with different interpolation types for rotation are blended. Blending prioritizes angle interpolation, so the blending result uses the shortest path referenced to the initial (RESET animation) value.");
WARN_PRINT_ED("Value Track: " + String(path) + " with different interpolation types for rotation are blended. Blending prioritizes angle interpolation, so the blending result uses the shortest path referenced to the initial (RESET animation) value.");
}
}
@ -1181,36 +1181,36 @@ void AnimationTree::_process_graph(double p_delta) {
if (!backward) {
if (prev_time > time) {
Error err = a->position_track_interpolate(i, prev_time, &loc[0]);
Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
if (err != OK) {
continue;
}
loc[0] = post_process_key_value(a, i, loc[0], t->object, t->bone_idx);
a->position_track_interpolate(i, (double)a->get_length(), &loc[1]);
a->try_position_track_interpolate(i, (double)a->get_length(), &loc[1]);
loc[1] = post_process_key_value(a, i, loc[1], t->object, t->bone_idx);
root_motion_cache.loc += (loc[1] - loc[0]) * blend;
prev_time = 0;
}
} else {
if (prev_time < time) {
Error err = a->position_track_interpolate(i, prev_time, &loc[0]);
Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
if (err != OK) {
continue;
}
loc[0] = post_process_key_value(a, i, loc[0], t->object, t->bone_idx);
a->position_track_interpolate(i, 0, &loc[1]);
a->try_position_track_interpolate(i, 0, &loc[1]);
loc[1] = post_process_key_value(a, i, loc[1], t->object, t->bone_idx);
root_motion_cache.loc += (loc[1] - loc[0]) * blend;
prev_time = (double)a->get_length();
}
}
Error err = a->position_track_interpolate(i, prev_time, &loc[0]);
Error err = a->try_position_track_interpolate(i, prev_time, &loc[0]);
if (err != OK) {
continue;
}
loc[0] = post_process_key_value(a, i, loc[0], t->object, t->bone_idx);
a->position_track_interpolate(i, time, &loc[1]);
a->try_position_track_interpolate(i, time, &loc[1]);
loc[1] = post_process_key_value(a, i, loc[1], t->object, t->bone_idx);
root_motion_cache.loc += (loc[1] - loc[0]) * blend;
prev_time = !backward ? 0 : (double)a->get_length();
@ -1219,7 +1219,7 @@ void AnimationTree::_process_graph(double p_delta) {
{
Vector3 loc;
Error err = a->position_track_interpolate(i, time, &loc);
Error err = a->try_position_track_interpolate(i, time, &loc);
if (err != OK) {
continue;
}
@ -1276,36 +1276,36 @@ void AnimationTree::_process_graph(double p_delta) {
if (!backward) {
if (prev_time > time) {
Error err = a->rotation_track_interpolate(i, prev_time, &rot[0]);
Error err = a->try_rotation_track_interpolate(i, prev_time, &rot[0]);
if (err != OK) {
continue;
}
rot[0] = post_process_key_value(a, i, rot[0], t->object, t->bone_idx);
a->rotation_track_interpolate(i, (double)a->get_length(), &rot[1]);
a->try_rotation_track_interpolate(i, (double)a->get_length(), &rot[1]);
rot[1] = post_process_key_value(a, i, rot[1], t->object, t->bone_idx);
root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
prev_time = 0;
}
} else {
if (prev_time < time) {
Error err = a->rotation_track_interpolate(i, prev_time, &rot[0]);
Error err = a->try_rotation_track_interpolate(i, prev_time, &rot[0]);
if (err != OK) {
continue;
}
rot[0] = post_process_key_value(a, i, rot[0], t->object, t->bone_idx);
a->rotation_track_interpolate(i, 0, &rot[1]);
a->try_rotation_track_interpolate(i, 0, &rot[1]);
root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
prev_time = (double)a->get_length();
}
}
Error err = a->rotation_track_interpolate(i, prev_time, &rot[0]);
Error err = a->try_rotation_track_interpolate(i, prev_time, &rot[0]);
if (err != OK) {
continue;
}
rot[0] = post_process_key_value(a, i, rot[0], t->object, t->bone_idx);
a->rotation_track_interpolate(i, time, &rot[1]);
a->try_rotation_track_interpolate(i, time, &rot[1]);
rot[1] = post_process_key_value(a, i, rot[1], t->object, t->bone_idx);
root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
prev_time = !backward ? 0 : (double)a->get_length();
@ -1314,7 +1314,7 @@ void AnimationTree::_process_graph(double p_delta) {
{
Quaternion rot;
Error err = a->rotation_track_interpolate(i, time, &rot);
Error err = a->try_rotation_track_interpolate(i, time, &rot);
if (err != OK) {
continue;
}
@ -1371,37 +1371,37 @@ void AnimationTree::_process_graph(double p_delta) {
if (!backward) {
if (prev_time > time) {
Error err = a->scale_track_interpolate(i, prev_time, &scale[0]);
Error err = a->try_scale_track_interpolate(i, prev_time, &scale[0]);
if (err != OK) {
continue;
}
scale[0] = post_process_key_value(a, i, scale[0], t->object, t->bone_idx);
a->scale_track_interpolate(i, (double)a->get_length(), &scale[1]);
a->try_scale_track_interpolate(i, (double)a->get_length(), &scale[1]);
root_motion_cache.scale += (scale[1] - scale[0]) * blend;
scale[1] = post_process_key_value(a, i, scale[1], t->object, t->bone_idx);
prev_time = 0;
}
} else {
if (prev_time < time) {
Error err = a->scale_track_interpolate(i, prev_time, &scale[0]);
Error err = a->try_scale_track_interpolate(i, prev_time, &scale[0]);
if (err != OK) {
continue;
}
scale[0] = post_process_key_value(a, i, scale[0], t->object, t->bone_idx);
a->scale_track_interpolate(i, 0, &scale[1]);
a->try_scale_track_interpolate(i, 0, &scale[1]);
scale[1] = post_process_key_value(a, i, scale[1], t->object, t->bone_idx);
root_motion_cache.scale += (scale[1] - scale[0]) * blend;
prev_time = (double)a->get_length();
}
}
Error err = a->scale_track_interpolate(i, prev_time, &scale[0]);
Error err = a->try_scale_track_interpolate(i, prev_time, &scale[0]);
if (err != OK) {
continue;
}
scale[0] = post_process_key_value(a, i, scale[0], t->object, t->bone_idx);
a->scale_track_interpolate(i, time, &scale[1]);
a->try_scale_track_interpolate(i, time, &scale[1]);
scale[1] = post_process_key_value(a, i, scale[1], t->object, t->bone_idx);
root_motion_cache.scale += (scale[1] - scale[0]) * blend;
prev_time = !backward ? 0 : (double)a->get_length();
@ -1410,7 +1410,7 @@ void AnimationTree::_process_graph(double p_delta) {
{
Vector3 scale;
Error err = a->scale_track_interpolate(i, time, &scale);
Error err = a->try_scale_track_interpolate(i, time, &scale);
if (err != OK) {
continue;
}
@ -1429,7 +1429,7 @@ void AnimationTree::_process_graph(double p_delta) {
float value;
Error err = a->blend_shape_track_interpolate(i, time, &value);
Error err = a->try_blend_shape_track_interpolate(i, time, &value);
//ERR_CONTINUE(err!=OK); //used for testing, should be removed
if (err != OK) {

View file

@ -1088,7 +1088,7 @@ Error Animation::position_track_get_key(int p_track, int p_key, Vector3 *r_posit
return OK;
}
Error Animation::position_track_interpolate(int p_track, double p_time, Vector3 *r_interpolation) const {
Error Animation::try_position_track_interpolate(int p_track, double p_time, Vector3 *r_interpolation) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), ERR_INVALID_PARAMETER);
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_POSITION_3D, ERR_INVALID_PARAMETER);
@ -1114,6 +1114,14 @@ Error Animation::position_track_interpolate(int p_track, double p_time, Vector3
return OK;
}
Vector3 Animation::position_track_interpolate(int p_track, double p_time) const {
Vector3 ret = Vector3(0, 0, 0);
ERR_FAIL_INDEX_V(p_track, tracks.size(), ret);
bool err = try_position_track_interpolate(p_track, p_time, &ret);
ERR_FAIL_COND_V_MSG(err, ret, "3D Position Track: '" + tracks[p_track]->path + "' is unavailable.");
return ret;
}
////
int Animation::rotation_track_insert_key(int p_track, double p_time, const Quaternion &p_rotation) {
@ -1160,7 +1168,7 @@ Error Animation::rotation_track_get_key(int p_track, int p_key, Quaternion *r_ro
return OK;
}
Error Animation::rotation_track_interpolate(int p_track, double p_time, Quaternion *r_interpolation) const {
Error Animation::try_rotation_track_interpolate(int p_track, double p_time, Quaternion *r_interpolation) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), ERR_INVALID_PARAMETER);
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_ROTATION_3D, ERR_INVALID_PARAMETER);
@ -1186,6 +1194,14 @@ Error Animation::rotation_track_interpolate(int p_track, double p_time, Quaterni
return OK;
}
Quaternion Animation::rotation_track_interpolate(int p_track, double p_time) const {
Quaternion ret = Quaternion(0, 0, 0, 1);
ERR_FAIL_INDEX_V(p_track, tracks.size(), ret);
bool err = try_rotation_track_interpolate(p_track, p_time, &ret);
ERR_FAIL_COND_V_MSG(err, ret, "3D Rotation Track: '" + tracks[p_track]->path + "' is unavailable.");
return ret;
}
////
int Animation::scale_track_insert_key(int p_track, double p_time, const Vector3 &p_scale) {
@ -1232,7 +1248,7 @@ Error Animation::scale_track_get_key(int p_track, int p_key, Vector3 *r_scale) c
return OK;
}
Error Animation::scale_track_interpolate(int p_track, double p_time, Vector3 *r_interpolation) const {
Error Animation::try_scale_track_interpolate(int p_track, double p_time, Vector3 *r_interpolation) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), ERR_INVALID_PARAMETER);
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_SCALE_3D, ERR_INVALID_PARAMETER);
@ -1258,6 +1274,16 @@ Error Animation::scale_track_interpolate(int p_track, double p_time, Vector3 *r_
return OK;
}
Vector3 Animation::scale_track_interpolate(int p_track, double p_time) const {
Vector3 ret = Vector3(1, 1, 1);
ERR_FAIL_INDEX_V(p_track, tracks.size(), ret);
bool err = try_scale_track_interpolate(p_track, p_time, &ret);
ERR_FAIL_COND_V_MSG(err, ret, "3D Scale Track: '" + tracks[p_track]->path + "' is unavailable.");
return ret;
}
////
int Animation::blend_shape_track_insert_key(int p_track, double p_time, float p_blend_shape) {
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
Track *t = tracks[p_track];
@ -1302,7 +1328,7 @@ Error Animation::blend_shape_track_get_key(int p_track, int p_key, float *r_blen
return OK;
}
Error Animation::blend_shape_track_interpolate(int p_track, double p_time, float *r_interpolation) const {
Error Animation::try_blend_shape_track_interpolate(int p_track, double p_time, float *r_interpolation) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), ERR_INVALID_PARAMETER);
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_BLEND_SHAPE, ERR_INVALID_PARAMETER);
@ -1328,6 +1354,16 @@ Error Animation::blend_shape_track_interpolate(int p_track, double p_time, float
return OK;
}
float Animation::blend_shape_track_interpolate(int p_track, double p_time) const {
float ret = 0;
ERR_FAIL_INDEX_V(p_track, tracks.size(), ret);
bool err = try_blend_shape_track_interpolate(p_track, p_time, &ret);
ERR_FAIL_COND_V_MSG(err, ret, "Blend Shape Track: '" + tracks[p_track]->path + "' is unavailable.");
return ret;
}
////
void Animation::track_remove_key_at_time(int p_track, double p_time) {
int idx = track_find_key(p_track, p_time, FIND_MODE_APPROX);
ERR_FAIL_COND(idx < 0);
@ -3796,6 +3832,11 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("scale_track_insert_key", "track_idx", "time", "scale"), &Animation::scale_track_insert_key);
ClassDB::bind_method(D_METHOD("blend_shape_track_insert_key", "track_idx", "time", "amount"), &Animation::blend_shape_track_insert_key);
ClassDB::bind_method(D_METHOD("position_track_interpolate", "track_idx", "time_sec"), &Animation::position_track_interpolate);
ClassDB::bind_method(D_METHOD("rotation_track_interpolate", "track_idx", "time_sec"), &Animation::rotation_track_interpolate);
ClassDB::bind_method(D_METHOD("scale_track_interpolate", "track_idx", "time_sec"), &Animation::scale_track_interpolate);
ClassDB::bind_method(D_METHOD("blend_shape_track_interpolate", "track_idx", "time_sec"), &Animation::blend_shape_track_interpolate);
ClassDB::bind_method(D_METHOD("track_insert_key", "track_idx", "time", "key", "transition"), &Animation::track_insert_key, DEFVAL(1));
ClassDB::bind_method(D_METHOD("track_remove_key", "track_idx", "key_idx"), &Animation::track_remove_key);
ClassDB::bind_method(D_METHOD("track_remove_key_at_time", "track_idx", "time"), &Animation::track_remove_key_at_time);
@ -4551,7 +4592,7 @@ Vector3i Animation::_compress_key(uint32_t p_track, const AABB &p_bounds, int32_
if (p_key >= 0) {
position_track_get_key(p_track, p_key, &pos);
} else {
position_track_interpolate(p_track, p_time, &pos);
try_position_track_interpolate(p_track, p_time, &pos);
}
pos = (pos - p_bounds.position) / p_bounds.size;
for (int j = 0; j < 3; j++) {
@ -4563,7 +4604,7 @@ Vector3i Animation::_compress_key(uint32_t p_track, const AABB &p_bounds, int32_
if (p_key >= 0) {
rotation_track_get_key(p_track, p_key, &rot);
} else {
rotation_track_interpolate(p_track, p_time, &rot);
try_rotation_track_interpolate(p_track, p_time, &rot);
}
Vector3 axis = rot.get_axis();
float angle = rot.get_angle();
@ -4580,7 +4621,7 @@ Vector3i Animation::_compress_key(uint32_t p_track, const AABB &p_bounds, int32_
if (p_key >= 0) {
scale_track_get_key(p_track, p_key, &scale);
} else {
scale_track_interpolate(p_track, p_time, &scale);
try_scale_track_interpolate(p_track, p_time, &scale);
}
scale = (scale - p_bounds.position) / p_bounds.size;
for (int j = 0; j < 3; j++) {
@ -4592,7 +4633,7 @@ Vector3i Animation::_compress_key(uint32_t p_track, const AABB &p_bounds, int32_
if (p_key >= 0) {
blend_shape_track_get_key(p_track, p_key, &blend);
} else {
blend_shape_track_interpolate(p_track, p_time, &blend);
try_blend_shape_track_interpolate(p_track, p_time, &blend);
}
blend = (blend / float(Compression::BLEND_SHAPE_RANGE)) * 0.5 + 0.5;

View file

@ -410,19 +410,23 @@ public:
int position_track_insert_key(int p_track, double p_time, const Vector3 &p_position);
Error position_track_get_key(int p_track, int p_key, Vector3 *r_position) const;
Error position_track_interpolate(int p_track, double p_time, Vector3 *r_interpolation) const;
Error try_position_track_interpolate(int p_track, double p_time, Vector3 *r_interpolation) const;
Vector3 position_track_interpolate(int p_track, double p_time) const;
int rotation_track_insert_key(int p_track, double p_time, const Quaternion &p_rotation);
Error rotation_track_get_key(int p_track, int p_key, Quaternion *r_rotation) const;
Error rotation_track_interpolate(int p_track, double p_time, Quaternion *r_interpolation) const;
Error try_rotation_track_interpolate(int p_track, double p_time, Quaternion *r_interpolation) const;
Quaternion rotation_track_interpolate(int p_track, double p_time) const;
int scale_track_insert_key(int p_track, double p_time, const Vector3 &p_scale);
Error scale_track_get_key(int p_track, int p_key, Vector3 *r_scale) const;
Error scale_track_interpolate(int p_track, double p_time, Vector3 *r_interpolation) const;
Error try_scale_track_interpolate(int p_track, double p_time, Vector3 *r_interpolation) const;
Vector3 scale_track_interpolate(int p_track, double p_time) const;
int blend_shape_track_insert_key(int p_track, double p_time, float p_blend);
Error blend_shape_track_get_key(int p_track, int p_key, float *r_blend) const;
Error blend_shape_track_interpolate(int p_track, double p_time, float *r_blend) const;
Error try_blend_shape_track_interpolate(int p_track, double p_time, float *r_blend) const;
float blend_shape_track_interpolate(int p_track, double p_time) const;
void track_set_interpolation_type(int p_track, InterpolationType p_interp);
InterpolationType track_get_interpolation_type(int p_track) const;

View file

@ -82,11 +82,11 @@ TEST_CASE("[Animation] Create value track") {
CHECK(animation->track_get_key_transition(1, 0) == doctest::Approx(real_t(-1.0)));
// This is a value track, so the methods below should return errors.
CHECK(animation->position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->bezier_track_interpolate(0, 0.0) == doctest::Approx(0.0));
CHECK(animation->blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
ERR_PRINT_ON;
}
@ -104,22 +104,22 @@ TEST_CASE("[Animation] Create 3D position track") {
Vector3 r_interpolation;
CHECK(animation->position_track_interpolate(0, -0.2, &r_interpolation) == OK);
CHECK(animation->try_position_track_interpolate(0, -0.2, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Vector3(0, 1, 2)));
CHECK(animation->position_track_interpolate(0, 0.0, &r_interpolation) == OK);
CHECK(animation->try_position_track_interpolate(0, 0.0, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Vector3(0, 1, 2)));
CHECK(animation->position_track_interpolate(0, 0.2, &r_interpolation) == OK);
CHECK(animation->try_position_track_interpolate(0, 0.2, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Vector3(1.4, 2.2, 3.2)));
CHECK(animation->position_track_interpolate(0, 0.4, &r_interpolation) == OK);
CHECK(animation->try_position_track_interpolate(0, 0.4, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Vector3(2.8, 3.4, 4.4)));
CHECK(animation->position_track_interpolate(0, 0.5, &r_interpolation) == OK);
CHECK(animation->try_position_track_interpolate(0, 0.5, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Vector3(3.5, 4, 5)));
CHECK(animation->position_track_interpolate(0, 0.6, &r_interpolation) == OK);
CHECK(animation->try_position_track_interpolate(0, 0.6, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Vector3(3.5, 4, 5)));
// 3D position tracks always use linear interpolation for performance reasons.
@ -129,10 +129,10 @@ TEST_CASE("[Animation] Create 3D position track") {
// This is a 3D position track, so the methods below should return errors.
ERR_PRINT_OFF;
CHECK(animation->value_track_interpolate(0, 0.0).is_null());
CHECK(animation->rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->bezier_track_interpolate(0, 0.0) == doctest::Approx(0.0));
CHECK(animation->blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
ERR_PRINT_ON;
}
@ -150,22 +150,22 @@ TEST_CASE("[Animation] Create 3D rotation track") {
Quaternion r_interpolation;
CHECK(animation->rotation_track_interpolate(0, -0.2, &r_interpolation) == OK);
CHECK(animation->try_rotation_track_interpolate(0, -0.2, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Quaternion(0.403423, 0.259035, 0.73846, 0.47416)));
CHECK(animation->rotation_track_interpolate(0, 0.0, &r_interpolation) == OK);
CHECK(animation->try_rotation_track_interpolate(0, 0.0, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Quaternion(0.403423, 0.259035, 0.73846, 0.47416)));
CHECK(animation->rotation_track_interpolate(0, 0.2, &r_interpolation) == OK);
CHECK(animation->try_rotation_track_interpolate(0, 0.2, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Quaternion(0.336182, 0.30704, 0.751515, 0.477425)));
CHECK(animation->rotation_track_interpolate(0, 0.4, &r_interpolation) == OK);
CHECK(animation->try_rotation_track_interpolate(0, 0.4, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Quaternion(0.266585, 0.352893, 0.759303, 0.477344)));
CHECK(animation->rotation_track_interpolate(0, 0.5, &r_interpolation) == OK);
CHECK(animation->try_rotation_track_interpolate(0, 0.5, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Quaternion(0.231055, 0.374912, 0.761204, 0.476048)));
CHECK(animation->rotation_track_interpolate(0, 0.6, &r_interpolation) == OK);
CHECK(animation->try_rotation_track_interpolate(0, 0.6, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Quaternion(0.231055, 0.374912, 0.761204, 0.476048)));
// 3D rotation tracks always use linear interpolation for performance reasons.
@ -175,10 +175,10 @@ TEST_CASE("[Animation] Create 3D rotation track") {
// This is a 3D rotation track, so the methods below should return errors.
ERR_PRINT_OFF;
CHECK(animation->value_track_interpolate(0, 0.0).is_null());
CHECK(animation->position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->bezier_track_interpolate(0, 0.0) == doctest::Approx(real_t(0.0)));
CHECK(animation->blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
ERR_PRINT_ON;
}
@ -196,22 +196,22 @@ TEST_CASE("[Animation] Create 3D scale track") {
Vector3 r_interpolation;
CHECK(animation->scale_track_interpolate(0, -0.2, &r_interpolation) == OK);
CHECK(animation->try_scale_track_interpolate(0, -0.2, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Vector3(0, 1, 2)));
CHECK(animation->scale_track_interpolate(0, 0.0, &r_interpolation) == OK);
CHECK(animation->try_scale_track_interpolate(0, 0.0, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Vector3(0, 1, 2)));
CHECK(animation->scale_track_interpolate(0, 0.2, &r_interpolation) == OK);
CHECK(animation->try_scale_track_interpolate(0, 0.2, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Vector3(1.4, 2.2, 3.2)));
CHECK(animation->scale_track_interpolate(0, 0.4, &r_interpolation) == OK);
CHECK(animation->try_scale_track_interpolate(0, 0.4, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Vector3(2.8, 3.4, 4.4)));
CHECK(animation->scale_track_interpolate(0, 0.5, &r_interpolation) == OK);
CHECK(animation->try_scale_track_interpolate(0, 0.5, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Vector3(3.5, 4, 5)));
CHECK(animation->scale_track_interpolate(0, 0.6, &r_interpolation) == OK);
CHECK(animation->try_scale_track_interpolate(0, 0.6, &r_interpolation) == OK);
CHECK(r_interpolation.is_equal_approx(Vector3(3.5, 4, 5)));
// 3D scale tracks always use linear interpolation for performance reasons.
@ -221,10 +221,10 @@ TEST_CASE("[Animation] Create 3D scale track") {
// This is a 3D scale track, so the methods below should return errors.
ERR_PRINT_OFF;
CHECK(animation->value_track_interpolate(0, 0.0).is_null());
CHECK(animation->position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->bezier_track_interpolate(0, 0.0) == doctest::Approx(0.0));
CHECK(animation->blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
ERR_PRINT_ON;
}
@ -247,22 +247,22 @@ TEST_CASE("[Animation] Create blend shape track") {
CHECK(animation->blend_shape_track_get_key(0, 1, &r_blend) == OK);
CHECK(r_blend == doctest::Approx(1.0f));
CHECK(animation->blend_shape_track_interpolate(0, -0.2, &r_blend) == OK);
CHECK(animation->try_blend_shape_track_interpolate(0, -0.2, &r_blend) == OK);
CHECK(r_blend == doctest::Approx(-1.0f));
CHECK(animation->blend_shape_track_interpolate(0, 0.0, &r_blend) == OK);
CHECK(animation->try_blend_shape_track_interpolate(0, 0.0, &r_blend) == OK);
CHECK(r_blend == doctest::Approx(-1.0f));
CHECK(animation->blend_shape_track_interpolate(0, 0.2, &r_blend) == OK);
CHECK(animation->try_blend_shape_track_interpolate(0, 0.2, &r_blend) == OK);
CHECK(r_blend == doctest::Approx(-0.2f));
CHECK(animation->blend_shape_track_interpolate(0, 0.4, &r_blend) == OK);
CHECK(animation->try_blend_shape_track_interpolate(0, 0.4, &r_blend) == OK);
CHECK(r_blend == doctest::Approx(0.6f));
CHECK(animation->blend_shape_track_interpolate(0, 0.5, &r_blend) == OK);
CHECK(animation->try_blend_shape_track_interpolate(0, 0.5, &r_blend) == OK);
CHECK(r_blend == doctest::Approx(1.0f));
CHECK(animation->blend_shape_track_interpolate(0, 0.6, &r_blend) == OK);
CHECK(animation->try_blend_shape_track_interpolate(0, 0.6, &r_blend) == OK);
CHECK(r_blend == doctest::Approx(1.0f));
// Blend shape tracks always use linear interpolation for performance reasons.
@ -272,9 +272,9 @@ TEST_CASE("[Animation] Create blend shape track") {
// This is a blend shape track, so the methods below should return errors.
ERR_PRINT_OFF;
CHECK(animation->value_track_interpolate(0, 0.0).is_null());
CHECK(animation->position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->bezier_track_interpolate(0, 0.0) == doctest::Approx(0.0));
ERR_PRINT_ON;
}
@ -302,10 +302,10 @@ TEST_CASE("[Animation] Create Bezier track") {
// This is a bezier track, so the methods below should return errors.
ERR_PRINT_OFF;
CHECK(animation->value_track_interpolate(0, 0.0).is_null());
CHECK(animation->position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_position_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_rotation_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_scale_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
CHECK(animation->try_blend_shape_track_interpolate(0, 0.0, nullptr) == ERR_INVALID_PARAMETER);
ERR_PRINT_ON;
}