IkConstraint.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. using System;
  2. using System.Collections.Generic;
  3. namespace Spine
  4. {
  5. public class IkConstraint
  6. {
  7. public IkConstraint(IkConstraintData data, Skeleton skeleton)
  8. {
  9. if (data == null)
  10. {
  11. throw new ArgumentNullException("data cannot be null.");
  12. }
  13. if (skeleton == null)
  14. {
  15. throw new ArgumentNullException("skeleton cannot be null.");
  16. }
  17. this.data = data;
  18. this.mix = data.mix;
  19. this.bendDirection = data.bendDirection;
  20. this.bones = new List<Bone>(data.bones.Count);
  21. foreach (BoneData boneData in data.bones)
  22. {
  23. this.bones.Add(skeleton.FindBone(boneData.name));
  24. }
  25. this.target = skeleton.FindBone(data.target.name);
  26. }
  27. public IkConstraintData Data
  28. {
  29. get
  30. {
  31. return this.data;
  32. }
  33. }
  34. public List<Bone> Bones
  35. {
  36. get
  37. {
  38. return this.bones;
  39. }
  40. }
  41. public Bone Target
  42. {
  43. get
  44. {
  45. return this.target;
  46. }
  47. set
  48. {
  49. this.target = value;
  50. }
  51. }
  52. public int BendDirection
  53. {
  54. get
  55. {
  56. return this.bendDirection;
  57. }
  58. set
  59. {
  60. this.bendDirection = value;
  61. }
  62. }
  63. public float Mix
  64. {
  65. get
  66. {
  67. return this.mix;
  68. }
  69. set
  70. {
  71. this.mix = value;
  72. }
  73. }
  74. public void apply()
  75. {
  76. Bone bone = this.target;
  77. List<Bone> list = this.bones;
  78. int count = list.Count;
  79. if (count != 1)
  80. {
  81. if (count == 2)
  82. {
  83. IkConstraint.apply(list[0], list[1], bone.worldX, bone.worldY, this.bendDirection, this.mix);
  84. }
  85. }
  86. else
  87. {
  88. IkConstraint.apply(list[0], bone.worldX, bone.worldY, this.mix);
  89. }
  90. }
  91. public override string ToString()
  92. {
  93. return this.data.name;
  94. }
  95. public static void apply(Bone bone, float targetX, float targetY, float alpha)
  96. {
  97. float num = (bone.data.inheritRotation && bone.parent != null) ? bone.parent.worldRotation : 0f;
  98. float rotation = bone.rotation;
  99. float num2 = (float)Math.Atan2((double)(targetY - bone.worldY), (double)(targetX - bone.worldX)) * 57.2957764f;
  100. if (bone.worldFlipX != (bone.worldFlipY != Bone.yDown))
  101. {
  102. num2 = -num2;
  103. }
  104. num2 -= num;
  105. bone.rotationIK = rotation + (num2 - rotation) * alpha;
  106. }
  107. public static void apply(Bone parent, Bone child, float targetX, float targetY, int bendDirection, float alpha)
  108. {
  109. float rotation = child.rotation;
  110. float rotation2 = parent.rotation;
  111. if (alpha == 0f)
  112. {
  113. child.rotationIK = rotation;
  114. parent.rotationIK = rotation2;
  115. return;
  116. }
  117. Bone parent2 = parent.parent;
  118. float x;
  119. float y;
  120. if (parent2 != null)
  121. {
  122. parent2.worldToLocal(targetX, targetY, out x, out y);
  123. targetX = (x - parent.x) * parent2.worldScaleX;
  124. targetY = (y - parent.y) * parent2.worldScaleY;
  125. }
  126. else
  127. {
  128. targetX -= parent.x;
  129. targetY -= parent.y;
  130. }
  131. if (child.parent == parent)
  132. {
  133. x = child.x;
  134. y = child.y;
  135. }
  136. else
  137. {
  138. child.parent.localToWorld(child.x, child.y, out x, out y);
  139. parent.worldToLocal(x, y, out x, out y);
  140. }
  141. float num = x * parent.worldScaleX;
  142. float num2 = y * parent.worldScaleY;
  143. float num3 = (float)Math.Atan2((double)num2, (double)num);
  144. float num4 = (float)Math.Sqrt((double)(num * num + num2 * num2));
  145. float num5 = child.data.length * child.worldScaleX;
  146. float num6 = 2f * num4 * num5;
  147. if (num6 < 0.0001f)
  148. {
  149. child.rotationIK = rotation + ((float)Math.Atan2((double)targetY, (double)targetX) * 57.2957764f - rotation2 - rotation) * alpha;
  150. return;
  151. }
  152. float num7 = (targetX * targetX + targetY * targetY - num4 * num4 - num5 * num5) / num6;
  153. if (num7 < -1f)
  154. {
  155. num7 = -1f;
  156. }
  157. else if (num7 > 1f)
  158. {
  159. num7 = 1f;
  160. }
  161. float num8 = (float)Math.Acos((double)num7) * (float)bendDirection;
  162. float num9 = num4 + num5 * num7;
  163. float num10 = num5 * (float)Math.Sin((double)num8);
  164. float num11 = (float)Math.Atan2((double)(targetY * num9 - targetX * num10), (double)(targetX * num9 + targetY * num10));
  165. float num12 = (num11 - num3) * 57.2957764f - rotation2;
  166. if (num12 > 180f)
  167. {
  168. num12 -= 360f;
  169. }
  170. else if (num12 < -180f)
  171. {
  172. num12 += 360f;
  173. }
  174. parent.rotationIK = rotation2 + num12 * alpha;
  175. num12 = (num8 + num3) * 57.2957764f - rotation;
  176. if (num12 > 180f)
  177. {
  178. num12 -= 360f;
  179. }
  180. else if (num12 < -180f)
  181. {
  182. num12 += 360f;
  183. }
  184. child.rotationIK = rotation + (num12 + parent.worldRotation - child.parent.worldRotation) * alpha;
  185. }
  186. private const float radDeg = 57.2957764f;
  187. internal IkConstraintData data;
  188. internal List<Bone> bones = new List<Bone>();
  189. internal Bone target;
  190. internal int bendDirection;
  191. internal float mix;
  192. }
  193. }