No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BoneCache.cs 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. using System;
  2. using UnityEngine;
  3. namespace UnityEditor.U2D.Animation
  4. {
  5. [Serializable]
  6. internal struct Pose
  7. {
  8. public Vector3 position;
  9. public Quaternion rotation;
  10. public Matrix4x4 matrix => Matrix4x4.TRS(position, rotation, Vector3.one);
  11. public static Pose Create(Vector3 p, Quaternion r)
  12. {
  13. var pose = new Pose()
  14. {
  15. position = p,
  16. rotation = r
  17. };
  18. return pose;
  19. }
  20. public override bool Equals(object other)
  21. {
  22. return other is Pose && this == (Pose)other;
  23. }
  24. public override int GetHashCode()
  25. {
  26. return position.GetHashCode() ^ rotation.GetHashCode();
  27. }
  28. public static bool operator==(Pose p1, Pose p2)
  29. {
  30. return p1.position == p2.position && p1.rotation == p2.rotation;
  31. }
  32. public static bool operator!=(Pose p1, Pose p2)
  33. {
  34. return !(p1 == p2);
  35. }
  36. }
  37. [Serializable]
  38. internal struct BonePose
  39. {
  40. public Pose pose;
  41. public float length;
  42. public static BonePose Create(Pose p, float l)
  43. {
  44. var pose = new BonePose()
  45. {
  46. pose = p,
  47. length = l
  48. };
  49. return pose;
  50. }
  51. public override bool Equals(object other)
  52. {
  53. return other is BonePose && this == (BonePose)other;
  54. }
  55. public override int GetHashCode()
  56. {
  57. return pose.GetHashCode() ^ length.GetHashCode();
  58. }
  59. public static bool operator==(BonePose p1, BonePose p2)
  60. {
  61. return p1.pose == p2.pose && Mathf.Abs(p1.length - p2.length) < Mathf.Epsilon;
  62. }
  63. public static bool operator!=(BonePose p1, BonePose p2)
  64. {
  65. return !(p1 == p2);
  66. }
  67. }
  68. internal class BoneCache : TransformCache
  69. {
  70. [SerializeField]
  71. Color32 m_BindPoseColor;
  72. [SerializeField]
  73. Pose m_BindPose;
  74. [SerializeField]
  75. BonePose m_DefaultPose;
  76. [SerializeField]
  77. BoneCache m_ChainedChild;
  78. [SerializeField]
  79. float m_Depth;
  80. [SerializeField]
  81. float m_LocalLength = 1f;
  82. [SerializeField]
  83. bool m_IsVisible = true;
  84. [SerializeField]
  85. string m_Guid;
  86. public bool NotInDefaultPose()
  87. {
  88. return localPosition != m_DefaultPose.pose.position
  89. || localRotation != m_DefaultPose.pose.rotation
  90. || Mathf.Abs(localLength - m_DefaultPose.length) > Mathf.Epsilon;
  91. }
  92. public bool isVisible
  93. {
  94. get => m_IsVisible;
  95. set => m_IsVisible = value;
  96. }
  97. public Color bindPoseColor
  98. {
  99. get => m_BindPoseColor;
  100. set => m_BindPoseColor = value;
  101. }
  102. public virtual BoneCache parentBone => parent as BoneCache;
  103. public SkeletonCache skeleton
  104. {
  105. get
  106. {
  107. var parentSkeleton = parent as SkeletonCache;
  108. if (parentSkeleton != null)
  109. return parentSkeleton;
  110. return parentBone != null ? parentBone.skeleton : null;
  111. }
  112. }
  113. public virtual BoneCache chainedChild
  114. {
  115. get
  116. {
  117. if (m_ChainedChild != null && m_ChainedChild.parentBone == this)
  118. return m_ChainedChild;
  119. return null;
  120. }
  121. set
  122. {
  123. if (m_ChainedChild != value)
  124. {
  125. if (value == null || value.parentBone == this)
  126. {
  127. m_ChainedChild = value;
  128. if(m_ChainedChild != null)
  129. OrientToChainedChild(false);
  130. }
  131. }
  132. }
  133. }
  134. Vector3 localEndPosition => Vector3.right * localLength;
  135. public Vector3 endPosition
  136. {
  137. get => localToWorldMatrix.MultiplyPoint3x4(localEndPosition);
  138. set
  139. {
  140. if (chainedChild != null)
  141. return;
  142. var direction = value - position;
  143. right = direction;
  144. length = direction.magnitude;
  145. }
  146. }
  147. public BonePose localPose
  148. {
  149. get => BonePose.Create(Pose.Create(localPosition, localRotation), localLength);
  150. set
  151. {
  152. localPosition = value.pose.position;
  153. localRotation = value.pose.rotation;
  154. localLength = value.length;
  155. }
  156. }
  157. public BonePose worldPose
  158. {
  159. get => BonePose.Create(Pose.Create(position, rotation), length);
  160. set
  161. {
  162. position = value.pose.position;
  163. rotation = value.pose.rotation;
  164. length = value.length;
  165. }
  166. }
  167. public Pose bindPose => m_BindPose;
  168. public string guid
  169. {
  170. get => m_Guid;
  171. set => m_Guid = value;
  172. }
  173. public float depth
  174. {
  175. get => m_Depth;
  176. set => m_Depth = value;
  177. }
  178. public float localLength
  179. {
  180. get => m_LocalLength;
  181. set => m_LocalLength = Mathf.Max(0f, value);
  182. }
  183. public float length
  184. {
  185. get => localToWorldMatrix.MultiplyVector(localEndPosition).magnitude;
  186. set => m_LocalLength = worldToLocalMatrix.MultiplyVector(right * Mathf.Max(0f, value)).magnitude;
  187. }
  188. internal Pose[] GetChildrenWoldPose()
  189. {
  190. return Array.ConvertAll(children, c => Pose.Create(c.position, c.rotation));
  191. }
  192. internal void SetChildrenWorldPose(Pose[] worldPoses)
  193. {
  194. var childrenArray = children;
  195. Debug.Assert(childrenArray.Length == worldPoses.Length);
  196. for (var i = 0; i < childrenArray.Length; ++i)
  197. {
  198. var child = childrenArray[i];
  199. var pose= worldPoses[i];
  200. child.position = pose.position;
  201. child.rotation = pose.rotation;
  202. }
  203. }
  204. internal override void OnDestroy()
  205. {
  206. base.OnDestroy();
  207. m_ChainedChild = null;
  208. }
  209. public new void SetParent(TransformCache newParent, bool worldPositionStays = true)
  210. {
  211. if (parentBone != null && parentBone.chainedChild == this)
  212. parentBone.chainedChild = null;
  213. base.SetParent(newParent, worldPositionStays);
  214. if (parentBone != null && parentBone.chainedChild == null && (parentBone.endPosition - position).sqrMagnitude < 0.001f)
  215. parentBone.chainedChild = this;
  216. }
  217. public void OrientToChainedChild(bool freezeChildren)
  218. {
  219. Debug.Assert(chainedChild != null);
  220. var childPosition = chainedChild.position;
  221. var childRotation = chainedChild.rotation;
  222. Pose[] childrenWorldPose = null;
  223. if (freezeChildren)
  224. childrenWorldPose = GetChildrenWoldPose();
  225. right = childPosition - position;
  226. if (freezeChildren)
  227. {
  228. SetChildrenWorldPose(childrenWorldPose);
  229. }
  230. else
  231. {
  232. chainedChild.position = childPosition;
  233. chainedChild.rotation = childRotation;
  234. }
  235. length = (childPosition - position).magnitude;
  236. }
  237. public void SetDefaultPose()
  238. {
  239. m_DefaultPose = localPose;
  240. if (IsUnscaled())
  241. m_BindPose = worldPose.pose;
  242. else
  243. throw new Exception("BindPose cannot be set under global scale");
  244. }
  245. public void RestoreDefaultPose()
  246. {
  247. localPose = m_DefaultPose;
  248. }
  249. bool IsUnscaled()
  250. {
  251. var currentTransform = this as TransformCache;
  252. while (currentTransform != null)
  253. {
  254. var scale = currentTransform.localScale;
  255. var isUnscaled = Mathf.Approximately(scale.x, 1f) && Mathf.Approximately(scale.y, 1f) && Mathf.Approximately(scale.z, 1f);
  256. if (!isUnscaled)
  257. return false;
  258. currentTransform = currentTransform.parent;
  259. }
  260. return true;
  261. }
  262. }
  263. }