1 | /**************************************************************************/ |
2 | /* post_import_plugin_skeleton_track_organizer.cpp */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #include "post_import_plugin_skeleton_track_organizer.h" |
32 | |
33 | #include "editor/import/scene_import_settings.h" |
34 | #include "scene/3d/skeleton_3d.h" |
35 | #include "scene/animation/animation_player.h" |
36 | #include "scene/resources/bone_map.h" |
37 | |
38 | void PostImportPluginSkeletonTrackOrganizer::get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) { |
39 | if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) { |
40 | r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/remove_tracks/except_bone_transform" ), false)); |
41 | r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/remove_tracks/unimportant_positions" ), true)); |
42 | r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/remove_tracks/unmapped_bones" ), false)); |
43 | } |
44 | } |
45 | |
46 | void PostImportPluginSkeletonTrackOrganizer::internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options) { |
47 | if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) { |
48 | // Prepare objects. |
49 | Object *map = p_options["retarget/bone_map" ].get_validated_object(); |
50 | if (!map) { |
51 | return; |
52 | } |
53 | BoneMap *bone_map = Object::cast_to<BoneMap>(map); |
54 | Ref<SkeletonProfile> profile = bone_map->get_profile(); |
55 | if (!profile.is_valid()) { |
56 | return; |
57 | } |
58 | Skeleton3D *src_skeleton = Object::cast_to<Skeleton3D>(p_node); |
59 | if (!src_skeleton) { |
60 | return; |
61 | } |
62 | bool remove_except_bone = bool(p_options["retarget/remove_tracks/except_bone_transform" ]); |
63 | bool remove_positions = bool(p_options["retarget/remove_tracks/unimportant_positions" ]); |
64 | bool remove_unmapped_bones = bool(p_options["retarget/remove_tracks/unmapped_bones" ]); |
65 | |
66 | if (!remove_positions && !remove_unmapped_bones) { |
67 | return; |
68 | } |
69 | |
70 | TypedArray<Node> nodes = p_base_scene->find_children("*" , "AnimationPlayer" ); |
71 | while (nodes.size()) { |
72 | AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back()); |
73 | List<StringName> anims; |
74 | ap->get_animation_list(&anims); |
75 | for (const StringName &name : anims) { |
76 | Ref<Animation> anim = ap->get_animation(name); |
77 | int track_len = anim->get_track_count(); |
78 | Vector<int> remove_indices; |
79 | for (int i = 0; i < track_len; i++) { |
80 | String track_path = String(anim->track_get_path(i).get_concatenated_names()); |
81 | Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path)); |
82 | if (!node) { |
83 | if (remove_except_bone) { |
84 | remove_indices.push_back(i); |
85 | } |
86 | continue; |
87 | } |
88 | Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node); |
89 | if (track_skeleton && track_skeleton == src_skeleton) { |
90 | if (anim->track_get_path(i).get_subname_count() != 1 || !(anim->track_get_type(i) == Animation::TYPE_POSITION_3D || anim->track_get_type(i) == Animation::TYPE_ROTATION_3D || anim->track_get_type(i) == Animation::TYPE_SCALE_3D)) { |
91 | if (remove_except_bone) { |
92 | remove_indices.push_back(i); |
93 | } |
94 | continue; |
95 | } |
96 | StringName bn = anim->track_get_path(i).get_subname(0); |
97 | if (bn) { |
98 | int prof_idx = profile->find_bone(bone_map->find_profile_bone_name(bn)); |
99 | if (remove_unmapped_bones && prof_idx < 0) { |
100 | remove_indices.push_back(i); |
101 | continue; |
102 | } |
103 | if (remove_positions && anim->track_get_type(i) == Animation::TYPE_POSITION_3D && prof_idx >= 0) { |
104 | StringName prof_bn = profile->get_bone_name(prof_idx); |
105 | if (prof_bn == profile->get_root_bone() || prof_bn == profile->get_scale_base_bone()) { |
106 | continue; |
107 | } |
108 | remove_indices.push_back(i); |
109 | } |
110 | } |
111 | } |
112 | if (remove_except_bone) { |
113 | remove_indices.push_back(i); |
114 | } |
115 | } |
116 | |
117 | remove_indices.reverse(); |
118 | for (int i = 0; i < remove_indices.size(); i++) { |
119 | anim->remove_track(remove_indices[i]); |
120 | } |
121 | } |
122 | } |
123 | } |
124 | } |
125 | |
126 | PostImportPluginSkeletonTrackOrganizer::PostImportPluginSkeletonTrackOrganizer() { |
127 | } |
128 | |