post_import_plugin_skeleton_renamer.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*************************************************************************/
  2. /* post_import_plugin_skeleton_renamer.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
  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. #include "post_import_plugin_skeleton_renamer.h"
  31. #include "editor/import/scene_import_settings.h"
  32. #include "scene/3d/importer_mesh_instance_3d.h"
  33. #include "scene/3d/skeleton_3d.h"
  34. #include "scene/animation/animation_player.h"
  35. #include "scene/resources/bone_map.h"
  36. void PostImportPluginSkeletonRenamer::get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options) {
  37. if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) {
  38. r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/bone_renamer/rename_bones"), true));
  39. r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/bone_renamer/unique_node/make_unique"), true));
  40. r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::STRING, "retarget/bone_renamer/unique_node/skeleton_name"), "GeneralSkeleton"));
  41. }
  42. }
  43. void PostImportPluginSkeletonRenamer::internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, Ref<Resource> p_resource, const Dictionary &p_options) {
  44. if (p_category == INTERNAL_IMPORT_CATEGORY_SKELETON_3D_NODE) {
  45. // Prepare objects.
  46. Object *map = p_options["retarget/bone_map"].get_validated_object();
  47. if (!map || !bool(p_options["retarget/bone_renamer/rename_bones"])) {
  48. return;
  49. }
  50. BoneMap *bone_map = Object::cast_to<BoneMap>(map);
  51. Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(p_node);
  52. // Rename bones in Skeleton3D.
  53. {
  54. int len = skeleton->get_bone_count();
  55. for (int i = 0; i < len; i++) {
  56. StringName bn = bone_map->find_profile_bone_name(skeleton->get_bone_name(i));
  57. if (bn) {
  58. skeleton->set_bone_name(i, bn);
  59. }
  60. }
  61. }
  62. // Rename bones in Skin.
  63. {
  64. TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D");
  65. while (nodes.size()) {
  66. ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back());
  67. Ref<Skin> skin = mi->get_skin();
  68. if (skin.is_valid()) {
  69. Node *node = mi->get_node(mi->get_skeleton_path());
  70. if (node) {
  71. Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node);
  72. if (mesh_skeleton && node == skeleton) {
  73. int len = skin->get_bind_count();
  74. for (int i = 0; i < len; i++) {
  75. StringName bn = bone_map->find_profile_bone_name(skin->get_bind_name(i));
  76. if (bn) {
  77. skin->set_bind_name(i, bn);
  78. }
  79. }
  80. }
  81. }
  82. }
  83. }
  84. }
  85. // Rename bones in AnimationPlayer.
  86. {
  87. TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
  88. while (nodes.size()) {
  89. AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back());
  90. List<StringName> anims;
  91. ap->get_animation_list(&anims);
  92. for (const StringName &name : anims) {
  93. Ref<Animation> anim = ap->get_animation(name);
  94. int len = anim->get_track_count();
  95. for (int i = 0; i < len; i++) {
  96. 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)) {
  97. continue;
  98. }
  99. String track_path = String(anim->track_get_path(i).get_concatenated_names());
  100. Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
  101. if (node) {
  102. Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
  103. if (track_skeleton && track_skeleton == skeleton) {
  104. StringName bn = bone_map->find_profile_bone_name(anim->track_get_path(i).get_subname(0));
  105. if (bn) {
  106. anim->track_set_path(i, track_path + ":" + bn);
  107. }
  108. }
  109. }
  110. }
  111. }
  112. }
  113. }
  114. // Rename bones in all Nodes by calling method.
  115. {
  116. Vector<Variant> vargs;
  117. vargs.push_back(p_base_scene);
  118. vargs.push_back(skeleton);
  119. vargs.push_back(bone_map);
  120. const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * vargs.size());
  121. const Variant *args = vargs.ptr();
  122. uint32_t argcount = vargs.size();
  123. for (uint32_t i = 0; i < argcount; i++) {
  124. argptrs[i] = &args[i];
  125. }
  126. TypedArray<Node> nodes = p_base_scene->find_children("*");
  127. while (nodes.size()) {
  128. Node *nd = Object::cast_to<Node>(nodes.pop_back());
  129. Callable::CallError ce;
  130. nd->callp("_notify_skeleton_bones_renamed", argptrs, argcount, ce);
  131. }
  132. }
  133. // Make unique skeleton.
  134. if (bool(p_options["retarget/bone_renamer/unique_node/make_unique"])) {
  135. String unique_name = String(p_options["retarget/bone_renamer/unique_node/skeleton_name"]);
  136. ERR_FAIL_COND_MSG(unique_name == String(), "Skeleton unique name cannot be empty.");
  137. TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
  138. while (nodes.size()) {
  139. AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(nodes.pop_back());
  140. List<StringName> anims;
  141. ap->get_animation_list(&anims);
  142. for (const StringName &name : anims) {
  143. Ref<Animation> anim = ap->get_animation(name);
  144. int track_len = anim->get_track_count();
  145. for (int i = 0; i < track_len; i++) {
  146. String track_path = String(anim->track_get_path(i).get_concatenated_names());
  147. Node *orig_node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
  148. Node *node = (ap->get_node(ap->get_root()))->get_node(NodePath(track_path));
  149. while (node) {
  150. Skeleton3D *track_skeleton = Object::cast_to<Skeleton3D>(node);
  151. if (track_skeleton && track_skeleton == skeleton) {
  152. if (node == orig_node) {
  153. if (anim->track_get_path(i).get_subname_count() > 0) {
  154. anim->track_set_path(i, UNIQUE_NODE_PREFIX + unique_name + String(":") + anim->track_get_path(i).get_concatenated_subnames());
  155. } else {
  156. anim->track_set_path(i, UNIQUE_NODE_PREFIX + unique_name);
  157. }
  158. } else {
  159. if (anim->track_get_path(i).get_subname_count() > 0) {
  160. anim->track_set_path(i, UNIQUE_NODE_PREFIX + unique_name + "/" + node->get_path_to(orig_node) + String(":") + anim->track_get_path(i).get_concatenated_subnames());
  161. } else {
  162. anim->track_set_path(i, UNIQUE_NODE_PREFIX + unique_name + "/" + node->get_path_to(orig_node));
  163. }
  164. }
  165. break;
  166. }
  167. node = node->get_parent();
  168. }
  169. }
  170. }
  171. }
  172. skeleton->set_name(unique_name);
  173. skeleton->set_unique_name_in_owner(true);
  174. }
  175. }
  176. }
  177. PostImportPluginSkeletonRenamer::PostImportPluginSkeletonRenamer() {
  178. }