|
@@ -71,12 +71,22 @@ namespace Spine.Unity.Examples {
|
|
|
public int colliderLayer = 0;
|
|
|
[Range(0, 1)]
|
|
|
public float mix = 1;
|
|
|
- public bool oldRagdollBehaviour = true;
|
|
|
+ public bool oldRagdollBehaviour = false;
|
|
|
#endregion
|
|
|
|
|
|
ISkeletonAnimation targetSkeletonComponent;
|
|
|
Skeleton skeleton;
|
|
|
+ struct BoneFlipEntry {
|
|
|
+ public BoneFlipEntry (bool flipX, bool flipY) {
|
|
|
+ this.flipX = flipX;
|
|
|
+ this.flipY = flipY;
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool flipX;
|
|
|
+ public bool flipY;
|
|
|
+ }
|
|
|
Dictionary<Bone, Transform> boneTable = new Dictionary<Bone, Transform>();
|
|
|
+ Dictionary<Bone, BoneFlipEntry> boneFlipTable = new Dictionary<Bone, BoneFlipEntry>();
|
|
|
Transform ragdollRoot;
|
|
|
public Rigidbody2D RootRigidbody { get; private set; }
|
|
|
public Bone StartingBone { get; private set; }
|
|
@@ -141,12 +151,12 @@ namespace Spine.Unity.Examples {
|
|
|
if (b == startingBone) {
|
|
|
ragdollRoot = new GameObject("RagdollRoot").transform;
|
|
|
ragdollRoot.SetParent(transform, false);
|
|
|
- if (b == skeleton.RootBone) { // RagdollRoot is skeleton root.
|
|
|
- ragdollRoot.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
|
|
|
- ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetPropagatedRotation(b));
|
|
|
+ if (b == skeleton.RootBone) { // RagdollRoot is skeleton root's parent, thus the skeleton's scale and position.
|
|
|
+ ragdollRoot.localPosition = new Vector3(skeleton.X, skeleton.Y, 0);
|
|
|
+ ragdollRoot.localRotation = (skeleton.ScaleX < 0) ? Quaternion.Euler(0, 0, 180.0f) : Quaternion.identity;
|
|
|
} else {
|
|
|
ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
|
|
|
- ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetPropagatedRotation(b.Parent));
|
|
|
+ ragdollRoot.localRotation = Quaternion.Euler(0, 0, b.Parent.WorldRotationX - b.Parent.ShearX);
|
|
|
}
|
|
|
parentTransform = ragdollRoot;
|
|
|
rootOffset = t.position - transform.position;
|
|
@@ -307,7 +317,6 @@ namespace Spine.Unity.Examples {
|
|
|
t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX - b.ShearX);
|
|
|
t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 1);
|
|
|
|
|
|
- // MITCH: You left "todo: proper ragdoll branching"
|
|
|
var colliders = AttachBoundingBoxRagdollColliders(b, boneGameObject, skeleton, this.gravityScale);
|
|
|
if (colliders.Count == 0) {
|
|
|
float length = b.Data.Length;
|
|
@@ -331,21 +340,39 @@ namespace Spine.Unity.Examples {
|
|
|
|
|
|
/// <summary>Performed every skeleton animation update to translate Unity Transforms positions into Spine bone transforms.</summary>
|
|
|
void UpdateSpineSkeleton (ISkeletonAnimation animatedSkeleton) {
|
|
|
- bool flipX = skeleton.ScaleX < 0;
|
|
|
- bool flipY = skeleton.ScaleY < 0;
|
|
|
- bool flipXOR = flipX ^ flipY;
|
|
|
- bool flipOR = flipX || flipY;
|
|
|
+ bool parentFlipX;
|
|
|
+ bool parentFlipY;
|
|
|
var startingBone = this.StartingBone;
|
|
|
+ GetStartBoneParentFlipState(out parentFlipX, out parentFlipY);
|
|
|
|
|
|
foreach (var pair in boneTable) {
|
|
|
var b = pair.Key;
|
|
|
var t = pair.Value;
|
|
|
bool isStartingBone = (b == startingBone);
|
|
|
- Transform parentTransform = isStartingBone ? ragdollRoot : boneTable[b.Parent];
|
|
|
+ var parentBone = b.Parent;
|
|
|
+ Transform parentTransform = isStartingBone ? ragdollRoot : boneTable[parentBone];
|
|
|
+ if (!isStartingBone) {
|
|
|
+ var parentBoneFlip = boneFlipTable[parentBone];
|
|
|
+ parentFlipX = parentBoneFlip.flipX;
|
|
|
+ parentFlipY = parentBoneFlip.flipY;
|
|
|
+ }
|
|
|
+ bool flipX = parentFlipX ^ (b.ScaleX < 0);
|
|
|
+ bool flipY = parentFlipY ^ (b.ScaleY < 0);
|
|
|
+
|
|
|
+ BoneFlipEntry boneFlip;
|
|
|
+ boneFlipTable.TryGetValue(b, out boneFlip);
|
|
|
+ boneFlip.flipX = flipX;
|
|
|
+ boneFlip.flipY = flipY;
|
|
|
+ boneFlipTable[b] = boneFlip;
|
|
|
+
|
|
|
+ bool flipXOR = flipX ^ flipY;
|
|
|
+ bool parentFlipXOR = parentFlipX ^ parentFlipY;
|
|
|
+
|
|
|
if (!oldRagdollBehaviour && isStartingBone) {
|
|
|
if (b != skeleton.RootBone) { // RagdollRoot is not skeleton root.
|
|
|
- ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
|
|
|
- ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetPropagatedRotation(b.Parent));
|
|
|
+ ragdollRoot.localPosition = new Vector3(parentBone.WorldX, parentBone.WorldY, 0);
|
|
|
+ ragdollRoot.localRotation = Quaternion.Euler(0, 0, parentBone.WorldRotationX - parentBone.ShearX);
|
|
|
+ ragdollRoot.localScale = new Vector3(parentBone.WorldScaleX, parentBone.WorldScaleY, 1);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -356,25 +383,26 @@ namespace Spine.Unity.Examples {
|
|
|
parentSpaceHelper.rotation = parentTransformWorldRotation;
|
|
|
parentSpaceHelper.localScale = parentTransform.lossyScale;
|
|
|
|
|
|
+ if (oldRagdollBehaviour) {
|
|
|
+ if (isStartingBone && b != skeleton.RootBone) {
|
|
|
+ Vector3 localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
|
|
|
+ parentSpaceHelper.position = ragdollRoot.TransformPoint(localPosition);
|
|
|
+ parentSpaceHelper.localRotation = Quaternion.Euler(0, 0, parentBone.WorldRotationX - parentBone.ShearX);
|
|
|
+ parentSpaceHelper.localScale = new Vector3(parentBone.WorldScaleX, parentBone.WorldScaleY, 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
Vector3 boneWorldPosition = t.position;
|
|
|
Vector3 right = parentSpaceHelper.InverseTransformDirection(t.right);
|
|
|
|
|
|
Vector3 boneLocalPosition = parentSpaceHelper.InverseTransformPoint(boneWorldPosition);
|
|
|
float boneLocalRotation = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
|
|
|
- if (flipOR) {
|
|
|
- if (isStartingBone) {
|
|
|
- if (flipX) boneLocalPosition.x *= -1f;
|
|
|
- if (flipY) boneLocalPosition.y *= -1f;
|
|
|
|
|
|
- boneLocalRotation = boneLocalRotation * (flipXOR ? -1f : 1f);
|
|
|
- if (flipX) boneLocalRotation += 180;
|
|
|
- } else {
|
|
|
- if (flipXOR) {
|
|
|
- boneLocalRotation *= -1f;
|
|
|
- boneLocalPosition.y *= -1f; // wtf??
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ if (flipXOR) boneLocalPosition.y *= -1f;
|
|
|
+ if (parentFlipXOR != flipXOR) boneLocalPosition.y *= -1f;
|
|
|
+
|
|
|
+ if (parentFlipXOR) boneLocalRotation *= -1f;
|
|
|
+ if (parentFlipX != flipX) boneLocalRotation += 180;
|
|
|
|
|
|
b.X = Mathf.Lerp(b.X, boneLocalPosition.x, mix);
|
|
|
b.Y = Mathf.Lerp(b.Y, boneLocalPosition.y, mix);
|
|
@@ -383,6 +411,17 @@ namespace Spine.Unity.Examples {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ void GetStartBoneParentFlipState (out bool parentFlipX, out bool parentFlipY) {
|
|
|
+ parentFlipX = skeleton.ScaleX < 0;
|
|
|
+ parentFlipY = skeleton.ScaleY < 0;
|
|
|
+ var parent = this.StartingBone == null ? null : this.StartingBone.Parent;
|
|
|
+ while (parent != null) {
|
|
|
+ parentFlipX ^= parent.ScaleX < 0;
|
|
|
+ parentFlipY ^= parent.ScaleY < 0;
|
|
|
+ parent = parent.Parent;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
static List<Collider2D> AttachBoundingBoxRagdollColliders (Bone b, GameObject go, Skeleton skeleton, float gravityScale) {
|
|
|
const string AttachmentNameMarker = "ragdoll";
|
|
|
var colliders = new List<Collider2D>();
|
|
@@ -414,16 +453,6 @@ namespace Spine.Unity.Examples {
|
|
|
return colliders;
|
|
|
}
|
|
|
|
|
|
- static float GetPropagatedRotation (Bone b) {
|
|
|
- Bone parent = b.Parent;
|
|
|
- float a = b.AppliedRotation;
|
|
|
- while (parent != null) {
|
|
|
- a += parent.AppliedRotation;
|
|
|
- parent = parent.Parent;
|
|
|
- }
|
|
|
- return a;
|
|
|
- }
|
|
|
-
|
|
|
static Vector3 FlipScale (bool flipX, bool flipY) {
|
|
|
return new Vector3(flipX ? -1f : 1f, flipY ? -1f : 1f, 1f);
|
|
|
}
|