123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- using System;
- using System.Collections.Generic;
- namespace Spine
- {
- public class IkConstraint
- {
- public IkConstraint(IkConstraintData data, Skeleton skeleton)
- {
- if (data == null)
- {
- throw new ArgumentNullException("data cannot be null.");
- }
- if (skeleton == null)
- {
- throw new ArgumentNullException("skeleton cannot be null.");
- }
- this.data = data;
- this.mix = data.mix;
- this.bendDirection = data.bendDirection;
- this.bones = new List<Bone>(data.bones.Count);
- foreach (BoneData boneData in data.bones)
- {
- this.bones.Add(skeleton.FindBone(boneData.name));
- }
- this.target = skeleton.FindBone(data.target.name);
- }
- public IkConstraintData Data
- {
- get
- {
- return this.data;
- }
- }
- public List<Bone> Bones
- {
- get
- {
- return this.bones;
- }
- }
- public Bone Target
- {
- get
- {
- return this.target;
- }
- set
- {
- this.target = value;
- }
- }
- public int BendDirection
- {
- get
- {
- return this.bendDirection;
- }
- set
- {
- this.bendDirection = value;
- }
- }
- public float Mix
- {
- get
- {
- return this.mix;
- }
- set
- {
- this.mix = value;
- }
- }
- public void apply()
- {
- Bone bone = this.target;
- List<Bone> list = this.bones;
- int count = list.Count;
- if (count != 1)
- {
- if (count == 2)
- {
- IkConstraint.apply(list[0], list[1], bone.worldX, bone.worldY, this.bendDirection, this.mix);
- }
- }
- else
- {
- IkConstraint.apply(list[0], bone.worldX, bone.worldY, this.mix);
- }
- }
- public override string ToString()
- {
- return this.data.name;
- }
- public static void apply(Bone bone, float targetX, float targetY, float alpha)
- {
- float num = (bone.data.inheritRotation && bone.parent != null) ? bone.parent.worldRotation : 0f;
- float rotation = bone.rotation;
- float num2 = (float)Math.Atan2((double)(targetY - bone.worldY), (double)(targetX - bone.worldX)) * 57.2957764f;
- if (bone.worldFlipX != (bone.worldFlipY != Bone.yDown))
- {
- num2 = -num2;
- }
- num2 -= num;
- bone.rotationIK = rotation + (num2 - rotation) * alpha;
- }
- public static void apply(Bone parent, Bone child, float targetX, float targetY, int bendDirection, float alpha)
- {
- float rotation = child.rotation;
- float rotation2 = parent.rotation;
- if (alpha == 0f)
- {
- child.rotationIK = rotation;
- parent.rotationIK = rotation2;
- return;
- }
- Bone parent2 = parent.parent;
- float x;
- float y;
- if (parent2 != null)
- {
- parent2.worldToLocal(targetX, targetY, out x, out y);
- targetX = (x - parent.x) * parent2.worldScaleX;
- targetY = (y - parent.y) * parent2.worldScaleY;
- }
- else
- {
- targetX -= parent.x;
- targetY -= parent.y;
- }
- if (child.parent == parent)
- {
- x = child.x;
- y = child.y;
- }
- else
- {
- child.parent.localToWorld(child.x, child.y, out x, out y);
- parent.worldToLocal(x, y, out x, out y);
- }
- float num = x * parent.worldScaleX;
- float num2 = y * parent.worldScaleY;
- float num3 = (float)Math.Atan2((double)num2, (double)num);
- float num4 = (float)Math.Sqrt((double)(num * num + num2 * num2));
- float num5 = child.data.length * child.worldScaleX;
- float num6 = 2f * num4 * num5;
- if (num6 < 0.0001f)
- {
- child.rotationIK = rotation + ((float)Math.Atan2((double)targetY, (double)targetX) * 57.2957764f - rotation2 - rotation) * alpha;
- return;
- }
- float num7 = (targetX * targetX + targetY * targetY - num4 * num4 - num5 * num5) / num6;
- if (num7 < -1f)
- {
- num7 = -1f;
- }
- else if (num7 > 1f)
- {
- num7 = 1f;
- }
- float num8 = (float)Math.Acos((double)num7) * (float)bendDirection;
- float num9 = num4 + num5 * num7;
- float num10 = num5 * (float)Math.Sin((double)num8);
- float num11 = (float)Math.Atan2((double)(targetY * num9 - targetX * num10), (double)(targetX * num9 + targetY * num10));
- float num12 = (num11 - num3) * 57.2957764f - rotation2;
- if (num12 > 180f)
- {
- num12 -= 360f;
- }
- else if (num12 < -180f)
- {
- num12 += 360f;
- }
- parent.rotationIK = rotation2 + num12 * alpha;
- num12 = (num8 + num3) * 57.2957764f - rotation;
- if (num12 > 180f)
- {
- num12 -= 360f;
- }
- else if (num12 < -180f)
- {
- num12 += 360f;
- }
- child.rotationIK = rotation + (num12 + parent.worldRotation - child.parent.worldRotation) * alpha;
- }
- private const float radDeg = 57.2957764f;
- internal IkConstraintData data;
- internal List<Bone> bones = new List<Bone>();
- internal Bone target;
- internal int bendDirection;
- internal float mix;
- }
- }
|