Make consistent the retrieval of audio tracks
This commit is contained in:
parent
0a89888cba
commit
4659090543
8 changed files with 245 additions and 40 deletions
|
@ -359,8 +359,10 @@
|
||||||
<param index="0" name="track_idx" type="int" />
|
<param index="0" name="track_idx" type="int" />
|
||||||
<param index="1" name="time" type="float" />
|
<param index="1" name="time" type="float" />
|
||||||
<param index="2" name="find_mode" type="int" enum="Animation.FindMode" default="0" />
|
<param index="2" name="find_mode" type="int" enum="Animation.FindMode" default="0" />
|
||||||
|
<param index="3" name="limit" type="bool" default="false" />
|
||||||
<description>
|
<description>
|
||||||
Finds the key index by time in a given track. Optionally, only find it if the approx/exact time is given.
|
Finds the key index by time in a given track. Optionally, only find it if the approx/exact time is given.
|
||||||
|
If [param limit] is [code]true[/code], it does not return keys outside the animation range.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="track_get_interpolation_loop_wrap" qualifiers="const">
|
<method name="track_get_interpolation_loop_wrap" qualifiers="const">
|
||||||
|
|
|
@ -5904,6 +5904,16 @@ bool AnimationTrackEditor::_is_track_compatible(int p_target_track_idx, Variant:
|
||||||
void AnimationTrackEditor::_edit_menu_about_to_popup() {
|
void AnimationTrackEditor::_edit_menu_about_to_popup() {
|
||||||
AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
|
AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
|
||||||
edit->get_popup()->set_item_disabled(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), !player->can_apply_reset());
|
edit->get_popup()->set_item_disabled(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), !player->can_apply_reset());
|
||||||
|
|
||||||
|
bool has_length = false;
|
||||||
|
for (const KeyValue<SelectedKey, KeyInfo> &E : selection) {
|
||||||
|
if (animation->track_get_type(E.key.track) == Animation::TYPE_AUDIO) {
|
||||||
|
has_length = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
edit->get_popup()->set_item_disabled(edit->get_popup()->get_item_index(EDIT_SET_START_OFFSET), !has_length);
|
||||||
|
edit->get_popup()->set_item_disabled(edit->get_popup()->get_item_index(EDIT_SET_END_OFFSET), !has_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationTrackEditor::goto_prev_step(bool p_from_mouse_event) {
|
void AnimationTrackEditor::goto_prev_step(bool p_from_mouse_event) {
|
||||||
|
@ -6229,6 +6239,56 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
|
||||||
undo_redo->commit_action();
|
undo_redo->commit_action();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case EDIT_SET_START_OFFSET: {
|
||||||
|
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
|
||||||
|
undo_redo->create_action(TTR("Animation Set Start Offset"), UndoRedo::MERGE_ENDS);
|
||||||
|
for (const KeyValue<SelectedKey, KeyInfo> &E : selection) {
|
||||||
|
if (animation->track_get_type(E.key.track) != Animation::TYPE_AUDIO) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Ref<AudioStream> stream = animation->audio_track_get_key_stream(E.key.track, E.key.key);
|
||||||
|
double len = stream->get_length() - animation->audio_track_get_key_end_offset(E.key.track, E.key.key);
|
||||||
|
real_t prev_offset = animation->audio_track_get_key_start_offset(E.key.track, E.key.key);
|
||||||
|
double prev_time = animation->track_get_key_time(E.key.track, E.key.key);
|
||||||
|
float cur_time = timeline->get_play_position();
|
||||||
|
float diff = prev_offset + cur_time - prev_time;
|
||||||
|
float destination = cur_time - MIN(0, diff);
|
||||||
|
if (diff >= len || animation->track_find_key(E.key.track, destination, Animation::FIND_MODE_EXACT) >= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
undo_redo->add_do_method(animation.ptr(), "audio_track_set_key_start_offset", E.key.track, E.key.key, diff);
|
||||||
|
undo_redo->add_do_method(animation.ptr(), "track_set_key_time", E.key.track, E.key.key, destination);
|
||||||
|
undo_redo->add_undo_method(animation.ptr(), "track_set_key_time", E.key.track, E.key.key, prev_time);
|
||||||
|
undo_redo->add_undo_method(animation.ptr(), "audio_track_set_key_start_offset", E.key.track, E.key.key, prev_offset);
|
||||||
|
}
|
||||||
|
undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
|
||||||
|
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
|
||||||
|
undo_redo->commit_action();
|
||||||
|
} break;
|
||||||
|
case EDIT_SET_END_OFFSET: {
|
||||||
|
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
|
||||||
|
undo_redo->create_action(TTR("Animation Set End Offset"), UndoRedo::MERGE_ENDS);
|
||||||
|
for (const KeyValue<SelectedKey, KeyInfo> &E : selection) {
|
||||||
|
if (animation->track_get_type(E.key.track) != Animation::TYPE_AUDIO) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Ref<AudioStream> stream = animation->audio_track_get_key_stream(E.key.track, E.key.key);
|
||||||
|
double len = stream->get_length() - animation->audio_track_get_key_start_offset(E.key.track, E.key.key);
|
||||||
|
real_t prev_offset = animation->audio_track_get_key_end_offset(E.key.track, E.key.key);
|
||||||
|
double prev_time = animation->track_get_key_time(E.key.track, E.key.key);
|
||||||
|
float cur_time = timeline->get_play_position();
|
||||||
|
float diff = prev_time + len - cur_time;
|
||||||
|
if (diff >= len) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
undo_redo->add_do_method(animation.ptr(), "audio_track_set_key_end_offset", E.key.track, E.key.key, diff);
|
||||||
|
undo_redo->add_undo_method(animation.ptr(), "audio_track_set_key_end_offset", E.key.track, E.key.key, prev_offset);
|
||||||
|
}
|
||||||
|
undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
|
||||||
|
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
|
||||||
|
undo_redo->commit_action();
|
||||||
|
} break;
|
||||||
|
|
||||||
case EDIT_EASE_SELECTION: {
|
case EDIT_EASE_SELECTION: {
|
||||||
ease_dialog->popup_centered(Size2(200, 100) * EDSCALE);
|
ease_dialog->popup_centered(Size2(200, 100) * EDSCALE);
|
||||||
} break;
|
} break;
|
||||||
|
@ -6342,6 +6402,36 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
|
||||||
case EDIT_PASTE_KEYS: {
|
case EDIT_PASTE_KEYS: {
|
||||||
_anim_paste_keys(-1.0, -1.0);
|
_anim_paste_keys(-1.0, -1.0);
|
||||||
} break;
|
} break;
|
||||||
|
case EDIT_MOVE_FIRST_SELECTED_KEY_TO_CURSOR: {
|
||||||
|
if (moving_selection || selection.is_empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
real_t from_t = 1e20;
|
||||||
|
for (const KeyValue<SelectedKey, KeyInfo> &E : selection) {
|
||||||
|
real_t t = animation->track_get_key_time(E.key.track, E.key.key);
|
||||||
|
if (t < from_t) {
|
||||||
|
from_t = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_move_selection_begin();
|
||||||
|
_move_selection(timeline->get_play_position() - from_t);
|
||||||
|
_move_selection_commit();
|
||||||
|
} break;
|
||||||
|
case EDIT_MOVE_LAST_SELECTED_KEY_TO_CURSOR: {
|
||||||
|
if (moving_selection || selection.is_empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
real_t to_t = -1e20;
|
||||||
|
for (const KeyValue<SelectedKey, KeyInfo> &E : selection) {
|
||||||
|
real_t t = animation->track_get_key_time(E.key.track, E.key.key);
|
||||||
|
if (t > to_t) {
|
||||||
|
to_t = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_move_selection_begin();
|
||||||
|
_move_selection(timeline->get_play_position() - to_t);
|
||||||
|
_move_selection_commit();
|
||||||
|
} break;
|
||||||
case EDIT_ADD_RESET_KEY: {
|
case EDIT_ADD_RESET_KEY: {
|
||||||
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
|
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
|
||||||
undo_redo->create_action(TTR("Animation Add RESET Keys"));
|
undo_redo->create_action(TTR("Animation Add RESET Keys"));
|
||||||
|
@ -6590,6 +6680,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationTrackEditor::_cleanup_animation(Ref<Animation> p_animation) {
|
void AnimationTrackEditor::_cleanup_animation(Ref<Animation> p_animation) {
|
||||||
|
_clear_selection();
|
||||||
for (int i = 0; i < p_animation->get_track_count(); i++) {
|
for (int i = 0; i < p_animation->get_track_count(); i++) {
|
||||||
if (!root->has_node_and_resource(p_animation->track_get_path(i))) {
|
if (!root->has_node_and_resource(p_animation->track_get_path(i))) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -6618,6 +6709,76 @@ void AnimationTrackEditor::_cleanup_animation(Ref<Animation> p_animation) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cleanup_keys_with_trimming_head->is_pressed()) {
|
||||||
|
// Check is necessary because if there is already a key in position 0, it should not be replaced.
|
||||||
|
if (p_animation->track_get_type(i) == Animation::TYPE_AUDIO && p_animation->track_find_key(i, 0, Animation::FIND_MODE_EXACT) < 0) {
|
||||||
|
for (int j = 0; j < p_animation->track_get_key_count(i); j++) {
|
||||||
|
double t = p_animation->track_get_key_time(i, j);
|
||||||
|
if (t < 0) {
|
||||||
|
if (j == p_animation->track_get_key_count(i) - 1 || (j + 1 < p_animation->track_get_key_count(i) && p_animation->track_get_key_time(i, j + 1) > 0)) {
|
||||||
|
Ref<AudioStream> stream = p_animation->audio_track_get_key_stream(i, j);
|
||||||
|
double len = stream->get_length() - p_animation->audio_track_get_key_end_offset(i, j);
|
||||||
|
double prev_offset = p_animation->audio_track_get_key_start_offset(i, j);
|
||||||
|
double prev_time = p_animation->track_get_key_time(i, j);
|
||||||
|
double diff = prev_offset - prev_time;
|
||||||
|
if (diff >= len) {
|
||||||
|
p_animation->track_remove_key(i, j);
|
||||||
|
j--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
p_animation->audio_track_set_key_start_offset(i, j, diff);
|
||||||
|
p_animation->track_set_key_time(i, j, 0);
|
||||||
|
} else {
|
||||||
|
p_animation->track_remove_key(i, j);
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int j = 0; j < p_animation->track_get_key_count(i); j++) {
|
||||||
|
double t = p_animation->track_get_key_time(i, j);
|
||||||
|
if (t < 0) {
|
||||||
|
p_animation->track_remove_key(i, j);
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleanup_keys_with_trimming_end->is_pressed()) {
|
||||||
|
if (p_animation->track_get_type(i) == Animation::TYPE_AUDIO) {
|
||||||
|
for (int j = 0; j < p_animation->track_get_key_count(i); j++) {
|
||||||
|
double t = p_animation->track_get_key_time(i, j);
|
||||||
|
if (t <= p_animation->get_length() && (j == p_animation->track_get_key_count(i) - 1 || (j + 1 < p_animation->track_get_key_count(i) && p_animation->track_get_key_time(i, j + 1) > p_animation->get_length()))) {
|
||||||
|
Ref<AudioStream> stream = animation->audio_track_get_key_stream(i, j);
|
||||||
|
double len = stream->get_length() - animation->audio_track_get_key_start_offset(i, j);
|
||||||
|
if (t + len < p_animation->get_length()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double prev_time = animation->track_get_key_time(i, j);
|
||||||
|
double diff = prev_time + len - p_animation->get_length();
|
||||||
|
if (diff >= len) {
|
||||||
|
p_animation->track_remove_key(i, j);
|
||||||
|
j--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
p_animation->audio_track_set_key_end_offset(i, j, diff);
|
||||||
|
} else if (t > p_animation->get_length()) {
|
||||||
|
p_animation->track_remove_key(i, j);
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int j = 0; j < p_animation->track_get_key_count(i); j++) {
|
||||||
|
double t = p_animation->track_get_key_time(i, j);
|
||||||
|
if (t > p_animation->get_length()) {
|
||||||
|
p_animation->track_remove_key(i, j);
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!prop_exists || p_animation->track_get_type(i) != Animation::TYPE_VALUE || !cleanup_keys->is_pressed()) {
|
if (!prop_exists || p_animation->track_get_type(i) != Animation::TYPE_VALUE || !cleanup_keys->is_pressed()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -6983,6 +7144,9 @@ AnimationTrackEditor::AnimationTrackEditor() {
|
||||||
edit->get_popup()->add_item(TTR("Scale Selection"), EDIT_SCALE_SELECTION);
|
edit->get_popup()->add_item(TTR("Scale Selection"), EDIT_SCALE_SELECTION);
|
||||||
edit->get_popup()->add_item(TTR("Scale From Cursor"), EDIT_SCALE_FROM_CURSOR);
|
edit->get_popup()->add_item(TTR("Scale From Cursor"), EDIT_SCALE_FROM_CURSOR);
|
||||||
edit->get_popup()->add_separator();
|
edit->get_popup()->add_separator();
|
||||||
|
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/set_start_offset", TTR("Set Start Offset (Audio)"), KeyModifierMask::CMD_OR_CTRL | Key::BRACKETLEFT), EDIT_SET_START_OFFSET);
|
||||||
|
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/set_end_offset", TTR("Set End Offset (Audio)"), KeyModifierMask::CMD_OR_CTRL | Key::BRACKETRIGHT), EDIT_SET_END_OFFSET);
|
||||||
|
edit->get_popup()->add_separator();
|
||||||
edit->get_popup()->add_item(TTR("Make Easing Selection"), EDIT_EASE_SELECTION);
|
edit->get_popup()->add_item(TTR("Make Easing Selection"), EDIT_EASE_SELECTION);
|
||||||
edit->get_popup()->add_separator();
|
edit->get_popup()->add_separator();
|
||||||
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/duplicate_selected_keys", TTR("Duplicate Selected Keys"), KeyModifierMask::CMD_OR_CTRL | Key::D), EDIT_DUPLICATE_SELECTED_KEYS);
|
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/duplicate_selected_keys", TTR("Duplicate Selected Keys"), KeyModifierMask::CMD_OR_CTRL | Key::D), EDIT_DUPLICATE_SELECTED_KEYS);
|
||||||
|
@ -6990,6 +7154,9 @@ AnimationTrackEditor::AnimationTrackEditor() {
|
||||||
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/paste_keys", TTR("Paste Keys"), KeyModifierMask::CMD_OR_CTRL | Key::V), EDIT_PASTE_KEYS);
|
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/paste_keys", TTR("Paste Keys"), KeyModifierMask::CMD_OR_CTRL | Key::V), EDIT_PASTE_KEYS);
|
||||||
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/add_reset_value", TTR("Add RESET Value(s)")));
|
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/add_reset_value", TTR("Add RESET Value(s)")));
|
||||||
edit->get_popup()->add_separator();
|
edit->get_popup()->add_separator();
|
||||||
|
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/move_first_selected_key_to_cursor", TTR("Move First Selected Key to Cursor"), Key::BRACKETLEFT), EDIT_MOVE_FIRST_SELECTED_KEY_TO_CURSOR);
|
||||||
|
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/move_last_selected_key_to_cursor", TTR("Move Last Selected Key to Cursor"), Key::BRACKETRIGHT), EDIT_MOVE_LAST_SELECTED_KEY_TO_CURSOR);
|
||||||
|
edit->get_popup()->add_separator();
|
||||||
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/delete_selection", TTR("Delete Selection"), Key::KEY_DELETE), EDIT_DELETE_SELECTION);
|
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/delete_selection", TTR("Delete Selection"), Key::KEY_DELETE), EDIT_DELETE_SELECTION);
|
||||||
|
|
||||||
edit->get_popup()->add_separator();
|
edit->get_popup()->add_separator();
|
||||||
|
@ -7083,12 +7250,21 @@ AnimationTrackEditor::AnimationTrackEditor() {
|
||||||
optimize_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_OPTIMIZE_ANIMATION_CONFIRM));
|
optimize_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_OPTIMIZE_ANIMATION_CONFIRM));
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
cleanup_dialog = memnew(ConfirmationDialog);
|
cleanup_dialog = memnew(ConfirmationDialog);
|
||||||
add_child(cleanup_dialog);
|
add_child(cleanup_dialog);
|
||||||
VBoxContainer *cleanup_vb = memnew(VBoxContainer);
|
VBoxContainer *cleanup_vb = memnew(VBoxContainer);
|
||||||
cleanup_dialog->add_child(cleanup_vb);
|
cleanup_dialog->add_child(cleanup_vb);
|
||||||
|
|
||||||
|
cleanup_keys_with_trimming_head = memnew(CheckBox);
|
||||||
|
cleanup_keys_with_trimming_head->set_text(TTR("Trim keys placed in negative time"));
|
||||||
|
cleanup_keys_with_trimming_head->set_pressed(true);
|
||||||
|
cleanup_vb->add_child(cleanup_keys_with_trimming_head);
|
||||||
|
|
||||||
|
cleanup_keys_with_trimming_end = memnew(CheckBox);
|
||||||
|
cleanup_keys_with_trimming_end->set_text(TTR("Trim keys placed exceed the animation length"));
|
||||||
|
cleanup_keys_with_trimming_end->set_pressed(true);
|
||||||
|
cleanup_vb->add_child(cleanup_keys_with_trimming_end);
|
||||||
|
|
||||||
cleanup_keys = memnew(CheckBox);
|
cleanup_keys = memnew(CheckBox);
|
||||||
cleanup_keys->set_text(TTR("Remove invalid keys"));
|
cleanup_keys->set_text(TTR("Remove invalid keys"));
|
||||||
cleanup_keys->set_pressed(true);
|
cleanup_keys->set_pressed(true);
|
||||||
|
|
|
@ -556,6 +556,8 @@ class AnimationTrackEditor : public VBoxContainer {
|
||||||
SpinBox *optimize_precision_error = nullptr;
|
SpinBox *optimize_precision_error = nullptr;
|
||||||
|
|
||||||
ConfirmationDialog *cleanup_dialog = nullptr;
|
ConfirmationDialog *cleanup_dialog = nullptr;
|
||||||
|
CheckBox *cleanup_keys_with_trimming_head = nullptr;
|
||||||
|
CheckBox *cleanup_keys_with_trimming_end = nullptr;
|
||||||
CheckBox *cleanup_keys = nullptr;
|
CheckBox *cleanup_keys = nullptr;
|
||||||
CheckBox *cleanup_tracks = nullptr;
|
CheckBox *cleanup_tracks = nullptr;
|
||||||
CheckBox *cleanup_all = nullptr;
|
CheckBox *cleanup_all = nullptr;
|
||||||
|
@ -654,9 +656,15 @@ public:
|
||||||
EDIT_SCALE_SELECTION,
|
EDIT_SCALE_SELECTION,
|
||||||
EDIT_SCALE_FROM_CURSOR,
|
EDIT_SCALE_FROM_CURSOR,
|
||||||
EDIT_SCALE_CONFIRM,
|
EDIT_SCALE_CONFIRM,
|
||||||
|
EDIT_SET_START_OFFSET,
|
||||||
|
EDIT_SET_END_OFFSET,
|
||||||
EDIT_EASE_SELECTION,
|
EDIT_EASE_SELECTION,
|
||||||
EDIT_EASE_CONFIRM,
|
EDIT_EASE_CONFIRM,
|
||||||
EDIT_DUPLICATE_SELECTED_KEYS,
|
EDIT_DUPLICATE_SELECTED_KEYS,
|
||||||
|
EDIT_DUPLICATE_SELECTION,
|
||||||
|
EDIT_DUPLICATE_TRANSPOSED,
|
||||||
|
EDIT_MOVE_FIRST_SELECTED_KEY_TO_CURSOR,
|
||||||
|
EDIT_MOVE_LAST_SELECTED_KEY_TO_CURSOR,
|
||||||
EDIT_ADD_RESET_KEY,
|
EDIT_ADD_RESET_KEY,
|
||||||
EDIT_DELETE_SELECTION,
|
EDIT_DELETE_SELECTION,
|
||||||
EDIT_GOTO_NEXT_STEP,
|
EDIT_GOTO_NEXT_STEP,
|
||||||
|
|
|
@ -140,3 +140,10 @@ Validate extension JSON: Error: Field 'classes/Animation/methods/blend_shape_tra
|
||||||
Validate extension JSON: Error: Field 'classes/Animation/methods/value_track_interpolate/arguments': size changed value in new API, from 2 to 3.
|
Validate extension JSON: Error: Field 'classes/Animation/methods/value_track_interpolate/arguments': size changed value in new API, from 2 to 3.
|
||||||
|
|
||||||
Added optional argument to track_interpolate to treat playing backward correctly. Compatibility method registered.
|
Added optional argument to track_interpolate to treat playing backward correctly. Compatibility method registered.
|
||||||
|
|
||||||
|
|
||||||
|
GH-86661
|
||||||
|
--------
|
||||||
|
Validate extension JSON: Error: Field 'classes/Animation/methods/track_find_key/arguments': size changed value in new API, from 3 to 4.
|
||||||
|
|
||||||
|
Added optional argument to track_find_key to avoid finding keys out of the animation range. Compatibility method registered.
|
||||||
|
|
|
@ -1458,7 +1458,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (seeked) {
|
if (seeked) {
|
||||||
int idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT);
|
int idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT, true);
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1494,7 +1494,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
|
||||||
}
|
}
|
||||||
TrackCacheMethod *t = static_cast<TrackCacheMethod *>(track);
|
TrackCacheMethod *t = static_cast<TrackCacheMethod *>(track);
|
||||||
if (seeked) {
|
if (seeked) {
|
||||||
int idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT);
|
int idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT, true);
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1541,7 +1541,9 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
|
||||||
// Find stream.
|
// Find stream.
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
if (seeked) {
|
if (seeked) {
|
||||||
idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT);
|
// Audio key may be playbacked from the middle, should use FIND_MODE_NEAREST.
|
||||||
|
// Then, check the current playing stream to prevent to playback doubly.
|
||||||
|
idx = a->track_find_key(i, time, Animation::FIND_MODE_NEAREST, true);
|
||||||
// Discard previous stream when seeking.
|
// Discard previous stream when seeking.
|
||||||
if (map.has(idx)) {
|
if (map.has(idx)) {
|
||||||
t->audio_stream_playback->stop_stream(map[idx].index);
|
t->audio_stream_playback->stop_stream(map[idx].index);
|
||||||
|
@ -1609,7 +1611,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) {
|
||||||
}
|
}
|
||||||
if (seeked) {
|
if (seeked) {
|
||||||
// Seek.
|
// Seek.
|
||||||
int idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT);
|
int idx = a->track_find_key(i, time, is_external_seeking ? Animation::FIND_MODE_NEAREST : Animation::FIND_MODE_EXACT, true);
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,12 +50,17 @@ Variant Animation::_value_track_interpolate_bind_compat_86629(int p_track, doubl
|
||||||
return value_track_interpolate(p_track, p_time, false);
|
return value_track_interpolate(p_track, p_time, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Animation::_track_find_key_bind_compat_86661(int p_track, double p_time, FindMode p_find_mode) const {
|
||||||
|
return track_find_key(p_track, p_time, p_find_mode, false);
|
||||||
|
}
|
||||||
|
|
||||||
void Animation::_bind_compatibility_methods() {
|
void Animation::_bind_compatibility_methods() {
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("position_track_interpolate", "track_idx", "time_sec"), &Animation::_position_track_interpolate_bind_compat_86629);
|
ClassDB::bind_compatibility_method(D_METHOD("position_track_interpolate", "track_idx", "time_sec"), &Animation::_position_track_interpolate_bind_compat_86629);
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("rotation_track_interpolate", "track_idx", "time_sec"), &Animation::_rotation_track_interpolate_bind_compat_86629);
|
ClassDB::bind_compatibility_method(D_METHOD("rotation_track_interpolate", "track_idx", "time_sec"), &Animation::_rotation_track_interpolate_bind_compat_86629);
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("scale_track_interpolate", "track_idx", "time_sec"), &Animation::_scale_track_interpolate_bind_compat_86629);
|
ClassDB::bind_compatibility_method(D_METHOD("scale_track_interpolate", "track_idx", "time_sec"), &Animation::_scale_track_interpolate_bind_compat_86629);
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("blend_shape_track_interpolate", "track_idx", "time_sec"), &Animation::_blend_shape_track_interpolate_bind_compat_86629);
|
ClassDB::bind_compatibility_method(D_METHOD("blend_shape_track_interpolate", "track_idx", "time_sec"), &Animation::_blend_shape_track_interpolate_bind_compat_86629);
|
||||||
ClassDB::bind_compatibility_method(D_METHOD("value_track_interpolate", "track_idx", "time_sec"), &Animation::_value_track_interpolate_bind_compat_86629);
|
ClassDB::bind_compatibility_method(D_METHOD("value_track_interpolate", "track_idx", "time_sec"), &Animation::_value_track_interpolate_bind_compat_86629);
|
||||||
|
ClassDB::bind_compatibility_method(D_METHOD("track_find_key", "track_idx", "time", "find_mode"), &Animation::_track_find_key_bind_compat_86661, DEFVAL(FIND_MODE_NEAREST));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // DISABLE_DEPRECATED
|
#endif // DISABLE_DEPRECATED
|
||||||
|
|
|
@ -1474,7 +1474,7 @@ void Animation::track_remove_key(int p_track, int p_idx) {
|
||||||
emit_changed();
|
emit_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode) const {
|
int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode, bool p_limit) const {
|
||||||
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
|
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
|
||||||
Track *t = tracks[p_track];
|
Track *t = tracks[p_track];
|
||||||
|
|
||||||
|
@ -1496,7 +1496,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode)
|
||||||
return key_index;
|
return key_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
int k = _find(tt->positions, p_time);
|
int k = _find(tt->positions, p_time, false, p_limit);
|
||||||
if (k < 0 || k >= tt->positions.size()) {
|
if (k < 0 || k >= tt->positions.size()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1523,7 +1523,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode)
|
||||||
return key_index;
|
return key_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
int k = _find(rt->rotations, p_time);
|
int k = _find(rt->rotations, p_time, false, p_limit);
|
||||||
if (k < 0 || k >= rt->rotations.size()) {
|
if (k < 0 || k >= rt->rotations.size()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1550,7 +1550,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode)
|
||||||
return key_index;
|
return key_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
int k = _find(st->scales, p_time);
|
int k = _find(st->scales, p_time, false, p_limit);
|
||||||
if (k < 0 || k >= st->scales.size()) {
|
if (k < 0 || k >= st->scales.size()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1577,7 +1577,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode)
|
||||||
return key_index;
|
return key_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
int k = _find(bst->blend_shapes, p_time);
|
int k = _find(bst->blend_shapes, p_time, false, p_limit);
|
||||||
if (k < 0 || k >= bst->blend_shapes.size()) {
|
if (k < 0 || k >= bst->blend_shapes.size()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1589,7 +1589,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode)
|
||||||
} break;
|
} break;
|
||||||
case TYPE_VALUE: {
|
case TYPE_VALUE: {
|
||||||
ValueTrack *vt = static_cast<ValueTrack *>(t);
|
ValueTrack *vt = static_cast<ValueTrack *>(t);
|
||||||
int k = _find(vt->values, p_time);
|
int k = _find(vt->values, p_time, false, p_limit);
|
||||||
if (k < 0 || k >= vt->values.size()) {
|
if (k < 0 || k >= vt->values.size()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1601,7 +1601,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode)
|
||||||
} break;
|
} break;
|
||||||
case TYPE_METHOD: {
|
case TYPE_METHOD: {
|
||||||
MethodTrack *mt = static_cast<MethodTrack *>(t);
|
MethodTrack *mt = static_cast<MethodTrack *>(t);
|
||||||
int k = _find(mt->methods, p_time);
|
int k = _find(mt->methods, p_time, false, p_limit);
|
||||||
if (k < 0 || k >= mt->methods.size()) {
|
if (k < 0 || k >= mt->methods.size()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1613,7 +1613,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode)
|
||||||
} break;
|
} break;
|
||||||
case TYPE_BEZIER: {
|
case TYPE_BEZIER: {
|
||||||
BezierTrack *bt = static_cast<BezierTrack *>(t);
|
BezierTrack *bt = static_cast<BezierTrack *>(t);
|
||||||
int k = _find(bt->values, p_time);
|
int k = _find(bt->values, p_time, false, p_limit);
|
||||||
if (k < 0 || k >= bt->values.size()) {
|
if (k < 0 || k >= bt->values.size()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1625,7 +1625,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode)
|
||||||
} break;
|
} break;
|
||||||
case TYPE_AUDIO: {
|
case TYPE_AUDIO: {
|
||||||
AudioTrack *at = static_cast<AudioTrack *>(t);
|
AudioTrack *at = static_cast<AudioTrack *>(t);
|
||||||
int k = _find(at->values, p_time);
|
int k = _find(at->values, p_time, false, p_limit);
|
||||||
if (k < 0 || k >= at->values.size()) {
|
if (k < 0 || k >= at->values.size()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1637,7 +1637,7 @@ int Animation::track_find_key(int p_track, double p_time, FindMode p_find_mode)
|
||||||
} break;
|
} break;
|
||||||
case TYPE_ANIMATION: {
|
case TYPE_ANIMATION: {
|
||||||
AnimationTrack *at = static_cast<AnimationTrack *>(t);
|
AnimationTrack *at = static_cast<AnimationTrack *>(t);
|
||||||
int k = _find(at->values, p_time);
|
int k = _find(at->values, p_time, false, p_limit);
|
||||||
if (k < 0 || k >= at->values.size()) {
|
if (k < 0 || k >= at->values.size()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -2332,7 +2332,7 @@ void Animation::track_set_key_transition(int p_track, int p_key_idx, real_t p_tr
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class K>
|
template <class K>
|
||||||
int Animation::_find(const Vector<K> &p_keys, double p_time, bool p_backward) const {
|
int Animation::_find(const Vector<K> &p_keys, double p_time, bool p_backward, bool p_limit) const {
|
||||||
int len = p_keys.size();
|
int len = p_keys.size();
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
return -2;
|
return -2;
|
||||||
|
@ -2344,7 +2344,7 @@ int Animation::_find(const Vector<K> &p_keys, double p_time, bool p_backward) co
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (low > high) {
|
if (low > high) {
|
||||||
ERR_PRINT("low > high, this may be a bug");
|
ERR_PRINT("low > high, this may be a bug.");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2372,6 +2372,14 @@ int Animation::_find(const Vector<K> &p_keys, double p_time, bool p_backward) co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_limit) {
|
||||||
|
double diff = length - keys[middle].time;
|
||||||
|
if ((signbit(keys[middle].time) && !Math::is_zero_approx(keys[middle].time)) || (signbit(diff) && !Math::is_zero_approx(diff))) {
|
||||||
|
ERR_PRINT_ONCE_ED("Found the key outside the animation range. Consider using the clean-up option in AnimationTrackEditor to fix it.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return middle;
|
return middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3804,7 +3812,7 @@ void Animation::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("track_get_key_count", "track_idx"), &Animation::track_get_key_count);
|
ClassDB::bind_method(D_METHOD("track_get_key_count", "track_idx"), &Animation::track_get_key_count);
|
||||||
ClassDB::bind_method(D_METHOD("track_get_key_value", "track_idx", "key_idx"), &Animation::track_get_key_value);
|
ClassDB::bind_method(D_METHOD("track_get_key_value", "track_idx", "key_idx"), &Animation::track_get_key_value);
|
||||||
ClassDB::bind_method(D_METHOD("track_get_key_time", "track_idx", "key_idx"), &Animation::track_get_key_time);
|
ClassDB::bind_method(D_METHOD("track_get_key_time", "track_idx", "key_idx"), &Animation::track_get_key_time);
|
||||||
ClassDB::bind_method(D_METHOD("track_find_key", "track_idx", "time", "find_mode"), &Animation::track_find_key, DEFVAL(FIND_MODE_NEAREST));
|
ClassDB::bind_method(D_METHOD("track_find_key", "track_idx", "time", "find_mode", "limit"), &Animation::track_find_key, DEFVAL(FIND_MODE_NEAREST), DEFVAL(false));
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("track_set_interpolation_type", "track_idx", "interpolation"), &Animation::track_set_interpolation_type);
|
ClassDB::bind_method(D_METHOD("track_set_interpolation_type", "track_idx", "interpolation"), &Animation::track_set_interpolation_type);
|
||||||
ClassDB::bind_method(D_METHOD("track_get_interpolation_type", "track_idx"), &Animation::track_get_interpolation_type);
|
ClassDB::bind_method(D_METHOD("track_get_interpolation_type", "track_idx"), &Animation::track_get_interpolation_type);
|
||||||
|
|
|
@ -44,13 +44,13 @@ public:
|
||||||
typedef uint32_t TypeHash;
|
typedef uint32_t TypeHash;
|
||||||
|
|
||||||
enum TrackType {
|
enum TrackType {
|
||||||
TYPE_VALUE, ///< Set a value in a property, can be interpolated.
|
TYPE_VALUE, // Set a value in a property, can be interpolated.
|
||||||
TYPE_POSITION_3D, ///< Position 3D track
|
TYPE_POSITION_3D, // Position 3D track, can be compressed.
|
||||||
TYPE_ROTATION_3D, ///< Rotation 3D track
|
TYPE_ROTATION_3D, // Rotation 3D track, can be compressed.
|
||||||
TYPE_SCALE_3D, ///< Scale 3D track
|
TYPE_SCALE_3D, // Scale 3D track, can be compressed.
|
||||||
TYPE_BLEND_SHAPE, ///< Blend Shape track
|
TYPE_BLEND_SHAPE, // Blend Shape track, can be compressed.
|
||||||
TYPE_METHOD, ///< Call any method on a specific node.
|
TYPE_METHOD, // Call any method on a specific node.
|
||||||
TYPE_BEZIER, ///< Bezier curve
|
TYPE_BEZIER, // Bezier curve.
|
||||||
TYPE_AUDIO,
|
TYPE_AUDIO,
|
||||||
TYPE_ANIMATION,
|
TYPE_ANIMATION,
|
||||||
};
|
};
|
||||||
|
@ -116,10 +116,10 @@ private:
|
||||||
|
|
||||||
struct Key {
|
struct Key {
|
||||||
real_t transition = 1.0;
|
real_t transition = 1.0;
|
||||||
double time = 0.0; // time in secs
|
double time = 0.0; // Time in secs.
|
||||||
};
|
};
|
||||||
|
|
||||||
// transform key holds either Vector3 or Quaternion
|
// Transform key holds either Vector3 or Quaternion.
|
||||||
template <class T>
|
template <class T>
|
||||||
struct TKey : public Key {
|
struct TKey : public Key {
|
||||||
T value;
|
T value;
|
||||||
|
@ -188,8 +188,8 @@ private:
|
||||||
|
|
||||||
/* BEZIER TRACK */
|
/* BEZIER TRACK */
|
||||||
struct BezierKey {
|
struct BezierKey {
|
||||||
Vector2 in_handle; //relative (x always <0)
|
Vector2 in_handle; // Relative (x always <0)
|
||||||
Vector2 out_handle; //relative (x always >0)
|
Vector2 out_handle; // Relative (x always >0)
|
||||||
real_t value = 0.0;
|
real_t value = 0.0;
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
HandleMode handle_mode = HANDLE_MODE_FREE;
|
HandleMode handle_mode = HANDLE_MODE_FREE;
|
||||||
|
@ -208,8 +208,8 @@ private:
|
||||||
|
|
||||||
struct AudioKey {
|
struct AudioKey {
|
||||||
Ref<Resource> stream;
|
Ref<Resource> stream;
|
||||||
real_t start_offset = 0.0; //offset from start
|
real_t start_offset = 0.0; // Offset from start.
|
||||||
real_t end_offset = 0.0; //offset from end, if 0 then full length or infinite
|
real_t end_offset = 0.0; // Offset from end, if 0 then full length or infinite.
|
||||||
AudioKey() {
|
AudioKey() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -235,10 +235,6 @@ private:
|
||||||
|
|
||||||
Vector<Track *> tracks;
|
Vector<Track *> tracks;
|
||||||
|
|
||||||
/*
|
|
||||||
template<class T>
|
|
||||||
int _insert_pos(double p_time, T& p_keys);*/
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void _clear(T &p_keys);
|
void _clear(T &p_keys);
|
||||||
|
|
||||||
|
@ -247,7 +243,7 @@ private:
|
||||||
|
|
||||||
template <class K>
|
template <class K>
|
||||||
|
|
||||||
inline int _find(const Vector<K> &p_keys, double p_time, bool p_backward = false) const;
|
inline int _find(const Vector<K> &p_keys, double p_time, bool p_backward = false, bool p_limit = false) const;
|
||||||
|
|
||||||
_FORCE_INLINE_ Vector3 _interpolate(const Vector3 &p_a, const Vector3 &p_b, real_t p_c) const;
|
_FORCE_INLINE_ Vector3 _interpolate(const Vector3 &p_a, const Vector3 &p_b, real_t p_c) const;
|
||||||
_FORCE_INLINE_ Quaternion _interpolate(const Quaternion &p_a, const Quaternion &p_b, real_t p_c) const;
|
_FORCE_INLINE_ Quaternion _interpolate(const Quaternion &p_a, const Quaternion &p_b, real_t p_c) const;
|
||||||
|
@ -327,7 +323,7 @@ private:
|
||||||
struct Compression {
|
struct Compression {
|
||||||
enum {
|
enum {
|
||||||
MAX_DATA_TRACK_SIZE = 16384,
|
MAX_DATA_TRACK_SIZE = 16384,
|
||||||
BLEND_SHAPE_RANGE = 8, // - 8.0 to 8.0
|
BLEND_SHAPE_RANGE = 8, // -8.0 to 8.0.
|
||||||
FORMAT_VERSION = 1
|
FORMAT_VERSION = 1
|
||||||
};
|
};
|
||||||
struct Page {
|
struct Page {
|
||||||
|
@ -337,7 +333,7 @@ private:
|
||||||
|
|
||||||
uint32_t fps = 120;
|
uint32_t fps = 120;
|
||||||
LocalVector<Page> pages;
|
LocalVector<Page> pages;
|
||||||
LocalVector<AABB> bounds; //used by position and scale tracks (which contain index to track and index to bounds).
|
LocalVector<AABB> bounds; // Used by position and scale tracks (which contain index to track and index to bounds).
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
} compression;
|
} compression;
|
||||||
|
|
||||||
|
@ -386,6 +382,7 @@ protected:
|
||||||
Vector3 _scale_track_interpolate_bind_compat_86629(int p_track, double p_time) const;
|
Vector3 _scale_track_interpolate_bind_compat_86629(int p_track, double p_time) const;
|
||||||
float _blend_shape_track_interpolate_bind_compat_86629(int p_track, double p_time) const;
|
float _blend_shape_track_interpolate_bind_compat_86629(int p_track, double p_time) const;
|
||||||
Variant _value_track_interpolate_bind_compat_86629(int p_track, double p_time) const;
|
Variant _value_track_interpolate_bind_compat_86629(int p_track, double p_time) const;
|
||||||
|
int _track_find_key_bind_compat_86661(int p_track, double p_time, FindMode p_find_mode = FIND_MODE_NEAREST) const;
|
||||||
static void _bind_compatibility_methods();
|
static void _bind_compatibility_methods();
|
||||||
#endif // DISABLE_DEPRECATED
|
#endif // DISABLE_DEPRECATED
|
||||||
|
|
||||||
|
@ -417,7 +414,7 @@ public:
|
||||||
void track_set_key_transition(int p_track, int p_key_idx, real_t p_transition);
|
void track_set_key_transition(int p_track, int p_key_idx, real_t p_transition);
|
||||||
void track_set_key_value(int p_track, int p_key_idx, const Variant &p_value);
|
void track_set_key_value(int p_track, int p_key_idx, const Variant &p_value);
|
||||||
void track_set_key_time(int p_track, int p_key_idx, double p_time);
|
void track_set_key_time(int p_track, int p_key_idx, double p_time);
|
||||||
int track_find_key(int p_track, double p_time, FindMode p_find_mode = FIND_MODE_NEAREST) const;
|
int track_find_key(int p_track, double p_time, FindMode p_find_mode = FIND_MODE_NEAREST, bool p_limit = false) const;
|
||||||
void track_remove_key(int p_track, int p_idx);
|
void track_remove_key(int p_track, int p_idx);
|
||||||
void track_remove_key_at_time(int p_track, double p_time);
|
void track_remove_key_at_time(int p_track, double p_time);
|
||||||
int track_get_key_count(int p_track) const;
|
int track_get_key_count(int p_track) const;
|
||||||
|
@ -503,7 +500,7 @@ public:
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void optimize(real_t p_allowed_velocity_err = 0.01, real_t p_allowed_angular_err = 0.01, int p_precision = 3);
|
void optimize(real_t p_allowed_velocity_err = 0.01, real_t p_allowed_angular_err = 0.01, int p_precision = 3);
|
||||||
void compress(uint32_t p_page_size = 8192, uint32_t p_fps = 120, float p_split_tolerance = 4.0); // 4.0 seems to be the split tolerance sweet spot from many tests
|
void compress(uint32_t p_page_size = 8192, uint32_t p_fps = 120, float p_split_tolerance = 4.0); // 4.0 seems to be the split tolerance sweet spot from many tests.
|
||||||
|
|
||||||
// Helper functions for Variant.
|
// Helper functions for Variant.
|
||||||
static bool is_variant_interpolatable(const Variant p_value);
|
static bool is_variant_interpolatable(const Variant p_value);
|
||||||
|
|
Loading…
Reference in a new issue