Constraint.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /**
  2. * The MIT License (MIT)
  3. *
  4. * Copyright (c) 2012-2017 DragonBones team and other contributors
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  7. * this software and associated documentation files (the "Software"), to deal in
  8. * the Software without restriction, including without limitation the rights to
  9. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10. * the Software, and to permit persons to whom the Software is furnished to do so,
  11. * subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in all
  14. * copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. using System;
  24. namespace DragonBones
  25. {
  26. /// <internal/>
  27. /// <private/>
  28. internal abstract class Constraint : BaseObject
  29. {
  30. protected static readonly Matrix _helpMatrix = new Matrix();
  31. protected static readonly TransformDB _helpTransform = new TransformDB();
  32. protected static readonly Point _helpPoint = new Point();
  33. /// <summary>
  34. /// - For timeline state.
  35. /// </summary>
  36. /// <internal/>
  37. internal ConstraintData _constraintData;
  38. protected Armature _armature;
  39. /// <summary>
  40. /// - For sort bones.
  41. /// </summary>
  42. /// <internal/>
  43. internal Bone _target;
  44. /// <summary>
  45. /// - For sort bones.
  46. /// </summary>
  47. /// <internal/>
  48. internal Bone _root;
  49. internal Bone _bone;
  50. protected override void _OnClear()
  51. {
  52. this._armature = null;
  53. this._target = null; //
  54. this._root = null; //
  55. this._bone = null; //
  56. }
  57. public abstract void Init(ConstraintData constraintData, Armature armature);
  58. public abstract void Update();
  59. public abstract void InvalidUpdate();
  60. public string name
  61. {
  62. get { return this._constraintData.name; }
  63. }
  64. }
  65. /// <internal/>
  66. /// <private/>
  67. internal class IKConstraint : Constraint
  68. {
  69. internal bool _scaleEnabled; // TODO
  70. /// <summary>
  71. /// - For timeline state.
  72. /// </summary>
  73. /// <internal/>
  74. internal bool _bendPositive;
  75. /// <summary>
  76. /// - For timeline state.
  77. /// </summary>
  78. /// <internal/>
  79. internal float _weight;
  80. protected override void _OnClear()
  81. {
  82. base._OnClear();
  83. this._scaleEnabled = false;
  84. this._bendPositive = false;
  85. this._weight = 1.0f;
  86. this._constraintData = null;
  87. }
  88. private void _ComputeA()
  89. {
  90. var ikGlobal = this._target.global;
  91. var global = this._root.global;
  92. var globalTransformMatrix = this._root.globalTransformMatrix;
  93. var radian = (float)Math.Atan2(ikGlobal.y - global.y, ikGlobal.x - global.x);
  94. if (global.scaleX < 0.0f)
  95. {
  96. radian += (float)Math.PI;
  97. }
  98. global.rotation += TransformDB.NormalizeRadian(radian - global.rotation) * this._weight;
  99. global.ToMatrix(globalTransformMatrix);
  100. }
  101. private void _ComputeB()
  102. {
  103. var boneLength = this._bone.boneData.length;
  104. var parent = this._root as Bone;
  105. var ikGlobal = this._target.global;
  106. var parentGlobal = parent.global;
  107. var global = this._bone.global;
  108. var globalTransformMatrix = this._bone.globalTransformMatrix;
  109. var x = globalTransformMatrix.a * boneLength;
  110. var y = globalTransformMatrix.b * boneLength;
  111. var lLL = x * x + y * y;
  112. var lL = (float)Math.Sqrt(lLL);
  113. var dX = global.x - parentGlobal.x;
  114. var dY = global.y - parentGlobal.y;
  115. var lPP = dX * dX + dY * dY;
  116. var lP = (float)Math.Sqrt(lPP);
  117. var rawRadian = global.rotation;
  118. var rawParentRadian = parentGlobal.rotation;
  119. var rawRadianA = (float)Math.Atan2(dY, dX);
  120. dX = ikGlobal.x - parentGlobal.x;
  121. dY = ikGlobal.y - parentGlobal.y;
  122. var lTT = dX * dX + dY * dY;
  123. var lT = (float)Math.Sqrt(lTT);
  124. var radianA = 0.0f;
  125. if (lL + lP <= lT || lT + lL <= lP || lT + lP <= lL)
  126. {
  127. radianA = (float)Math.Atan2(ikGlobal.y - parentGlobal.y, ikGlobal.x - parentGlobal.x);
  128. if (lL + lP <= lT)
  129. {
  130. }
  131. else if (lP < lL)
  132. {
  133. radianA += (float)Math.PI;
  134. }
  135. }
  136. else
  137. {
  138. var h = (lPP - lLL + lTT) / (2.0f * lTT);
  139. var r = (float)Math.Sqrt(lPP - h * h * lTT) / lT;
  140. var hX = parentGlobal.x + (dX * h);
  141. var hY = parentGlobal.y + (dY * h);
  142. var rX = -dY * r;
  143. var rY = dX * r;
  144. var isPPR = false;
  145. var parentParent = parent.parent;
  146. if (parentParent != null)
  147. {
  148. var parentParentMatrix = parentParent.globalTransformMatrix;
  149. isPPR = parentParentMatrix.a * parentParentMatrix.d - parentParentMatrix.b * parentParentMatrix.c < 0.0f;
  150. }
  151. if (isPPR != this._bendPositive)
  152. {
  153. global.x = hX - rX;
  154. global.y = hY - rY;
  155. }
  156. else
  157. {
  158. global.x = hX + rX;
  159. global.y = hY + rY;
  160. }
  161. radianA = (float)Math.Atan2(global.y - parentGlobal.y, global.x - parentGlobal.x);
  162. }
  163. var dR = TransformDB.NormalizeRadian(radianA - rawRadianA);
  164. parentGlobal.rotation = rawParentRadian + dR * this._weight;
  165. parentGlobal.ToMatrix(parent.globalTransformMatrix);
  166. //
  167. var currentRadianA = rawRadianA + dR * this._weight;
  168. global.x = parentGlobal.x + (float)Math.Cos(currentRadianA) * lP;
  169. global.y = parentGlobal.y + (float)Math.Sin(currentRadianA) * lP;
  170. //
  171. var radianB = (float)Math.Atan2(ikGlobal.y - global.y, ikGlobal.x - global.x);
  172. if (global.scaleX < 0.0f)
  173. {
  174. radianB += (float)Math.PI;
  175. }
  176. global.rotation = parentGlobal.rotation + rawRadian - rawParentRadian + TransformDB.NormalizeRadian(radianB - dR - rawRadian) * this._weight;
  177. global.ToMatrix(globalTransformMatrix);
  178. }
  179. public override void Init(ConstraintData constraintData, Armature armature)
  180. {
  181. if (this._constraintData != null)
  182. {
  183. return;
  184. }
  185. this._constraintData = constraintData;
  186. this._armature = armature;
  187. this._target = this._armature.GetBone(this._constraintData.target.name);
  188. this._root = this._armature.GetBone(this._constraintData.root.name);
  189. this._bone = this._constraintData.bone != null ? this._armature.GetBone(this._constraintData.bone.name) : null;
  190. {
  191. var ikConstraintData = this._constraintData as IKConstraintData;
  192. //
  193. this._scaleEnabled = ikConstraintData.scaleEnabled;
  194. this._bendPositive = ikConstraintData.bendPositive;
  195. this._weight = ikConstraintData.weight;
  196. }
  197. this._root._hasConstraint = true;
  198. }
  199. public override void Update()
  200. {
  201. this._root.UpdateByConstraint();
  202. if (this._bone != null)
  203. {
  204. this._bone.UpdateByConstraint();
  205. this._ComputeB();
  206. }
  207. else
  208. {
  209. this._ComputeA();
  210. }
  211. }
  212. public override void InvalidUpdate()
  213. {
  214. this._root.InvalidUpdate();
  215. if (this._bone != null)
  216. {
  217. this._bone.InvalidUpdate();
  218. }
  219. }
  220. }
  221. }