BipedNaming.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. using UnityEngine;
  2. using System.Collections;
  3. using System;
  4. namespace RootMotion {
  5. /// <summary>
  6. /// Class for identifying biped bones based on most common naming conventions.
  7. /// </summary>
  8. public static class BipedNaming {
  9. /// <summary>
  10. /// Type of the bone.
  11. /// </summary>
  12. [System.Serializable]
  13. public enum BoneType {
  14. Unassigned,
  15. Spine,
  16. Head,
  17. Arm,
  18. Leg,
  19. Tail,
  20. Eye
  21. }
  22. /// <summary>
  23. /// Bone side: Left and Right for limbs and Center for spine, head and tail.
  24. /// </summary>
  25. [System.Serializable]
  26. public enum BoneSide {
  27. Center,
  28. Left,
  29. Right
  30. }
  31. // Bone identifications
  32. public static string[]
  33. typeLeft = {" L ", "_L_", "-L-", " l ", "_l_", "-l-", "Left", "left", "CATRigL"},
  34. typeRight = {" R ", "_R_", "-R-", " r ", "_r_", "-r-", "Right", "right", "CATRigR"},
  35. typeSpine = {"Spine", "spine", "Pelvis", "pelvis", "Root", "root", "Torso", "torso", "Body", "body", "Hips", "hips", "Neck", "neck", "Chest", "chest"},
  36. typeHead = {"Head", "head"},
  37. typeArm = {"Arm", "arm", "Hand", "hand", "Wrist", "Wrist", "Elbow", "elbow", "Palm", "palm"},
  38. typeLeg = {"Leg", "leg", "Thigh", "thigh", "Calf", "calf", "Femur", "femur", "Knee", "knee", "Foot", "foot", "Ankle", "ankle", "Hip", "hip"},
  39. typeTail = {"Tail", "tail"},
  40. typeEye = {"Eye", "eye"},
  41. typeExclude = {"Nub", "Dummy", "dummy", "Tip", "IK", "Mesh"},
  42. typeExcludeSpine = {"Head", "head"},
  43. typeExcludeHead = {"Top", "End" },
  44. typeExcludeArm = {"Collar", "collar", "Clavicle", "clavicle", "Finger", "finger", "Index", "index", "Mid", "mid", "Pinky", "pinky", "Ring", "Thumb", "thumb", "Adjust", "adjust", "Twist", "twist"},
  45. typeExcludeLeg = {"Toe", "toe", "Platform", "Adjust", "adjust", "Twist", "twist"},
  46. typeExcludeTail = {},
  47. typeExcludeEye = {"Lid", "lid", "Brow", "brow", "Lash", "lash"},
  48. pelvis = {"Pelvis", "pelvis", "Hip", "hip"},
  49. hand = {"Hand", "hand", "Wrist", "wrist", "Palm", "palm"},
  50. foot = {"Foot", "foot", "Ankle", "ankle"};
  51. #region Public methods
  52. /// <summary>
  53. /// Returns only the bones with the specified BoneType.
  54. /// </summary>
  55. public static Transform[] GetBonesOfType(BoneType boneType, Transform[] bones) {
  56. Transform[] r = new Transform[0];
  57. foreach (Transform bone in bones) {
  58. if (bone != null && GetBoneType(bone.name) == boneType) {
  59. Array.Resize(ref r, r.Length + 1);
  60. r[r.Length - 1] = bone;
  61. }
  62. }
  63. return r;
  64. }
  65. /// <summary>
  66. /// Returns only the bones with the specified BoneSide.
  67. /// </summary>
  68. public static Transform[] GetBonesOfSide(BoneSide boneSide, Transform[] bones) {
  69. Transform[] r = new Transform[0];
  70. foreach (Transform bone in bones) {
  71. if (bone != null && GetBoneSide(bone.name) == boneSide) {
  72. Array.Resize(ref r, r.Length + 1);
  73. r[r.Length - 1] = bone;
  74. }
  75. }
  76. return r;
  77. }
  78. /// <summary>
  79. /// Gets the bones of type and side.
  80. /// </summary>
  81. public static Transform[] GetBonesOfTypeAndSide(BoneType boneType, BoneSide boneSide, Transform[] bones) {
  82. Transform[] bonesOfType = GetBonesOfType(boneType, bones);
  83. return GetBonesOfSide(boneSide, bonesOfType);
  84. }
  85. /// <summary>
  86. /// Gets the bone of type and side. If more than one is found, will return the first in the array.
  87. /// </summary>
  88. public static Transform GetFirstBoneOfTypeAndSide(BoneType boneType, BoneSide boneSide, Transform[] bones) {
  89. Transform[] b = GetBonesOfTypeAndSide(boneType, boneSide, bones);
  90. if (b.Length == 0) return null;
  91. return b[0];
  92. }
  93. /// <summary>
  94. /// Returns only the bones that match all the namings in params string[][] namings
  95. /// </summary>
  96. /// <returns>
  97. /// The matching Transforms
  98. /// </returns>
  99. /// <param name='transforms'>
  100. /// Transforms.
  101. /// </param>
  102. /// <param name='namings'>
  103. /// Namings.
  104. /// </param>
  105. public static Transform GetNamingMatch(Transform[] transforms, params string[][] namings) {
  106. foreach (Transform t in transforms) {
  107. bool match = true;
  108. foreach (string[] naming in namings) {
  109. if (!matchesNaming(t.name, naming)) {
  110. match = false;
  111. break;
  112. }
  113. }
  114. if (match) return t;
  115. }
  116. return null;
  117. }
  118. /// <summary>
  119. /// Gets the type of the bone.
  120. /// </summary>
  121. public static BoneType GetBoneType(string boneName) {
  122. if (isSpine(boneName)) return BoneType.Spine;
  123. if (isHead(boneName)) return BoneType.Head;
  124. if (isArm (boneName)) return BoneType.Arm;
  125. if (isLeg(boneName)) return BoneType.Leg;
  126. if (isTail(boneName)) return BoneType.Tail;
  127. if (isEye(boneName)) return BoneType.Eye;
  128. return BoneType.Unassigned;
  129. }
  130. /// <summary>
  131. /// Gets the bone side.
  132. /// </summary>
  133. public static BoneSide GetBoneSide(string boneName) {
  134. if (isLeft(boneName)) return BoneSide.Left;
  135. if (isRight(boneName)) return BoneSide.Right;
  136. return BoneSide.Center;
  137. }
  138. /// <summary>
  139. /// Returns the bone of type and side with additional naming parameters.
  140. /// </summary>
  141. public static Transform GetBone(Transform[] transforms, BoneType boneType, BoneSide boneSide = BoneSide.Center, params string[][] namings) {
  142. Transform[] bones = GetBonesOfTypeAndSide(boneType, boneSide, transforms);
  143. return GetNamingMatch(bones, namings);
  144. }
  145. #endregion Public methods
  146. private static bool isLeft(string boneName) {
  147. return matchesNaming(boneName, typeLeft) || lastLetter(boneName) == "L" || firstLetter(boneName) == "L";
  148. }
  149. private static bool isRight(string boneName) {
  150. return matchesNaming(boneName, typeRight) || lastLetter(boneName) == "R" || firstLetter(boneName) == "R";
  151. }
  152. private static bool isSpine(string boneName) {
  153. return matchesNaming(boneName, typeSpine) && !excludesNaming(boneName, typeExcludeSpine);
  154. }
  155. private static bool isHead(string boneName) {
  156. return matchesNaming(boneName, typeHead) && !excludesNaming(boneName, typeExcludeHead);
  157. }
  158. private static bool isArm(string boneName) {
  159. return matchesNaming(boneName, typeArm) && !excludesNaming(boneName, typeExcludeArm);
  160. }
  161. private static bool isLeg(string boneName) {
  162. return matchesNaming(boneName, typeLeg) && !excludesNaming(boneName, typeExcludeLeg);
  163. }
  164. private static bool isTail(string boneName) {
  165. return matchesNaming(boneName, typeTail) && !excludesNaming(boneName, typeExcludeTail);
  166. }
  167. private static bool isEye(string boneName) {
  168. return matchesNaming(boneName, typeEye) && !excludesNaming(boneName, typeExcludeEye);
  169. }
  170. private static bool isTypeExclude(string boneName) {
  171. return matchesNaming(boneName, typeExclude);
  172. }
  173. private static bool matchesNaming(string boneName, string[] namingConvention) {
  174. if (excludesNaming(boneName, typeExclude)) return false;
  175. foreach(string n in namingConvention) {
  176. if (boneName.Contains(n)) return true;
  177. }
  178. return false;
  179. }
  180. private static bool excludesNaming(string boneName, string[] namingConvention) {
  181. foreach(string n in namingConvention) {
  182. if (boneName.Contains(n)) return true;
  183. }
  184. return false;
  185. }
  186. private static bool matchesLastLetter(string boneName, string[] namingConvention) {
  187. foreach(string n in namingConvention) {
  188. if (LastLetterIs(boneName, n)) return true;
  189. }
  190. return false;
  191. }
  192. private static bool LastLetterIs(string boneName, string letter) {
  193. string lastLetter = boneName.Substring(boneName.Length - 1, 1);
  194. return lastLetter == letter;
  195. }
  196. private static string firstLetter(string boneName) {
  197. if (boneName.Length > 0) return boneName.Substring(0, 1);
  198. return "";
  199. }
  200. private static string lastLetter(string boneName) {
  201. if (boneName.Length > 0) return boneName.Substring(boneName.Length - 1, 1);
  202. return "";
  203. }
  204. }
  205. }