BoneCache.cs 8.7 KB

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