From 73d041dd985ef8802eeb98fcb1955643f79b373e Mon Sep 17 00:00:00 2001 From: "Silc Lizard (Tokage) Renew" <61938263+TokageItLab@users.noreply.github.com> Date: Tue, 2 Dec 2025 21:39:47 +0900 Subject: [PATCH] Optimize Animation Resource, Library, Mixer, Player Co-Authored-By: Silc Lizard (Tokage) Renew --- .../animation_blend_space_1d_editor.cpp | 5 +- .../animation_blend_space_2d_editor.cpp | 4 +- .../animation_blend_tree_editor_plugin.cpp | 10 +- editor/animation/animation_library_editor.cpp | 14 +- .../animation_player_editor_plugin.cpp | 20 +- .../animation_state_machine_editor.cpp | 4 +- editor/animation/animation_track_editor.cpp | 16 +- .../animation_tree_editor_plugin.cpp | 15 +- .../animation/animation_tree_editor_plugin.h | 2 +- editor/docks/scene_tree_dock.cpp | 9 +- .../post_import_plugin_skeleton_renamer.cpp | 8 +- ...post_import_plugin_skeleton_rest_fixer.cpp | 24 +- ...import_plugin_skeleton_track_organizer.cpp | 4 +- editor/import/3d/resource_importer_scene.cpp | 32 +-- editor/import/3d/scene_import_settings.cpp | 8 +- editor/scene/3d/root_motion_editor_plugin.cpp | 5 +- editor/settings/editor_folding.cpp | 2 +- .../4.6-stable/GH-116394.txt | 6 + modules/gltf/gltf_document.cpp | 4 +- scene/animation/animation_blend_tree.cpp | 6 +- scene/animation/animation_blend_tree.h | 2 +- scene/animation/animation_mixer.cpp | 220 +++++++++------ scene/animation/animation_mixer.h | 37 +-- scene/animation/animation_player.cpp | 61 +++-- scene/animation/animation_player.h | 2 +- scene/animation/animation_tree.cpp | 3 +- scene/resources/animation.cpp | 250 +++++++++--------- scene/resources/animation.h | 12 +- scene/resources/animation_library.cpp | 8 +- scene/resources/animation_library.h | 2 +- 30 files changed, 394 insertions(+), 401 deletions(-) create mode 100644 misc/extension_api_validation/4.6-stable/GH-116394.txt diff --git a/editor/animation/animation_blend_space_1d_editor.cpp b/editor/animation/animation_blend_space_1d_editor.cpp index f3a6fb19cf..dc80ddce2f 100644 --- a/editor/animation/animation_blend_space_1d_editor.cpp +++ b/editor/animation/animation_blend_space_1d_editor.cpp @@ -84,10 +84,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Refadd_submenu_node_item(TTR("Add Animation"), animations_menu); - List names; - tree->get_animation_list(&names); - - for (const StringName &E : names) { + for (const StringName &E : tree->get_sorted_animation_list()) { animations_menu->add_icon_item(get_editor_theme_icon(SNAME("Animation")), E); animations_to_add.push_back(E); } diff --git a/editor/animation/animation_blend_space_2d_editor.cpp b/editor/animation/animation_blend_space_2d_editor.cpp index 930077fcb6..a86938e918 100644 --- a/editor/animation/animation_blend_space_2d_editor.cpp +++ b/editor/animation/animation_blend_space_2d_editor.cpp @@ -128,9 +128,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Refadd_submenu_node_item(TTR("Add Animation"), animations_menu); - List names; - tree->get_animation_list(&names); - for (const StringName &E : names) { + for (const StringName &E : tree->get_sorted_animation_list()) { animations_menu->add_icon_item(get_editor_theme_icon(SNAME("Animation")), E); animations_to_add.push_back(E); } diff --git a/editor/animation/animation_blend_tree_editor_plugin.cpp b/editor/animation/animation_blend_tree_editor_plugin.cpp index 7dbe52f130..08a4de95b4 100644 --- a/editor/animation/animation_blend_tree_editor_plugin.cpp +++ b/editor/animation/animation_blend_tree_editor_plugin.cpp @@ -275,10 +275,7 @@ void AnimationNodeBlendTreeEditor::update_graph() { ProgressBar *pb = memnew(ProgressBar); - List anims; - tree->get_animation_list(&anims); - - for (const StringName &F : anims) { + for (const StringName &F : tree->get_sorted_animation_list()) { mb->get_popup()->add_item(F); options.push_back(F); } @@ -801,10 +798,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref &ano HashSet paths; HashMap> types; { - List animation_list; - tree->get_animation_list(&animation_list); - - for (const StringName &E : animation_list) { + for (const StringName &E : tree->get_sorted_animation_list()) { Ref anim = tree->get_animation(E); for (int i = 0; i < anim->get_track_count(); i++) { String track_path = String(anim->track_get_path(i)); diff --git a/editor/animation/animation_library_editor.cpp b/editor/animation/animation_library_editor.cpp index 35b61e35eb..55b16ce973 100644 --- a/editor/animation/animation_library_editor.cpp +++ b/editor/animation/animation_library_editor.cpp @@ -212,7 +212,7 @@ void AnimationLibraryEditor::_file_popup_selected(int p_id) { } break; case FILE_MENU_MAKE_LIBRARY_UNIQUE: { StringName lib_name = file_dialog_library; - List animation_list; + LocalVector animation_list; Ref ald = memnew(AnimationLibrary); al->get_animation_list(&animation_list); @@ -377,7 +377,7 @@ void AnimationLibraryEditor::_load_files(const PackedStringArray &p_paths) { continue; } - List libs; + LocalVector libs; mixer->get_animation_library_list(&libs); bool is_already_added = false; for (const StringName &K : libs) { @@ -423,7 +423,7 @@ void AnimationLibraryEditor::_load_files(const PackedStringArray &p_paths) { continue; } - List anims; + LocalVector anims; al->get_animation_list(&anims); bool is_already_added = false; for (const StringName &K : anims) { @@ -686,7 +686,7 @@ void AnimationLibraryEditor::update_tree() { Color ss_color = get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)); TreeItem *root = tree->create_item(); - List libs; + LocalVector libs; const Vector collapsed_libs = _load_mixer_libs_folding(); mixer->get_animation_library_list(&libs); @@ -743,7 +743,7 @@ void AnimationLibraryEditor::update_tree() { libitem->set_custom_bg_color(0, ss_color); - List animations; + LocalVector animations; al->get_animation_list(&animations); for (const StringName &L : animations) { TreeItem *anitem = tree->create_item(libitem); @@ -888,7 +888,7 @@ String AnimationLibraryEditor::_get_mixer_signature() const { String signature = String(); // Get all libraries sorted for consistency - List libs; + LocalVector libs; mixer->get_animation_library_list(&libs); libs.sort_custom(); @@ -897,7 +897,7 @@ String AnimationLibraryEditor::_get_mixer_signature() const { signature += "::" + String(lib_name); Ref lib = mixer->get_animation_library(lib_name); if (lib.is_valid()) { - List anims; + LocalVector anims; lib->get_animation_list(&anims); anims.sort_custom(); for (const StringName &anim_name : anims) { diff --git a/editor/animation/animation_player_editor_plugin.cpp b/editor/animation/animation_player_editor_plugin.cpp index 53703ba332..dc8c706ccd 100644 --- a/editor/animation/animation_player_editor_plugin.cpp +++ b/editor/animation/animation_player_editor_plugin.cpp @@ -829,10 +829,8 @@ void AnimationPlayerEditor::_update_animation_blend() { blend_editor.tree->clear(); - String current = animation->get_item_text(animation->get_selected()); + StringName current = animation->get_item_text(animation->get_selected()); - List anims; - player->get_animation_list(&anims); TreeItem *root = blend_editor.tree->create_item(); updating_blends = true; @@ -841,7 +839,7 @@ void AnimationPlayerEditor::_update_animation_blend() { blend_editor.next->clear(); blend_editor.next->add_item("", i); - for (const StringName &to : anims) { + for (const StringName &to : player->get_sorted_animation_list()) { TreeItem *blend = blend_editor.tree->create_item(root); blend->set_editable(0, false); blend->set_editable(1, true); @@ -1038,7 +1036,7 @@ void AnimationPlayerEditor::_update_player() { return; } - List libraries; + LocalVector libraries; player->get_animation_library_list(&libraries); int active_idx = -1; @@ -1063,7 +1061,7 @@ void AnimationPlayerEditor::_update_player() { } } - List animlist; + LocalVector animlist; anim_library->get_animation_list(&animlist); for (const StringName &E : animlist) { @@ -1169,7 +1167,7 @@ void AnimationPlayerEditor::_update_name_dialog_library_dropdown() { } } - List libraries; + LocalVector libraries; player->get_animation_library_list(&libraries); library->clear(); @@ -1511,7 +1509,7 @@ void AnimationPlayerEditor::_current_animation_changed(const StringName &p_name) } // Determine the read-only status of the animation's library and the libraries as a whole. - List libraries; + LocalVector libraries; player->get_animation_library_list(&libraries); bool current_animation_library_is_readonly = false; @@ -1523,7 +1521,7 @@ void AnimationPlayerEditor::_current_animation_changed(const StringName &p_name) all_animation_libraries_are_readonly = false; } - List animlist; + LocalVector animlist; anim_library->get_animation_list(&animlist); bool animation_found = false; for (const StringName &E : animlist) { @@ -2464,13 +2462,13 @@ void AnimationPlayerEditorPlugin::_update_dummy_player(AnimationMixer *p_mixer) memdelete(default_node); // Library list is dynamically added to property list, should be copied explicitly. - List existing_libs; + LocalVector existing_libs; dummy_player->get_animation_library_list(&existing_libs); for (const StringName &K : existing_libs) { dummy_player->remove_animation_library(K); } - List libraries; + LocalVector libraries; p_mixer->get_animation_library_list(&libraries); for (const StringName &K : libraries) { dummy_player->add_animation_library(K, p_mixer->get_animation_library(K)); diff --git a/editor/animation/animation_state_machine_editor.cpp b/editor/animation/animation_state_machine_editor.cpp index 8385122801..fbdaddeb5e 100644 --- a/editor/animation/animation_state_machine_editor.cpp +++ b/editor/animation/animation_state_machine_editor.cpp @@ -44,6 +44,7 @@ #include "scene/gui/line_edit.h" #include "scene/gui/option_button.h" #include "scene/gui/panel_container.h" +#include "scene/gui/rich_text_label.h" #include "scene/gui/separator.h" #include "scene/main/viewport.h" #include "scene/main/window.h" @@ -823,8 +824,7 @@ void AnimationNodeStateMachineEditor::_open_menu(const Vector2 &p_position) { animations_menu->clear(); animations_to_add.clear(); - List animation_names; - tree->get_animation_list(&animation_names); + LocalVector animation_names = tree->get_sorted_animation_list(); menu->add_submenu_node_item(TTR("Add Animation"), animations_menu); if (animation_names.is_empty()) { menu->set_item_disabled(menu->get_item_idx_from_text(TTR("Add Animation")), true); diff --git a/editor/animation/animation_track_editor.cpp b/editor/animation/animation_track_editor.cpp index 3ad6ad9319..01faa868a1 100644 --- a/editor/animation/animation_track_editor.cpp +++ b/editor/animation/animation_track_editor.cpp @@ -649,9 +649,7 @@ void AnimationTrackKeyEdit::_get_property_list(List *p_list) const if (root_path) { AnimationPlayer *ap = Object::cast_to(root_path->get_node_or_null(animation->track_get_path(track))); if (ap) { - List anims; - ap->get_animation_list(&anims); - for (const StringName &E : anims) { + for (const StringName &E : ap->get_sorted_animation_list()) { if (!animations.is_empty()) { animations += ","; } @@ -1255,9 +1253,7 @@ void AnimationMultiTrackKeyEdit::_get_property_list(List *p_list) if (root_path) { AnimationPlayer *ap = Object::cast_to(root_path->get_node_or_null(animation->track_get_path(first_track))); if (ap) { - List anims; - ap->get_animation_list(&anims); - for (const StringName &anim : anims) { + for (const StringName &anim : ap->get_sorted_animation_list()) { if (!animations.is_empty()) { animations += ","; } @@ -4290,10 +4286,8 @@ void AnimationTrackEditor::_animation_track_remove_request(int p_track, Reftrack_get_path(i) == p_from_animation->track_get_path(p_track)) { // Check if the reset track isn't used by other animations. bool used = false; - List animation_list; - player->get_animation_list(&animation_list); - for (const StringName &anim_name : animation_list) { + for (const StringName &anim_name : player->get_sorted_animation_list()) { Ref anim = player->get_animation(anim_name); if (anim == p_from_animation || anim == reset) { continue; @@ -7716,9 +7710,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { } break; case EDIT_CLEAN_UP_ANIMATION_CONFIRM: { if (cleanup_all->is_pressed()) { - List names; - AnimationPlayerEditor::get_singleton()->get_player()->get_animation_list(&names); - for (const StringName &E : names) { + for (const StringName &E : AnimationPlayerEditor::get_singleton()->get_player()->get_sorted_animation_list()) { _cleanup_animation(AnimationPlayerEditor::get_singleton()->get_player()->get_animation(E)); } } else { diff --git a/editor/animation/animation_tree_editor_plugin.cpp b/editor/animation/animation_tree_editor_plugin.cpp index e0b8e7975f..d1625b8b87 100644 --- a/editor/animation/animation_tree_editor_plugin.cpp +++ b/editor/animation/animation_tree_editor_plugin.cpp @@ -238,26 +238,19 @@ bool AnimationTreeEditor::can_edit(const Ref &p_node) const { return false; } -Vector AnimationTreeEditor::get_animation_list() { +LocalVector AnimationTreeEditor::get_animation_list() { // This can be called off the main thread due to resource preview generation. Quit early in that case. if (!singleton->tree || !Thread::is_main_thread() || !singleton->is_visible()) { // When tree is empty, singleton not in the main thread. - return Vector(); + return LocalVector(); } AnimationTree *tree = singleton->tree; if (!tree) { - return Vector(); + return LocalVector(); } - List anims; - tree->get_animation_list(&anims); - Vector ret; - for (const StringName &E : anims) { - ret.push_back(E); - } - - return ret; + return tree->get_sorted_animation_list(); } AnimationTreeEditor::AnimationTreeEditor() { diff --git a/editor/animation/animation_tree_editor_plugin.h b/editor/animation/animation_tree_editor_plugin.h index 32db6f1a54..644966bf84 100644 --- a/editor/animation/animation_tree_editor_plugin.h +++ b/editor/animation/animation_tree_editor_plugin.h @@ -67,7 +67,7 @@ class AnimationTreeEditor : public EditorDock { void _path_button_pressed(int p_path); void _animation_list_changed(); - static Vector get_animation_list(); + static LocalVector get_animation_list(); protected: void _notification(int p_what); diff --git a/editor/docks/scene_tree_dock.cpp b/editor/docks/scene_tree_dock.cpp index bc100982ff..51677d7b13 100644 --- a/editor/docks/scene_tree_dock.cpp +++ b/editor/docks/scene_tree_dock.cpp @@ -1977,10 +1977,7 @@ bool SceneTreeDock::_has_tracks_to_delete(Node *p_node, List &p_to_delet if (ap) { Node *root = ap->get_node(ap->get_root_node()); if (root && !p_to_delete.find(root)) { - List anims; - ap->get_animation_list(&anims); - - for (const StringName &E : anims) { + for (const StringName &E : ap->get_sorted_animation_list()) { Ref anim = ap->get_animation(E); if (anim.is_null()) { continue; @@ -2242,15 +2239,13 @@ void SceneTreeDock::perform_node_renames(Node *p_base, HashMap } if (!points_to_other_animation_player) { - List anims; - mixer->get_animation_list(&anims); Node *root = mixer->get_node(mixer->get_root_node()); if (root) { HashMap::Iterator found_root_path = p_renames->find(root); NodePath new_root_path = found_root_path ? found_root_path->value : root->get_path(); if (!new_root_path.is_empty()) { // No renaming if root node is deleted. - for (const StringName &E : anims) { + for (const StringName &E : mixer->get_sorted_animation_list()) { Ref anim = mixer->get_animation(E); if (!r_rem_anims->has(anim)) { r_rem_anims->insert(anim, HashSet()); diff --git a/editor/import/3d/post_import_plugin_skeleton_renamer.cpp b/editor/import/3d/post_import_plugin_skeleton_renamer.cpp index 938c924f29..b4fcc9ecaf 100644 --- a/editor/import/3d/post_import_plugin_skeleton_renamer.cpp +++ b/editor/import/3d/post_import_plugin_skeleton_renamer.cpp @@ -95,9 +95,7 @@ void PostImportPluginSkeletonRenamer::_internal_process(InternalImportCategory p TypedArray nodes = p_base_scene->find_children("*", "AnimationPlayer"); while (nodes.size()) { AnimationPlayer *ap = Object::cast_to(nodes.pop_back()); - List anims; - ap->get_animation_list(&anims); - for (const StringName &name : anims) { + for (const StringName &name : ap->get_sorted_animation_list()) { Ref anim = ap->get_animation(name); int len = anim->get_track_count(); for (int i = 0; i < len; i++) { @@ -208,9 +206,7 @@ void PostImportPluginSkeletonRenamer::internal_process(InternalImportCategory p_ TypedArray nodes = p_base_scene->find_children("*", "AnimationPlayer"); while (nodes.size()) { AnimationPlayer *ap = Object::cast_to(nodes.pop_back()); - List anims; - ap->get_animation_list(&anims); - for (const StringName &name : anims) { + for (const StringName &name : ap->get_sorted_animation_list()) { Ref anim = ap->get_animation(name); int track_len = anim->get_track_count(); for (int i = 0; i < track_len; i++) { diff --git a/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp index ae82b3f50a..e0e916658b 100644 --- a/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp +++ b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp @@ -167,9 +167,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory TypedArray nodes = p_base_scene->find_children("*", "AnimationPlayer"); while (nodes.size()) { AnimationPlayer *ap = Object::cast_to(nodes.pop_back()); - List anims; - ap->get_animation_list(&anims); - for (const StringName &name : anims) { + for (const StringName &name : ap->get_sorted_animation_list()) { Ref anim = ap->get_animation(name); int track_len = anim->get_track_count(); for (int i = 0; i < track_len; i++) { @@ -235,9 +233,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory TypedArray nodes = p_base_scene->find_children("*", "AnimationPlayer"); while (nodes.size()) { AnimationPlayer *ap = Object::cast_to(nodes.pop_back()); - List anims; - ap->get_animation_list(&anims); - for (const StringName &name : anims) { + for (const StringName &name : ap->get_sorted_animation_list()) { if (String(name).contains_char('/')) { continue; // Avoid animation library which may be created by importer dynamically. } @@ -407,9 +403,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory TypedArray nodes = p_base_scene->find_children("*", "AnimationPlayer"); while (nodes.size()) { AnimationPlayer *ap = Object::cast_to(nodes.pop_back()); - List anims; - ap->get_animation_list(&anims); - for (const StringName &name : anims) { + for (const StringName &name : ap->get_sorted_animation_list()) { Ref anim = ap->get_animation(name); int track_len = anim->get_track_count(); for (int i = 0; i < track_len; i++) { @@ -579,9 +573,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory String general_skeleton_pathname = UNIQUE_NODE_PREFIX + profile_skeleton->get_name(); while (nodes.size()) { AnimationPlayer *ap = Object::cast_to(nodes.pop_back()); - List anims; - ap->get_animation_list(&anims); - for (const StringName &name : anims) { + for (const StringName &name : ap->get_sorted_animation_list()) { Ref anim = ap->get_animation(name); int track_len = anim->get_track_count(); for (int i = 0; i < track_len; i++) { @@ -715,9 +707,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory while (nodes.size()) { AnimationPlayer *ap = Object::cast_to(nodes.pop_back()); ERR_CONTINUE(!ap); - List anims; - ap->get_animation_list(&anims); - for (const StringName &name : anims) { + for (const StringName &name : ap->get_sorted_animation_list()) { Ref anim = ap->get_animation(name); int track_len = anim->get_track_count(); for (int i = 0; i < track_len; i++) { @@ -846,9 +836,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory TypedArray nodes = p_base_scene->find_children("*", "AnimationPlayer"); while (nodes.size()) { AnimationPlayer *ap = Object::cast_to(nodes.pop_back()); - List anims; - ap->get_animation_list(&anims); - for (const StringName &name : anims) { + for (const StringName &name : ap->get_sorted_animation_list()) { Ref anim = ap->get_animation(name); int track_len = anim->get_track_count(); for (int i = 0; i < track_len; i++) { diff --git a/editor/import/3d/post_import_plugin_skeleton_track_organizer.cpp b/editor/import/3d/post_import_plugin_skeleton_track_organizer.cpp index c6befa13f1..6cc93e7ed7 100644 --- a/editor/import/3d/post_import_plugin_skeleton_track_organizer.cpp +++ b/editor/import/3d/post_import_plugin_skeleton_track_organizer.cpp @@ -69,13 +69,11 @@ void PostImportPluginSkeletonTrackOrganizer::internal_process(InternalImportCate TypedArray nodes = p_base_scene->find_children("*", "AnimationPlayer"); while (nodes.size()) { AnimationPlayer *ap = Object::cast_to(nodes.pop_back()); - List anims; - ap->get_animation_list(&anims); Ref unmapped_al; unmapped_al.instantiate(); - for (const StringName &name : anims) { + for (const StringName &name : ap->get_sorted_animation_list()) { Ref anim = ap->get_animation(name); int track_len = anim->get_track_count(); Vector remove_indices; diff --git a/editor/import/3d/resource_importer_scene.cpp b/editor/import/3d/resource_importer_scene.cpp index 89eefd376c..16bfaa1e49 100644 --- a/editor/import/3d/resource_importer_scene.cpp +++ b/editor/import/3d/resource_importer_scene.cpp @@ -616,7 +616,7 @@ void _populate_scalable_nodes_collection(Node *p_node, ScalableNodeCollection &p } AnimationPlayer *animation_player = Object::cast_to(p_node); if (animation_player) { - List animation_list; + LocalVector animation_list; animation_player->get_animation_list(&animation_list); for (const StringName &E : animation_list) { @@ -702,7 +702,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, HashMap anims; + LocalVector anims; ap->get_animation_list(&anims); for (const StringName &E : anims) { Ref anim = ap->get_animation(E); @@ -1079,7 +1079,7 @@ Node *ResourceImporterScene::_pre_fix_animations(Node *p_node, Node *p_root, con if (Object::cast_to(p_node)) { AnimationPlayer *ap = Object::cast_to(p_node); - List anims; + LocalVector anims; ap->get_animation_list(&anims); AnimationImportTracks import_tracks_mode[TRACK_CHANNEL_MAX] = { @@ -1127,7 +1127,7 @@ Node *ResourceImporterScene::_post_fix_animations(Node *p_node, Node *p_root, co if (Object::cast_to(p_node)) { AnimationPlayer *ap = Object::cast_to(p_node); - List anims; + LocalVector anims; ap->get_animation_list(&anims); if (p_remove_immutable_tracks) { @@ -1504,10 +1504,10 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< for (int node_i = 0; node_i < children.size(); node_i++) { AnimationPlayer *anim_player = cast_to(children[node_i]); ERR_CONTINUE(anim_player == nullptr); - List anim_list; + LocalVector anim_list; anim_player->get_animation_list(&anim_list); if (anim_list.size() == 1) { - selected_animation_name = anim_list.front()->get(); + selected_animation_name = anim_list[0]; } rest_animation = anim_player->get_animation(selected_animation_name); if (rest_animation.is_valid()) { @@ -1520,10 +1520,10 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< if (rest_animation.is_null()) { Ref library(external_object); if (library.is_valid()) { - List anim_list; + LocalVector anim_list; library->get_animation_list(&anim_list); if (anim_list.size() == 1) { - selected_animation_name = String(anim_list.front()->get()); + selected_animation_name = String(anim_list[0]); } rest_animation = library->get_animation(selected_animation_name); } @@ -1873,7 +1873,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< } if (post_importer_plugins.size()) { - List anims; + LocalVector anims; ap->get_animation_list(&anims); for (const StringName &name : anims) { if (p_animation_data.has(name)) { @@ -2098,7 +2098,7 @@ void ResourceImporterScene::_create_slices(AnimationPlayer *ap, Ref a } void ResourceImporterScene::_optimize_animations(AnimationPlayer *anim, float p_max_vel_error, float p_max_ang_error, int p_prc_error) { - List anim_names; + LocalVector anim_names; anim->get_animation_list(&anim_names); for (const StringName &E : anim_names) { Ref a = anim->get_animation(E); @@ -2107,7 +2107,7 @@ void ResourceImporterScene::_optimize_animations(AnimationPlayer *anim, float p_ } void ResourceImporterScene::_compress_animations(AnimationPlayer *anim, int p_page_size_kb) { - List anim_names; + LocalVector anim_names; anim->get_animation_list(&anim_names); for (const StringName &E : anim_names) { Ref a = anim->get_animation(E); @@ -2384,10 +2384,10 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor Ref library(res); String selected_animation_name = p_options["rest_pose/selected_animation"]; if (library.is_valid()) { - List anim_list; + LocalVector anim_list; library->get_animation_list(&anim_list); if (anim_list.size() == 1) { - selected_animation_name = String(anim_list.front()->get()); + selected_animation_name = String(anim_list[0]); } if (library->has_animation(selected_animation_name)) { anim = library->get_animation(selected_animation_name); @@ -2818,7 +2818,7 @@ void ResourceImporterScene::_copy_meta(Object *p_src_object, Object *p_dst_objec } void ResourceImporterScene::_optimize_track_usage(AnimationPlayer *p_player, AnimationImportTracks *p_track_actions) { - List anims; + LocalVector anims; p_player->get_animation_list(&anims); Node *parent = p_player->get_parent(); ERR_FAIL_NULL(parent); @@ -3333,10 +3333,10 @@ Error ResourceImporterScene::import(ResourceUID::ID p_source_id, const String &p for (int i = 0; i < scene->get_child_count(); i++) { AnimationPlayer *ap = Object::cast_to(scene->get_child(i)); if (ap) { - List libs; + LocalVector libs; ap->get_animation_library_list(&libs); if (libs.size()) { - library = ap->get_animation_library(libs.front()->get()); + library = ap->get_animation_library(libs[0]); break; } } diff --git a/editor/import/3d/scene_import_settings.cpp b/editor/import/3d/scene_import_settings.cpp index eff60946b5..3ab686cc05 100644 --- a/editor/import/3d/scene_import_settings.cpp +++ b/editor/import/3d/scene_import_settings.cpp @@ -142,10 +142,10 @@ class SceneImportSettingsData : public Object { hint_string = anim->get_name(); } if (library.is_valid()) { - List anim_names; + LocalVector anim_names; library->get_animation_list(&anim_names); if (anim_names.size() == 1) { - (*settings)["rest_pose/selected_animation"] = String(anim_names.front()->get()); + (*settings)["rest_pose/selected_animation"] = String(anim_names[0]); } for (StringName anim_name : anim_names) { hint_string += "," + anim_name; // Include preceding, as a catch-all. @@ -465,9 +465,7 @@ void SceneImportSettingsDialog::_fill_scene(Node *p_node, TreeItem *p_parent_ite AnimationPlayer *anim_node = Object::cast_to(p_node); if (anim_node) { Vector animation_list; - List animations; - anim_node->get_animation_list(&animations); - for (const StringName &E : animations) { + for (const StringName &E : anim_node->get_sorted_animation_list()) { _fill_animation(scene_tree, anim_node->get_animation(E), E, item); animation_list.append(E); } diff --git a/editor/scene/3d/root_motion_editor_plugin.cpp b/editor/scene/3d/root_motion_editor_plugin.cpp index 8cf69cb5cf..49eda8abc8 100644 --- a/editor/scene/3d/root_motion_editor_plugin.cpp +++ b/editor/scene/3d/root_motion_editor_plugin.cpp @@ -67,10 +67,7 @@ void EditorPropertyRootMotion::_node_assign() { HashSet paths; { - List animations; - mixer->get_animation_list(&animations); - - for (const StringName &E : animations) { + for (const StringName &E : mixer->get_sorted_animation_list()) { Ref anim = mixer->get_animation(E); for (int i = 0; i < anim->get_track_count(); i++) { String pathname = anim->track_get_path(i).get_concatenated_names(); diff --git a/editor/settings/editor_folding.cpp b/editor/settings/editor_folding.cpp index 0d93d6d3be..916d25bc81 100644 --- a/editor/settings/editor_folding.cpp +++ b/editor/settings/editor_folding.cpp @@ -124,7 +124,7 @@ void EditorFolding::_fill_folds(const Node *p_root, const Node *p_node, Array &p const AnimationMixer *anim_mixer = Object::cast_to(p_node); if (anim_mixer) { - List anim_names; + LocalVector anim_names; anim_mixer->get_animation_list(&anim_names); for (const StringName &anim_name : anim_names) { Ref anim = anim_mixer->get_animation(anim_name); diff --git a/misc/extension_api_validation/4.6-stable/GH-116394.txt b/misc/extension_api_validation/4.6-stable/GH-116394.txt new file mode 100644 index 0000000000..1e36d5c223 --- /dev/null +++ b/misc/extension_api_validation/4.6-stable/GH-116394.txt @@ -0,0 +1,6 @@ +GH-116394 +--------- +Validate extension JSON: Error: Field 'classes/Animation/methods/get_length/return_value': meta changed value in new API, from "float" to "double". +Validate extension JSON: Error: Field 'classes/Animation/methods/set_length/arguments/0': meta changed value in new API, from "float" to "double". + +Return type and parameter changed from real_t to double to match internals. No compatibility methods registered because GDExtension FFI already uses double. diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 1bda104af6..28d26add1a 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -3519,9 +3519,7 @@ Error GLTFDocument::_serialize_animations(Ref p_state) { } for (int32_t player_i = 0; player_i < p_state->animation_players.size(); player_i++) { AnimationPlayer *animation_player = p_state->animation_players[player_i]; - List animations; - animation_player->get_animation_list(&animations); - for (const StringName &animation_name : animations) { + for (const StringName &animation_name : animation_player->get_sorted_animation_list()) { _convert_animation(p_state, animation_player, animation_name); } } diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index 86fec0d878..74aa972306 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -43,7 +43,7 @@ StringName AnimationNodeAnimation::get_animation() const { return animation; } -Vector (*AnimationNodeAnimation::get_editable_animation_list)() = nullptr; +LocalVector (*AnimationNodeAnimation::get_editable_animation_list)() = nullptr; void AnimationNodeAnimation::get_parameter_list(List *r_list) const { AnimationNode::get_parameter_list(r_list); @@ -82,9 +82,9 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::get_node_time_info() const { void AnimationNodeAnimation::_validate_property(PropertyInfo &p_property) const { if (Engine::get_singleton()->is_editor_hint() && p_property.name == "animation" && get_editable_animation_list) { - Vector names = get_editable_animation_list(); + LocalVector names = get_editable_animation_list(); String anims; - for (int i = 0; i < names.size(); i++) { + for (uint32_t i = 0; i < names.size(); i++) { if (i > 0) { anims += ","; } diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h index 6830cddf62..a63813c677 100644 --- a/scene/animation/animation_blend_tree.h +++ b/scene/animation/animation_blend_tree.h @@ -59,7 +59,7 @@ public: virtual NodeTimeInfo get_node_time_info() const override; // Wrapper of get_parameter(). - static Vector (*get_editable_animation_list)(); + static LocalVector (*get_editable_animation_list)(); virtual String get_caption() const override; virtual NodeTimeInfo process(const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only = false) override; diff --git a/scene/animation/animation_mixer.cpp b/scene/animation/animation_mixer.cpp index 436dfbc13e..df4d449384 100644 --- a/scene/animation/animation_mixer.cpp +++ b/scene/animation/animation_mixer.cpp @@ -160,33 +160,32 @@ void AnimationMixer::_animation_set_cache_update() { for (const AnimationLibraryData &lib : animation_libraries) { for (const KeyValue> &K : lib.library->animations) { StringName key = lib.name == StringName() ? K.key : StringName(String(lib.name) + "/" + String(K.key)); - if (!animation_set.has(key)) { - AnimationData ad; - ad.animation = K.value; - ad.animation_library = lib.name; - ad.name = key; - ad.last_update = animation_set_update_pass; - animation_set.insert(ad.name, ad); - cache_valid = false; // No need to delete the cache, but it must be updated to add track caches. + + AnimationData *ad = animation_set.getptr(key); + + if (!ad) { + ad = &animation_set.insert(key, AnimationData())->value; // 2) Hash key and lookup again. + ad->animation = K.value; + ad->animation_library = lib.name; + ad->name = key; + ad->last_update = animation_set_update_pass; + cache_valid = false; } else { - AnimationData &ad = animation_set[key]; - if (ad.last_update != animation_set_update_pass) { - // Was not updated, update. If the animation is duplicated, the second one will be ignored. - if (ad.animation != K.value || ad.animation_library != lib.name) { - // Animation changed, update and clear caches. + if (ad->last_update != animation_set_update_pass) { + if (ad->animation != K.value || ad->animation_library != lib.name) { clear_cache_needed = true; - ad.animation = K.value; - ad.animation_library = lib.name; + ad->animation = K.value; + ad->animation_library = lib.name; } - ad.last_update = animation_set_update_pass; + ad->last_update = animation_set_update_pass; } } } } // Check removed. - List to_erase; + LocalVector to_erase; for (const KeyValue &E : animation_set) { if (E.value.last_update != animation_set_update_pass) { // Was not updated, must be erased. @@ -195,9 +194,8 @@ void AnimationMixer::_animation_set_cache_update() { } } - while (to_erase.size()) { - animation_set.erase(to_erase.front()->get()); - to_erase.pop_front(); + for (const StringName &E : to_erase) { + animation_set.erase(E); } if (clear_cache_needed) { @@ -213,7 +211,7 @@ void AnimationMixer::_animation_added(const StringName &p_name, const StringName } void AnimationMixer::_animation_removed(const StringName &p_name, const StringName &p_library) { - StringName name = p_library == StringName() ? p_name : StringName(String(p_library) + "/" + String(p_name)); + const StringName name = p_library == StringName() ? p_name : StringName(String(p_library) + "/" + String(p_name)); if (!animation_set.has(name)) { return; // No need to update because not the one from the library being used. @@ -225,8 +223,8 @@ void AnimationMixer::_animation_removed(const StringName &p_name, const StringNa } void AnimationMixer::_animation_renamed(const StringName &p_name, const StringName &p_to_name, const StringName &p_library) { - StringName from_name = p_library == StringName() ? p_name : StringName(String(p_library) + "/" + String(p_name)); - StringName to_name = p_library == StringName() ? p_to_name : StringName(String(p_library) + "/" + String(p_to_name)); + const StringName from_name = p_library == StringName() ? p_name : StringName(String(p_library) + "/" + String(p_name)); + const StringName to_name = p_library == StringName() ? p_to_name : StringName(String(p_library) + "/" + String(p_to_name)); if (!animation_set.has(from_name)) { return; // No need to update because not the one from the library being used. @@ -260,7 +258,7 @@ TypedArray AnimationMixer::_get_animation_library_list() const { return ret; } -void AnimationMixer::get_animation_library_list(List *p_libraries) const { +void AnimationMixer::get_animation_library_list(LocalVector *p_libraries) const { for (const AnimationLibraryData &lib : animation_libraries) { p_libraries->push_back(lib.name); } @@ -285,13 +283,14 @@ bool AnimationMixer::has_animation_library(const StringName &p_name) const { return false; } -StringName AnimationMixer::find_animation_library(const Ref &p_animation) const { +const StringName &AnimationMixer::find_animation_library(const Ref &p_animation) const { for (const KeyValue &E : animation_set) { if (E.value.animation == p_animation) { return E.value.animation_library; } } - return StringName(); + const static StringName empty = StringName(); + return empty; } Error AnimationMixer::add_animation_library(const StringName &p_name, const Ref &p_animation_library) { @@ -394,21 +393,33 @@ void AnimationMixer::rename_animation_library(const StringName &p_name, const St notify_property_list_changed(); } -void AnimationMixer::get_animation_list(List *p_animations) const { - List anims; +LocalVector AnimationMixer::get_sorted_animation_list() const { + LocalVector animations; + get_animation_list(&animations); + animations.sort_custom(); + return animations; +} + +void AnimationMixer::get_animation_list(LocalVector *p_animations) const { + p_animations->reserve(p_animations->size() + animation_set.size()); for (const KeyValue &E : animation_set) { - anims.push_back(E.key); - } - anims.sort(); - for (const String &E : anims) { - p_animations->push_back(E); + p_animations->push_back(E.key); } } -Ref AnimationMixer::get_animation(const StringName &p_name) const { - ERR_FAIL_COND_V_MSG(!animation_set.has(p_name), Ref(), vformat("Animation not found: \"%s\".", p_name)); - const AnimationData &anim_data = animation_set[p_name]; - return anim_data.animation; +const Ref &AnimationMixer::get_animation(const StringName &p_name) const { + const Ref &animation = get_animation_or_null(p_name); + ERR_FAIL_COND_V_MSG(animation.is_null(), animation, vformat("Animation not found: \"%s\".", p_name)); + return animation; +} + +const Ref &AnimationMixer::get_animation_or_null(const StringName &p_name) const { + const AnimationData *ad = animation_set.getptr(p_name); + if (!ad) { + const static Ref empty = Ref(); + return empty; + } + return ad->animation; } bool AnimationMixer::has_animation(const StringName &p_name) const { @@ -618,7 +629,7 @@ void AnimationMixer::_init_root_motion_cache() { root_motion_scale_accumulator = Vector3(1, 1, 1); } -void AnimationMixer::_create_track_num_to_track_cache_for_animation(Ref &p_animation) { +void AnimationMixer::_create_track_num_to_track_cache_for_animation(const Ref &p_animation) { if (animation_track_num_to_track_cache.has(p_animation)) { // In AnimationMixer::_update_caches, it retrieves all animations via AnimationMixer::get_animation_list // Since multiple AnimationLibraries can share the same Animation, it is possible that the cache is already created. @@ -640,12 +651,15 @@ void AnimationMixer::_create_track_num_to_track_cache_for_animation(Ref sname_list; + LocalVector sname_list; get_animation_list(&sname_list); bool check_path = GLOBAL_GET_CACHED(bool, "animation/warnings/check_invalid_track_paths"); @@ -677,19 +691,21 @@ bool AnimationMixer::_update_caches() { reset_anim = get_animation(SceneStringName(RESET)); } for (const StringName &E : sname_list) { - Ref anim = get_animation(E); + const Ref &anim = get_animation(E); for (int i = 0; i < anim->get_track_count(); i++) { if (!anim->track_is_enabled(i)) { continue; } NodePath path = anim->track_get_path(i); + (void)path.hash(); // Make sure the cache is valid for faster comparison. + Animation::TypeHash thash = anim->track_get_type_hash(i); Animation::TrackType track_src_type = anim->track_get_type(i); Animation::TrackType track_cache_type = Animation::get_cache_type(track_src_type); TrackCache *track = nullptr; - if (track_cache.has(thash)) { - track = track_cache.get(thash); + if (TrackCache **p = track_cache.getptr(thash)) { + track = *p; } // If not valid, delete track. @@ -947,7 +963,7 @@ bool AnimationMixer::_update_caches() { } } - List to_delete; + LocalVector to_delete; for (const KeyValue &K : track_cache) { if (K.value->setup_pass != setup_pass) { @@ -955,11 +971,9 @@ bool AnimationMixer::_update_caches() { } } - while (to_delete.front()) { - Animation::TypeHash thash = to_delete.front()->get(); + for (const Animation::TypeHash &thash : to_delete) { memdelete(track_cache[thash]); track_cache.erase(thash); - to_delete.pop_front(); } track_map.clear(); @@ -976,7 +990,7 @@ bool AnimationMixer::_update_caches() { animation_track_num_to_track_cache.clear(); for (const StringName &E : sname_list) { - Ref anim = get_animation(E); + const Ref &anim = get_animation(E); _create_track_num_to_track_cache_for_animation(anim); } @@ -1143,14 +1157,29 @@ void AnimationMixer::blend_capture(double p_delta) { void AnimationMixer::_blend_calc_total_weight() { for (const AnimationInstance &ai : animation_instances) { - Ref a = ai.animation_data.animation; + const Ref &a = ai.animation_data.animation; real_t weight = ai.playback_info.weight; - const real_t *track_weights_ptr = ai.playback_info.track_weights.ptr(); - int track_weights_count = ai.playback_info.track_weights.size(); - ERR_CONTINUE_EDMSG(!animation_track_num_to_track_cache.has(a), "No animation in cache."); - LocalVector &track_num_to_track_cache = animation_track_num_to_track_cache[a]; - thread_local HashSet processed_hashes; - processed_hashes.clear(); + if (Math::is_zero_approx(weight)) { + continue; + } + Span track_weights = ai.playback_info.track_weights; + + LocalVector *t_cache = animation_track_num_to_track_cache.getptr(a); + ERR_CONTINUE_EDMSG(!t_cache, "No animation in cache."); + LocalVector &track_num_to_track_cache = *t_cache; + + uint64_t pass_id = ++animation_instance_weight_pass_counter; + // Handle wrap (slower but rare). + if (unlikely(pass_id == 0)) { + for (KeyValue &kv : track_cache) { + if (kv.value) { + kv.value->animation_instance_weight_applied_at = 0; + } + } + animation_instance_weight_pass_counter = 1; + pass_id = 1; + } + const LocalVector &tracks = a->get_tracks(); Animation::Track *const *tracks_ptr = tracks.ptr(); int count = tracks.size(); @@ -1159,18 +1188,30 @@ void AnimationMixer::_blend_calc_total_weight() { if (!animation_track->enabled) { continue; } - Animation::TypeHash thash = animation_track->thash; TrackCache *track = track_num_to_track_cache[i]; - if (track == nullptr || processed_hashes.has(thash)) { + if (track == nullptr) { // No path, but avoid error spamming. - // Or, there is the case different track type with same path; These can be distinguished by hash. So don't add the weight doubly. continue; } + + // In some cases (e.g. TrackCacheTransform), + // multiple Animation::Tracks (e.g. TYPE_POSITION_3D, TYPE_ROTATION_3D and TYPE_SCALE_3D) + // can point to the same TrackCache instance. + // So we need to make sure that the weight is added only once per AnimationInstance. + if (track->animation_instance_weight_applied_at == pass_id) { + continue; + } + int blend_idx = track->blend_idx; ERR_CONTINUE(blend_idx < 0 || blend_idx >= track_count); - real_t blend = blend_idx < track_weights_count ? track_weights_ptr[blend_idx] * weight : weight; + real_t blend; + if (!track_weights.is_empty() && blend_idx < static_cast(track_weights.size())) { + blend = track_weights[blend_idx] * weight; + } else { + blend = weight; + } track->total_weight += blend; - processed_hashes.insert(thash); + track->animation_instance_weight_applied_at = pass_id; } } } @@ -1181,7 +1222,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { bool can_call = is_inside_tree() && !Engine::get_singleton()->is_editor_hint(); #endif // TOOLS_ENABLED for (const AnimationInstance &ai : animation_instances) { - Ref a = ai.animation_data.animation; + const Ref &a = ai.animation_data.animation; double time = ai.playback_info.time; double delta = ai.playback_info.delta; double start = ai.playback_info.start; @@ -1190,18 +1231,18 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { Animation::LoopedFlag looped_flag = ai.playback_info.looped_flag; bool is_external_seeking = ai.playback_info.is_external_seeking; real_t weight = ai.playback_info.weight; - const real_t *track_weights_ptr = ai.playback_info.track_weights.ptr(); - int track_weights_count = ai.playback_info.track_weights.size(); bool backward = std::signbit(delta); // This flag is used by the root motion calculates or detecting the end of audio stream. bool seeked_backward = std::signbit(p_delta); #ifndef _3D_DISABLED bool calc_root = !seeked || is_external_seeking; #endif // _3D_DISABLED - ERR_CONTINUE_EDMSG(!animation_track_num_to_track_cache.has(a), "No animation in cache."); - LocalVector &track_num_to_track_cache = animation_track_num_to_track_cache[a]; + LocalVector *t_cache = animation_track_num_to_track_cache.getptr(a); + ERR_CONTINUE_EDMSG(!t_cache, "No animation in cache."); + LocalVector &track_num_to_track_cache = *t_cache; + const LocalVector &tracks = a->get_tracks(); Animation::Track *const *tracks_ptr = tracks.ptr(); - real_t a_length = a->get_length(); + double a_length = a->get_length(); int count = tracks.size(); for (int i = 0; i < count; i++) { const Animation::Track *animation_track = tracks_ptr[i]; @@ -1214,7 +1255,14 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { } int blend_idx = track->blend_idx; ERR_CONTINUE(blend_idx < 0 || blend_idx >= track_count); - real_t blend = blend_idx < track_weights_count ? track_weights_ptr[blend_idx] * weight : weight; + real_t blend; + Span track_weights = ai.playback_info.track_weights; + if (!track_weights.is_empty() && blend_idx < static_cast(track_weights.size())) { + blend = track_weights[blend_idx] * weight; + } else { + blend = weight; + } + if (!deterministic) { // If non-deterministic, do normalization. // It would be better to make this if statement outside the for loop, but come here since too much code... @@ -1626,7 +1674,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { t_obj->set_indexed(t->subpath, value); } } else { - List indices; + LocalVector indices; a->track_get_key_indices_in_range(i, time, delta, start, end, &indices, looped_flag); for (int &F : indices) { t->use_discrete = true; @@ -1659,7 +1707,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { Vector params = a->method_track_get_params(i, idx); _call_object(t->object_id, method, params, callback_mode_method == ANIMATION_CALLBACK_MODE_METHOD_DEFERRED); } else { - List indices; + LocalVector indices; a->track_get_key_indices_in_range(i, time, delta, start, end, &indices, looped_flag); for (int &F : indices) { StringName method = a->method_track_get_name(i, F); @@ -1707,10 +1755,10 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { map.erase(idx); } } else { - List to_play; + LocalVector to_play; a->track_get_key_indices_in_range(i, time, delta, start, end, &to_play, looped_flag); if (to_play.size()) { - idx = to_play.back()->get(); + idx = to_play[to_play.size() - 1]; } } if (idx < 0) { @@ -1790,10 +1838,10 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { } double pos = a->track_get_key_time(i, idx); StringName anim_name = a->animation_track_get_key_animation(i, idx); - if (String(anim_name) == "[stop]" || !player2->has_animation(anim_name)) { + const Ref &anim = player2->get_animation_or_null(anim_name); + if (anim_name == SNAME("[stop]") || anim.is_null()) { continue; } - Ref anim = player2->get_animation(anim_name); double at_anim_pos = start; switch (anim->get_loop_mode()) { case Animation::LOOP_NONE: { @@ -1822,12 +1870,12 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { } } else { // Find stuff to play. - List to_play; + LocalVector to_play; a->track_get_key_indices_in_range(i, time, delta, start, end, &to_play, looped_flag); if (to_play.size()) { - int idx = to_play.back()->get(); + int idx = to_play[to_play.size() - 1]; StringName anim_name = a->animation_track_get_key_animation(i, idx); - if (String(anim_name) == "[stop]" || !player2->has_animation(anim_name)) { + if (anim_name == SNAME("[stop]") || !player2->has_animation(anim_name)) { if (playing_caches.has(t)) { playing_caches.erase(t); player2->stop(); @@ -2033,19 +2081,19 @@ void AnimationMixer::_call_object(ObjectID p_object_id, const StringName &p_meth } } -void AnimationMixer::make_animation_instance(const StringName &p_name, const PlaybackInfo p_playback_info) { - ERR_FAIL_COND(!has_animation(p_name)); - +void AnimationMixer::make_animation_instance(const StringName &p_name, const PlaybackInfo &p_playback_info) { + const Ref &animation = get_animation_or_null(p_name); + ERR_FAIL_COND(animation.is_null()); AnimationData ad; ad.name = p_name; ad.animation = get_animation(p_name); ad.animation_library = find_animation_library(ad.animation); AnimationInstance ai; - ai.animation_data = ad; + ai.animation_data = std::move(ad); ai.playback_info = p_playback_info; - animation_instances.push_back(ai); + animation_instances.push_back(std::move(ai)); } void AnimationMixer::clear_animation_instances() { @@ -2286,9 +2334,9 @@ Ref AnimationMixer::apply_reset(bool p_user_initiated) { void AnimationMixer::capture(const StringName &p_name, double p_duration, Tween::TransitionType p_trans_type, Tween::EaseType p_ease_type) { ERR_FAIL_COND(!active); - ERR_FAIL_COND(!has_animation(p_name)); + const Ref &reference_animation = get_animation_or_null(p_name); + ERR_FAIL_COND(reference_animation.is_null()); ERR_FAIL_COND(p_duration <= 0); - Ref reference_animation = get_animation(p_name); if (!cache_valid) { _update_caches(); // Need to retrieve object id. @@ -2370,13 +2418,11 @@ void AnimationMixer::get_argument_options(const StringName &p_function, int p_id const String pf = p_function; if (p_idx == 0) { if (pf == "get_animation" || pf == "has_animation") { - List al; - get_animation_list(&al); - for (const StringName &name : al) { + for (const StringName &name : get_sorted_animation_list()) { r_options->push_back(String(name).quote()); } } else if (pf == "get_animation_library" || pf == "has_animation_library" || pf == "remove_animation_library" || pf == "rename_animation_library") { - List al; + LocalVector al; get_animation_library_list(&al); for (const StringName &name : al) { r_options->push_back(String(name).quote()); @@ -2495,7 +2541,7 @@ AnimationMixer::AnimationMixer() { AnimationMixer::~AnimationMixer() { } -void AnimatedValuesBackup::set_data(const AHashMap p_data) { +void AnimatedValuesBackup::set_data(const AHashMap &p_data) { clear_data(); for (const KeyValue &E : p_data) { diff --git a/scene/animation/animation_mixer.h b/scene/animation/animation_mixer.h index e7f4838037..814aedc05a 100644 --- a/scene/animation/animation_mixer.h +++ b/scene/animation/animation_mixer.h @@ -76,7 +76,7 @@ public: }; struct AnimationData { - String name; + StringName name; Ref animation; StringName animation_library; uint64_t last_update = 0; @@ -91,7 +91,10 @@ public: bool is_external_seeking = false; Animation::LoopedFlag looped_flag = Animation::LOOPED_FLAG_NONE; real_t weight = 0.0; + // HACK: For now this will still have to be a copy, since we don't have AnimationNodeInstance yet... Vector track_weights; + // TODO: When rebasing https://github.com/godotengine/godot/pull/113444, update this to use LocalVector instead. + // LocalVector *track_weights = nullptr; }; struct AnimationInstance { @@ -105,13 +108,13 @@ protected: AHashMap animation_set; // HashMap TypedArray _get_animation_library_list() const; + // TODO: This needs to be a TypedArray see this PR for rationale https://github.com/godotengine/godot/pull/110767/ Vector _get_animation_list() const { - List animations; - get_animation_list(&animations); Vector ret; - while (animations.size()) { - ret.push_back(animations.front()->get()); - animations.pop_front(); + LocalVector animations = get_sorted_animation_list(); + ret.resize(animations.size()); + for (uint32_t i = 0; i < animations.size(); ++i) { + ret.write[i] = animations[i]; } return ret; } @@ -141,7 +144,6 @@ protected: /* ---- Caches for blending ---- */ bool cache_valid = false; uint64_t setup_pass = 1; - uint64_t process_pass = 1; struct TrackCache { bool root_motion = false; @@ -151,6 +153,7 @@ protected: int blend_idx = -1; ObjectID object_id; real_t total_weight = 0.0; + uint64_t animation_instance_weight_applied_at = 0; TrackCache() = default; TrackCache(const TrackCache &p_other) : @@ -158,7 +161,8 @@ protected: setup_pass(p_other.setup_pass), type(p_other.type), object_id(p_other.object_id), - total_weight(p_other.total_weight) {} + total_weight(p_other.total_weight), + animation_instance_weight_applied_at(p_other.animation_instance_weight_applied_at) {} virtual ~TrackCache() {} }; @@ -315,13 +319,14 @@ protected: void _clear_playing_caches(); void _init_root_motion_cache(); bool _update_caches(); - void _create_track_num_to_track_cache_for_animation(Ref &p_animation); + void _create_track_num_to_track_cache_for_animation(const Ref &p_animation); /* ---- Audio ---- */ AudioServer::PlaybackType playback_type; /* ---- Blending processor ---- */ LocalVector animation_instances; + uint64_t animation_instance_weight_pass_counter = 0; AHashMap track_map; int track_count = 0; bool deterministic = false; @@ -399,16 +404,18 @@ protected: public: /* ---- Data lists ---- */ - void get_animation_library_list(List *p_animations) const; + void get_animation_library_list(LocalVector *p_animations) const; Ref get_animation_library(const StringName &p_name) const; bool has_animation_library(const StringName &p_name) const; - StringName find_animation_library(const Ref &p_animation) const; + const StringName &find_animation_library(const Ref &p_animation) const; Error add_animation_library(const StringName &p_name, const Ref &p_animation_library); void remove_animation_library(const StringName &p_name); void rename_animation_library(const StringName &p_name, const StringName &p_new_name); - void get_animation_list(List *p_animations) const; - Ref get_animation(const StringName &p_name) const; + LocalVector get_sorted_animation_list() const; + void get_animation_list(LocalVector *p_animations) const; + const Ref &get_animation(const StringName &p_name) const; + const Ref &get_animation_or_null(const StringName &p_name) const; bool has_animation(const StringName &p_name) const; StringName find_animation(const Ref &p_animation) const; @@ -451,7 +458,7 @@ public: Vector3 get_root_motion_scale_accumulator() const; /* ---- Blending processor ---- */ - void make_animation_instance(const StringName &p_name, const PlaybackInfo p_playback_info); + void make_animation_instance(const StringName &p_name, const PlaybackInfo &p_playback_info); void clear_animation_instances(); virtual void advance(double p_time); virtual void clear_caches(); // Must be called by hand if an animation was modified after added. @@ -488,7 +495,7 @@ class AnimatedValuesBackup : public RefCounted { AHashMap data; public: - void set_data(const AHashMap p_data); + void set_data(const AHashMap &p_data); AHashMap get_data() const; void clear_data(); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index c87ce8404e..b759138a87 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -287,20 +287,20 @@ void AnimationPlayer::_blend_playback_data(double p_delta, bool p_started) { } return; } - List::Element *> to_erase; - for (List::Element *E = c.blend.front(); E; E = E->next()) { - Blend &b = E->get(); + LocalVector to_erase; + for (uint32_t i = 0; i < c.blend.size(); i++) { + Blend &b = c.blend[i]; b.blend_left = MAX(0, b.blend_left - Math::abs(speed_scale * p_delta) / b.blend_time); if (Animation::is_less_or_equal_approx(b.blend_left, 0)) { - to_erase.push_back(E); + to_erase.push_back(i); b.blend_left = CMP_EPSILON; // May want to play last frame. } // Note: There may be issues if an animation event triggers an animation change while this blend is active, // so it is best to use "deferred" calls instead of "immediate" for animation events that can trigger new animations. _process_playback_data(b.data, p_delta, b.blend_left, false, false, false); } - for (List::Element *&E : to_erase) { - c.blend.erase(E); + for (int i = to_erase.size() - 1; i >= 0; i--) { + c.blend.remove_at(to_erase[i]); } } @@ -351,9 +351,9 @@ void AnimationPlayer::_blend_post_process() { return; } } - String old = playback.assigned; + const StringName old = playback.assigned; play(playback_queue.front()->get()); - String new_name = playback.assigned; + const StringName &new_name = playback.assigned; playback_queue.pop_front(); if (end_notify) { emit_signal(SceneStringName(animation_changed), old, new_name); @@ -432,9 +432,10 @@ void AnimationPlayer::play_section_with_markers(const StringName &p_name, const name = playback.assigned; } - ERR_FAIL_COND_MSG(!animation_set.has(name), vformat("Animation not found: %s.", name)); + AnimationData *ad = animation_set.getptr(name); + ERR_FAIL_NULL_MSG(ad, vformat("Animation not found: %s.", name)); - Ref animation = animation_set[name].animation; + const Ref &animation = ad->animation; ERR_FAIL_COND_MSG(p_start_marker == p_end_marker && p_start_marker, vformat("Start marker and end marker cannot be the same marker: %s.", p_start_marker)); ERR_FAIL_COND_MSG(p_start_marker && !animation->has_marker(p_start_marker), vformat("Marker %s not found in animation: %s.", p_start_marker, name)); @@ -480,12 +481,12 @@ void AnimationPlayer::play_section(const StringName &p_name, double p_start_time } else if (blend_times.has(bk)) { blend_time = blend_times[bk]; } else { - bk.from = "*"; + bk.from = SNAME("*"); if (blend_times.has(bk)) { blend_time = blend_times[bk]; } else { bk.from = c.current.animation_name; - bk.to = "*"; + bk.to = SNAME("*"); if (blend_times.has(bk)) { blend_time = blend_times[bk]; @@ -682,10 +683,11 @@ void AnimationPlayer::seek_internal(double p_time, bool p_update, bool p_update_ playback.current.pos = p_time; if (!playback.current.is_enabled) { if (!playback.assigned.is_empty()) { - ERR_FAIL_COND_MSG(!animation_set.has(playback.assigned), vformat("Animation not found: %s.", playback.assigned)); + AnimationData *ad = animation_set.getptr(playback.assigned); + ERR_FAIL_NULL_MSG(ad, vformat("Animation not found: %s.", playback.assigned)); playback.current.is_enabled = true; playback.current.animation_name = playback.assigned; - playback.current.animation_length = animation_set[playback.assigned].animation->get_length(); + playback.current.animation_length = ad->animation->get_length(); } if (!playback.current.is_enabled) { return; // There is no animation. @@ -826,10 +828,11 @@ void AnimationPlayer::animation_set_next(const StringName &p_animation, const St } StringName AnimationPlayer::animation_get_next(const StringName &p_animation) const { - if (!animation_next_set.has(p_animation)) { + const StringName *next = animation_next_set.getptr(p_animation); + if (!next) { return StringName(); } - return animation_next_set[p_animation]; + return *next; } void AnimationPlayer::set_default_blend_time(double p_default) { @@ -860,8 +863,8 @@ double AnimationPlayer::get_blend_time(const StringName &p_animation1, const Str bk.from = p_animation1; bk.to = p_animation2; - if (blend_times.has(bk)) { - return blend_times[bk]; + if (const double *blend_time = blend_times.getptr(bk)) { + return *blend_time; } else { return 0; } @@ -904,9 +907,7 @@ Tween::EaseType AnimationPlayer::get_auto_capture_ease_type() const { void AnimationPlayer::get_argument_options(const StringName &p_function, int p_idx, List *r_options) const { const String pf = p_function; if (p_idx == 0 && (pf == "play" || pf == "play_backwards" || pf == "has_animation" || pf == "queue")) { - List al; - get_animation_list(&al); - for (const StringName &name : al) { + for (const StringName &name : get_sorted_animation_list()) { r_options->push_back(String(name).quote()); } } @@ -917,7 +918,7 @@ void AnimationPlayer::get_argument_options(const StringName &p_function, int p_i void AnimationPlayer::_animation_removed(const StringName &p_name, const StringName &p_library) { AnimationMixer::_animation_removed(p_name, p_library); - StringName name = p_library == StringName() ? p_name : StringName(String(p_library) + "/" + String(p_name)); + const StringName &name = p_library == StringName() ? p_name : StringName(String(p_library) + "/" + String(p_name)); if (!animation_set.has(name)) { return; // No need to update because not the one from the library being used. @@ -926,17 +927,16 @@ void AnimationPlayer::_animation_removed(const StringName &p_name, const StringN _animation_set_cache_update(); // Erase blends if needed - List to_erase; + LocalVector to_erase; for (const KeyValue &E : blend_times) { - BlendKey bk = E.key; + const BlendKey &bk = E.key; if (bk.from == name || bk.to == name) { to_erase.push_back(bk); } } - while (to_erase.size()) { - blend_times.erase(to_erase.front()->get()); - to_erase.pop_front(); + for (const BlendKey &bk : to_erase) { + blend_times.erase(bk); } } @@ -944,7 +944,7 @@ void AnimationPlayer::_rename_animation(const StringName &p_from_name, const Str AnimationMixer::_rename_animation(p_from_name, p_to_name); // Rename autoplay or blends if needed. - List to_erase; + LocalVector to_erase; HashMap to_insert; for (const KeyValue &E : blend_times) { BlendKey bk = E.key; @@ -965,9 +965,8 @@ void AnimationPlayer::_rename_animation(const StringName &p_from_name, const Str } } - while (to_erase.size()) { - blend_times.erase(to_erase.front()->get()); - to_erase.pop_front(); + for (const BlendKey &bk : to_erase) { + blend_times.erase(bk); } while (to_insert.size()) { diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 68506310f3..7a9e334bbe 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -96,7 +96,7 @@ private: bool seeked = false; bool internal_seeked = false; bool started = false; - List blend; + LocalVector blend; } playback; struct BlendKey { diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index d5cecba78c..d0112c519d 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -142,6 +142,7 @@ void AnimationNode::get_child_nodes(List *r_child_nodes) { void AnimationNode::blend_animation(const StringName &p_animation, AnimationMixer::PlaybackInfo p_playback_info) { ERR_FAIL_NULL(process_state); + // HACK: See PlaybackInfo.track_weights for more info p_playback_info.track_weights = Vector(node_state.track_weights); process_state->tree->make_animation_instance(p_animation, p_playback_info); } @@ -890,7 +891,7 @@ void AnimationTree::_setup_animation_player() { while (animation_libraries.size()) { remove_animation_library(animation_libraries[0].name); } - List list; + LocalVector list; player->get_animation_library_list(&list); for (const StringName &E : list) { Ref lib = player->get_animation_library(E); diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 9572e51e26..2caac91c3b 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -1091,7 +1091,7 @@ void Animation::track_set_interpolation_loop_wrap(int p_track, bool p_enable) { } bool Animation::track_get_interpolation_loop_wrap(int p_track) const { - ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_track, tracks.size(), INTERPOLATION_NEAREST); + ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_track, tracks.size(), false); return tracks[p_track]->loop_wrap; } @@ -1295,8 +1295,8 @@ Error Animation::try_rotation_track_interpolate(int p_track, double p_time, Quat Quaternion Animation::rotation_track_interpolate(int p_track, double p_time, bool p_backward) const { Quaternion ret = Quaternion(0, 0, 0, 1); ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_track, tracks.size(), ret); - bool err = try_rotation_track_interpolate(p_track, p_time, &ret, p_backward); - ERR_FAIL_COND_V_MSG(err, ret, "3D Rotation Track: '" + String(tracks[p_track]->path) + "' is unavailable."); + Error err = try_rotation_track_interpolate(p_track, p_time, &ret, p_backward); + ERR_FAIL_COND_V_MSG(err != OK, ret, "3D Rotation Track: '" + String(tracks[p_track]->path) + "' is unavailable."); return ret; } @@ -2766,7 +2766,7 @@ Animation::UpdateMode Animation::value_track_get_update_mode(int p_track) const } template -void Animation::_track_get_key_indices_in_range(const LocalVector &p_array, double from_time, double to_time, List *p_indices, bool p_is_backward) const { +void Animation::_track_get_key_indices_in_range(const LocalVector &p_array, double from_time, double to_time, LocalVector *r_indices, bool p_is_backward) const { int len = p_array.size(); if (len == 0) { return; @@ -2804,22 +2804,22 @@ void Animation::_track_get_key_indices_in_range(const LocalVector &p_array, d } if (from == to) { - p_indices->push_back(from); + r_indices->push_back(from); return; } if (!p_is_backward) { for (int i = from; i <= to; i++) { - p_indices->push_back(i); + r_indices->push_back(i); } } else { for (int i = to; i >= from; i--) { - p_indices->push_back(i); + r_indices->push_back(i); } } } -void Animation::track_get_key_indices_in_range(int p_track, double p_time, double p_delta, double p_start, double p_end, List *p_indices, Animation::LoopedFlag p_looped_flag) const { +void Animation::track_get_key_indices_in_range(int p_track, double p_time, double p_delta, double p_start, double p_end, LocalVector *r_indices, Animation::LoopedFlag p_looped_flag) const { ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_track, tracks.size()); if (p_delta == 0) { @@ -2878,111 +2878,111 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl case TYPE_POSITION_3D: { const PositionTrack *tt = static_cast(t); if (tt->compressed_track >= 0) { - _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, p_start, to_time, p_indices); + _get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, r_indices); + _get_compressed_key_indices_in_range<3>(tt->compressed_track, p_start, to_time, r_indices); } else { if (!is_backward) { - _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); + _track_get_key_indices_in_range(tt->positions, from_time, anim_end, r_indices, is_backward); + _track_get_key_indices_in_range(tt->positions, anim_start, to_time, r_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); + _track_get_key_indices_in_range(tt->positions, anim_start, to_time, r_indices, is_backward); + _track_get_key_indices_in_range(tt->positions, from_time, anim_end, r_indices, is_backward); } } } break; case TYPE_ROTATION_3D: { const RotationTrack *rt = static_cast(t); if (rt->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, end, p_indices); - _get_compressed_key_indices_in_range<3>(rt->compressed_track, start, to_time, p_indices); + _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, end, r_indices); + _get_compressed_key_indices_in_range<3>(rt->compressed_track, start, to_time, r_indices); } else { if (!is_backward) { - _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); + _track_get_key_indices_in_range(rt->rotations, from_time, anim_end, r_indices, is_backward); + _track_get_key_indices_in_range(rt->rotations, anim_start, to_time, r_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); + _track_get_key_indices_in_range(rt->rotations, anim_start, to_time, r_indices, is_backward); + _track_get_key_indices_in_range(rt->rotations, from_time, anim_end, r_indices, is_backward); } } } break; case TYPE_SCALE_3D: { const ScaleTrack *st = static_cast(t); if (st->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, end, p_indices); - _get_compressed_key_indices_in_range<3>(st->compressed_track, start, to_time, p_indices); + _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, end, r_indices); + _get_compressed_key_indices_in_range<3>(st->compressed_track, start, to_time, r_indices); } else { if (!is_backward) { - _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); + _track_get_key_indices_in_range(st->scales, from_time, anim_end, r_indices, is_backward); + _track_get_key_indices_in_range(st->scales, anim_start, to_time, r_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); + _track_get_key_indices_in_range(st->scales, anim_start, to_time, r_indices, is_backward); + _track_get_key_indices_in_range(st->scales, from_time, anim_end, r_indices, is_backward); } } } break; case TYPE_BLEND_SHAPE: { const BlendShapeTrack *bst = static_cast(t); if (bst->compressed_track >= 0) { - _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, end, p_indices); - _get_compressed_key_indices_in_range<1>(bst->compressed_track, start, to_time, p_indices); + _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, end, r_indices); + _get_compressed_key_indices_in_range<1>(bst->compressed_track, start, to_time, r_indices); } else { if (!is_backward) { - _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); + _track_get_key_indices_in_range(bst->blend_shapes, from_time, anim_end, r_indices, is_backward); + _track_get_key_indices_in_range(bst->blend_shapes, anim_start, to_time, r_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); + _track_get_key_indices_in_range(bst->blend_shapes, anim_start, to_time, r_indices, is_backward); + _track_get_key_indices_in_range(bst->blend_shapes, from_time, anim_end, r_indices, is_backward); } } } break; case TYPE_VALUE: { const ValueTrack *vt = static_cast(t); if (!is_backward) { - _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); + _track_get_key_indices_in_range(vt->values, from_time, anim_end, r_indices, is_backward); + _track_get_key_indices_in_range(vt->values, anim_start, to_time, r_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); + _track_get_key_indices_in_range(vt->values, anim_start, to_time, r_indices, is_backward); + _track_get_key_indices_in_range(vt->values, from_time, anim_end, r_indices, is_backward); } } break; case TYPE_METHOD: { const MethodTrack *mt = static_cast(t); if (!is_backward) { - _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); + _track_get_key_indices_in_range(mt->methods, from_time, anim_end, r_indices, is_backward); + _track_get_key_indices_in_range(mt->methods, anim_start, to_time, r_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); + _track_get_key_indices_in_range(mt->methods, anim_start, to_time, r_indices, is_backward); + _track_get_key_indices_in_range(mt->methods, from_time, anim_end, r_indices, is_backward); } } break; case TYPE_BEZIER: { const BezierTrack *bz = static_cast(t); if (!is_backward) { - _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); + _track_get_key_indices_in_range(bz->values, from_time, anim_end, r_indices, is_backward); + _track_get_key_indices_in_range(bz->values, anim_start, to_time, r_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); + _track_get_key_indices_in_range(bz->values, anim_start, to_time, r_indices, is_backward); + _track_get_key_indices_in_range(bz->values, from_time, anim_end, r_indices, is_backward); } } break; case TYPE_AUDIO: { const AudioTrack *ad = static_cast(t); if (!is_backward) { - _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); + _track_get_key_indices_in_range(ad->values, from_time, anim_end, r_indices, is_backward); + _track_get_key_indices_in_range(ad->values, anim_start, to_time, r_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); + _track_get_key_indices_in_range(ad->values, anim_start, to_time, r_indices, is_backward); + _track_get_key_indices_in_range(ad->values, from_time, anim_end, r_indices, is_backward); } } break; case TYPE_ANIMATION: { const AnimationTrack *an = static_cast(t); if (!is_backward) { - _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); + _track_get_key_indices_in_range(an->values, from_time, anim_end, r_indices, is_backward); + _track_get_key_indices_in_range(an->values, anim_start, to_time, r_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); + _track_get_key_indices_in_range(an->values, anim_start, to_time, r_indices, is_backward); + _track_get_key_indices_in_range(an->values, from_time, anim_end, r_indices, is_backward); } } break; } @@ -2994,12 +2994,12 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl if (!is_backward && Math::is_equal_approx(from_time, start)) { int edge = track_find_key(p_track, start, FIND_MODE_EXACT); if (edge >= 0) { - p_indices->push_back(edge); + r_indices->push_back(edge); } } else if (is_backward && Math::is_equal_approx(to_time, end)) { int edge = track_find_key(p_track, end, FIND_MODE_EXACT); if (edge >= 0) { - p_indices->push_back(edge); + r_indices->push_back(edge); } } } @@ -3018,67 +3018,67 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl case TYPE_POSITION_3D: { const PositionTrack *tt = static_cast(t); if (tt->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(tt->compressed_track, start, from_time, p_indices); - _get_compressed_key_indices_in_range<3>(tt->compressed_track, start, to_time, p_indices); + _get_compressed_key_indices_in_range<3>(tt->compressed_track, start, from_time, r_indices); + _get_compressed_key_indices_in_range<3>(tt->compressed_track, start, to_time, r_indices); } else { - _track_get_key_indices_in_range(tt->positions, start, from_time, p_indices, true); - _track_get_key_indices_in_range(tt->positions, start, to_time, p_indices, false); + _track_get_key_indices_in_range(tt->positions, start, from_time, r_indices, true); + _track_get_key_indices_in_range(tt->positions, start, to_time, r_indices, false); } } break; case TYPE_ROTATION_3D: { const RotationTrack *rt = static_cast(t); if (rt->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(rt->compressed_track, start, from_time, p_indices); - _get_compressed_key_indices_in_range<3>(rt->compressed_track, start, to_time, p_indices); + _get_compressed_key_indices_in_range<3>(rt->compressed_track, start, from_time, r_indices); + _get_compressed_key_indices_in_range<3>(rt->compressed_track, start, to_time, r_indices); } else { - _track_get_key_indices_in_range(rt->rotations, start, from_time, p_indices, true); - _track_get_key_indices_in_range(rt->rotations, start, to_time, p_indices, false); + _track_get_key_indices_in_range(rt->rotations, start, from_time, r_indices, true); + _track_get_key_indices_in_range(rt->rotations, start, to_time, r_indices, false); } } break; case TYPE_SCALE_3D: { const ScaleTrack *st = static_cast(t); if (st->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(st->compressed_track, start, from_time, p_indices); - _get_compressed_key_indices_in_range<3>(st->compressed_track, start, to_time, p_indices); + _get_compressed_key_indices_in_range<3>(st->compressed_track, start, from_time, r_indices); + _get_compressed_key_indices_in_range<3>(st->compressed_track, start, to_time, r_indices); } else { - _track_get_key_indices_in_range(st->scales, start, from_time, p_indices, true); - _track_get_key_indices_in_range(st->scales, start, to_time, p_indices, false); + _track_get_key_indices_in_range(st->scales, start, from_time, r_indices, true); + _track_get_key_indices_in_range(st->scales, start, to_time, r_indices, false); } } break; case TYPE_BLEND_SHAPE: { const BlendShapeTrack *bst = static_cast(t); if (bst->compressed_track >= 0) { - _get_compressed_key_indices_in_range<1>(bst->compressed_track, start, from_time, p_indices); - _get_compressed_key_indices_in_range<1>(bst->compressed_track, start, to_time, p_indices); + _get_compressed_key_indices_in_range<1>(bst->compressed_track, start, from_time, r_indices); + _get_compressed_key_indices_in_range<1>(bst->compressed_track, start, to_time, r_indices); } else { - _track_get_key_indices_in_range(bst->blend_shapes, start, from_time, p_indices, true); - _track_get_key_indices_in_range(bst->blend_shapes, start, to_time, p_indices, false); + _track_get_key_indices_in_range(bst->blend_shapes, start, from_time, r_indices, true); + _track_get_key_indices_in_range(bst->blend_shapes, start, to_time, r_indices, false); } } break; case TYPE_VALUE: { const ValueTrack *vt = static_cast(t); - _track_get_key_indices_in_range(vt->values, start, from_time, p_indices, true); - _track_get_key_indices_in_range(vt->values, start, to_time, p_indices, false); + _track_get_key_indices_in_range(vt->values, start, from_time, r_indices, true); + _track_get_key_indices_in_range(vt->values, start, to_time, r_indices, false); } break; case TYPE_METHOD: { const MethodTrack *mt = static_cast(t); - _track_get_key_indices_in_range(mt->methods, start, from_time, p_indices, true); - _track_get_key_indices_in_range(mt->methods, start, to_time, p_indices, false); + _track_get_key_indices_in_range(mt->methods, start, from_time, r_indices, true); + _track_get_key_indices_in_range(mt->methods, start, to_time, r_indices, false); } break; case TYPE_BEZIER: { const BezierTrack *bz = static_cast(t); - _track_get_key_indices_in_range(bz->values, start, from_time, p_indices, true); - _track_get_key_indices_in_range(bz->values, start, to_time, p_indices, false); + _track_get_key_indices_in_range(bz->values, start, from_time, r_indices, true); + _track_get_key_indices_in_range(bz->values, start, to_time, r_indices, false); } break; case TYPE_AUDIO: { const AudioTrack *ad = static_cast(t); - _track_get_key_indices_in_range(ad->values, start, from_time, p_indices, true); - _track_get_key_indices_in_range(ad->values, start, to_time, p_indices, false); + _track_get_key_indices_in_range(ad->values, start, from_time, r_indices, true); + _track_get_key_indices_in_range(ad->values, start, to_time, r_indices, false); } break; case TYPE_ANIMATION: { const AnimationTrack *an = static_cast(t); - _track_get_key_indices_in_range(an->values, start, from_time, p_indices, true); - _track_get_key_indices_in_range(an->values, start, to_time, p_indices, false); + _track_get_key_indices_in_range(an->values, start, from_time, r_indices, true); + _track_get_key_indices_in_range(an->values, start, to_time, r_indices, false); } break; } return; @@ -3089,67 +3089,67 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl case TYPE_POSITION_3D: { const PositionTrack *tt = static_cast(t); if (tt->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, end, p_indices); - _get_compressed_key_indices_in_range<3>(tt->compressed_track, to_time, end, p_indices); + _get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, end, r_indices); + _get_compressed_key_indices_in_range<3>(tt->compressed_track, to_time, end, r_indices); } else { - _track_get_key_indices_in_range(tt->positions, from_time, end, p_indices, false); - _track_get_key_indices_in_range(tt->positions, to_time, end, p_indices, true); + _track_get_key_indices_in_range(tt->positions, from_time, end, r_indices, false); + _track_get_key_indices_in_range(tt->positions, to_time, end, r_indices, true); } } break; case TYPE_ROTATION_3D: { const RotationTrack *rt = static_cast(t); if (rt->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, end, p_indices); - _get_compressed_key_indices_in_range<3>(rt->compressed_track, to_time, end, p_indices); + _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, end, r_indices); + _get_compressed_key_indices_in_range<3>(rt->compressed_track, to_time, end, r_indices); } else { - _track_get_key_indices_in_range(rt->rotations, from_time, end, p_indices, false); - _track_get_key_indices_in_range(rt->rotations, to_time, end, p_indices, true); + _track_get_key_indices_in_range(rt->rotations, from_time, end, r_indices, false); + _track_get_key_indices_in_range(rt->rotations, to_time, end, r_indices, true); } } break; case TYPE_SCALE_3D: { const ScaleTrack *st = static_cast(t); if (st->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, end, p_indices); - _get_compressed_key_indices_in_range<3>(st->compressed_track, to_time, end, p_indices); + _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, end, r_indices); + _get_compressed_key_indices_in_range<3>(st->compressed_track, to_time, end, r_indices); } else { - _track_get_key_indices_in_range(st->scales, from_time, end, p_indices, false); - _track_get_key_indices_in_range(st->scales, to_time, end, p_indices, true); + _track_get_key_indices_in_range(st->scales, from_time, end, r_indices, false); + _track_get_key_indices_in_range(st->scales, to_time, end, r_indices, true); } } break; case TYPE_BLEND_SHAPE: { const BlendShapeTrack *bst = static_cast(t); if (bst->compressed_track >= 0) { - _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, end, p_indices); - _get_compressed_key_indices_in_range<1>(bst->compressed_track, to_time, end, p_indices); + _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, end, r_indices); + _get_compressed_key_indices_in_range<1>(bst->compressed_track, to_time, end, r_indices); } else { - _track_get_key_indices_in_range(bst->blend_shapes, from_time, end, p_indices, false); - _track_get_key_indices_in_range(bst->blend_shapes, to_time, end, p_indices, true); + _track_get_key_indices_in_range(bst->blend_shapes, from_time, end, r_indices, false); + _track_get_key_indices_in_range(bst->blend_shapes, to_time, end, r_indices, true); } } break; case TYPE_VALUE: { const ValueTrack *vt = static_cast(t); - _track_get_key_indices_in_range(vt->values, from_time, end, p_indices, false); - _track_get_key_indices_in_range(vt->values, to_time, end, p_indices, true); + _track_get_key_indices_in_range(vt->values, from_time, end, r_indices, false); + _track_get_key_indices_in_range(vt->values, to_time, end, r_indices, true); } break; case TYPE_METHOD: { const MethodTrack *mt = static_cast(t); - _track_get_key_indices_in_range(mt->methods, from_time, end, p_indices, false); - _track_get_key_indices_in_range(mt->methods, to_time, end, p_indices, true); + _track_get_key_indices_in_range(mt->methods, from_time, end, r_indices, false); + _track_get_key_indices_in_range(mt->methods, to_time, end, r_indices, true); } break; case TYPE_BEZIER: { const BezierTrack *bz = static_cast(t); - _track_get_key_indices_in_range(bz->values, from_time, end, p_indices, false); - _track_get_key_indices_in_range(bz->values, to_time, end, p_indices, true); + _track_get_key_indices_in_range(bz->values, from_time, end, r_indices, false); + _track_get_key_indices_in_range(bz->values, to_time, end, r_indices, true); } break; case TYPE_AUDIO: { const AudioTrack *ad = static_cast(t); - _track_get_key_indices_in_range(ad->values, from_time, end, p_indices, false); - _track_get_key_indices_in_range(ad->values, to_time, end, p_indices, true); + _track_get_key_indices_in_range(ad->values, from_time, end, r_indices, false); + _track_get_key_indices_in_range(ad->values, to_time, end, r_indices, true); } break; case TYPE_ANIMATION: { const AnimationTrack *an = static_cast(t); - _track_get_key_indices_in_range(an->values, from_time, end, p_indices, false); - _track_get_key_indices_in_range(an->values, to_time, end, p_indices, true); + _track_get_key_indices_in_range(an->values, from_time, end, r_indices, false); + _track_get_key_indices_in_range(an->values, to_time, end, r_indices, true); } break; } return; @@ -3167,54 +3167,54 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl case TYPE_POSITION_3D: { const PositionTrack *tt = static_cast(t); 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, r_indices); } else { - _track_get_key_indices_in_range(tt->positions, from_time, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(tt->positions, from_time, to_time, r_indices, is_backward); } } break; case TYPE_ROTATION_3D: { const RotationTrack *rt = static_cast(t); 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, r_indices); } else { - _track_get_key_indices_in_range(rt->rotations, from_time, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(rt->rotations, from_time, to_time, r_indices, is_backward); } } break; case TYPE_SCALE_3D: { const ScaleTrack *st = static_cast(t); 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, r_indices); } else { - _track_get_key_indices_in_range(st->scales, from_time, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(st->scales, from_time, to_time, r_indices, is_backward); } } break; case TYPE_BLEND_SHAPE: { const BlendShapeTrack *bst = static_cast(t); 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, r_indices); } else { - _track_get_key_indices_in_range(bst->blend_shapes, from_time, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(bst->blend_shapes, from_time, to_time, r_indices, is_backward); } } break; case TYPE_VALUE: { const ValueTrack *vt = static_cast(t); - _track_get_key_indices_in_range(vt->values, from_time, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(vt->values, from_time, to_time, r_indices, is_backward); } break; case TYPE_METHOD: { const MethodTrack *mt = static_cast(t); - _track_get_key_indices_in_range(mt->methods, from_time, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(mt->methods, from_time, to_time, r_indices, is_backward); } break; case TYPE_BEZIER: { const BezierTrack *bz = static_cast(t); - _track_get_key_indices_in_range(bz->values, from_time, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(bz->values, from_time, to_time, r_indices, is_backward); } break; case TYPE_AUDIO: { const AudioTrack *ad = static_cast(t); - _track_get_key_indices_in_range(ad->values, from_time, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(ad->values, from_time, to_time, r_indices, is_backward); } break; case TYPE_ANIMATION: { const AnimationTrack *an = static_cast(t); - _track_get_key_indices_in_range(an->values, from_time, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(an->values, from_time, to_time, r_indices, is_backward); } break; } } @@ -3853,7 +3853,7 @@ StringName Animation::animation_track_get_key_animation(int p_track, int p_key) return at->values[p_key].value; } -void Animation::set_length(real_t p_length) { +void Animation::set_length(double p_length) { if (p_length < ANIM_MIN_LENGTH) { p_length = ANIM_MIN_LENGTH; } @@ -3861,19 +3861,11 @@ void Animation::set_length(real_t p_length) { emit_changed(); } -real_t Animation::get_length() const { - return length; -} - void Animation::set_loop_mode(Animation::LoopMode p_loop_mode) { loop_mode = p_loop_mode; emit_changed(); } -Animation::LoopMode Animation::get_loop_mode() const { - return loop_mode; -} - void Animation::track_set_imported(int p_track, bool p_imported) { ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_track, tracks.size()); tracks[p_track]->imported = p_imported; @@ -5495,7 +5487,7 @@ bool Animation::_fetch_compressed(uint32_t p_compressed_track, double p_time, Ve } template -void Animation::_get_compressed_key_indices_in_range(uint32_t p_compressed_track, double p_time, double p_delta, List *r_indices) const { +void Animation::_get_compressed_key_indices_in_range(uint32_t p_compressed_track, double p_time, double p_delta, LocalVector *r_indices) const { ERR_FAIL_COND(!compression.enabled); ERR_FAIL_UNSIGNED_INDEX(p_compressed_track, compression.bounds.size()); diff --git a/scene/resources/animation.h b/scene/resources/animation.h index a2725f294e..08fa38718e 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -280,7 +280,7 @@ private: _FORCE_INLINE_ T _interpolate(const LocalVector> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok, bool p_backward = false) const; template - _FORCE_INLINE_ void _track_get_key_indices_in_range(const LocalVector &p_array, double from_time, double to_time, List *p_indices, bool p_is_backward) const; + _FORCE_INLINE_ void _track_get_key_indices_in_range(const LocalVector &p_array, double from_time, double to_time, LocalVector *r_indices, bool p_is_backward) const; double length = 1.0; real_t step = DEFAULT_STEP; @@ -368,7 +368,7 @@ private: bool _fetch_compressed_by_index(uint32_t p_compressed_track, int p_index, Vector3i &r_value, double &r_time) const; int _get_compressed_key_count(uint32_t p_compressed_track) const; template - void _get_compressed_key_indices_in_range(uint32_t p_compressed_track, double p_time, double p_delta, List *r_indices) const; + void _get_compressed_key_indices_in_range(uint32_t p_compressed_track, double p_time, double p_delta, LocalVector *r_indices) const; _FORCE_INLINE_ Quaternion _uncompress_quaternion(const Vector3i &p_value) const; _FORCE_INLINE_ Vector3 _uncompress_pos_scale(uint32_t p_compressed_track, const Vector3i &p_value) const; _FORCE_INLINE_ float _uncompress_blend_shape(const Vector3i &p_value) const; @@ -516,7 +516,7 @@ public: void copy_track(int p_track, Ref p_to_animation); - void track_get_key_indices_in_range(int p_track, double p_time, double p_delta, double p_start, double p_end, List *p_indices, Animation::LoopedFlag p_looped_flag = Animation::LOOPED_FLAG_NONE) const; + void track_get_key_indices_in_range(int p_track, double p_time, double p_delta, double p_start, double p_end, LocalVector *r_indices, Animation::LoopedFlag p_looped_flag = Animation::LOOPED_FLAG_NONE) const; void add_marker(const StringName &p_name, double p_time); void remove_marker(const StringName &p_name); @@ -529,11 +529,11 @@ public: Color get_marker_color(const StringName &p_name) const; void set_marker_color(const StringName &p_name, const Color &p_color); - void set_length(real_t p_length); - real_t get_length() const; + void set_length(double p_length); + _FORCE_INLINE_ double get_length() const { return length; } void set_loop_mode(LoopMode p_loop_mode); - LoopMode get_loop_mode() const; + _FORCE_INLINE_ LoopMode get_loop_mode() const { return loop_mode; } void set_step(real_t p_step); real_t get_step() const; diff --git a/scene/resources/animation_library.cpp b/scene/resources/animation_library.cpp index b2370f77e6..fd7cdf78f6 100644 --- a/scene/resources/animation_library.cpp +++ b/scene/resources/animation_library.cpp @@ -96,7 +96,7 @@ Ref AnimationLibrary::get_animation(const StringName &p_name) const { TypedArray AnimationLibrary::_get_animation_list() const { TypedArray ret; - List names; + LocalVector names; get_animation_list(&names); for (const StringName &K : names) { ret.push_back(K); @@ -108,8 +108,8 @@ void AnimationLibrary::_animation_changed(const StringName &p_name) { emit_signal(SceneStringName(animation_changed), p_name); } -void AnimationLibrary::get_animation_list(List *p_animations) const { - List anims; +void AnimationLibrary::get_animation_list(LocalVector *p_animations) const { + LocalVector anims; for (const KeyValue> &E : animations) { anims.push_back(E.key); @@ -148,7 +148,7 @@ Dictionary AnimationLibrary::_get_data() const { void AnimationLibrary::get_argument_options(const StringName &p_function, int p_idx, List *r_options) const { const String pf = p_function; if (p_idx == 0 && (pf == "get_animation" || pf == "has_animation" || pf == "rename_animation" || pf == "remove_animation")) { - List names; + LocalVector names; get_animation_list(&names); for (const StringName &E : names) { r_options->push_back(E.operator String().quote()); diff --git a/scene/resources/animation_library.h b/scene/resources/animation_library.h index 7d78146c44..22896650a3 100644 --- a/scene/resources/animation_library.h +++ b/scene/resources/animation_library.h @@ -60,7 +60,7 @@ public: void rename_animation(const StringName &p_name, const StringName &p_new_name); bool has_animation(const StringName &p_name) const; Ref get_animation(const StringName &p_name) const; - void get_animation_list(List *p_animations) const; + void get_animation_list(LocalVector *p_animations) const; int get_animation_list_size() const; #ifdef TOOLS_ENABLED