From 216441ac4a4e1517ce7bfdbabc4de6f40308fdf1 Mon Sep 17 00:00:00 2001 From: pharan Date: Thu, 29 Jun 2017 17:14:27 +0800 Subject: [PATCH] [unity] Cleanup line endings. --- .../Editor/SpineAttributeDrawers.cs | 3 +- .../Modules/Ragdoll/SkeletonRagdoll2D.cs | 820 +++++++++--------- .../Assets/spine-unity/SkeletonAnimation.cs | 2 +- .../Assets/spine-unity/SkeletonRenderer.cs | 2 +- .../SkeletonUtility/SkeletonUtility.cs | 8 +- 5 files changed, 418 insertions(+), 417 deletions(-) diff --git a/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs b/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs index 82bb77b14..505a31ae0 100644 --- a/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs +++ b/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs @@ -99,8 +99,9 @@ namespace Spine.Unity.Editor { skeletonDataAsset = property.serializedObject.targetObject as SkeletonDataAsset; if (skeletonDataAsset == null) return; } - + position = EditorGUI.PrefixLabel(position, label); + var image = Icon; var propertyStringValue = (property.hasMultipleDifferentValues) ? SpineInspectorUtility.EmDash : property.stringValue; if (GUI.Button(position, string.IsNullOrEmpty(propertyStringValue) ? NoneLabel(image) : SpineInspectorUtility.TempContent(propertyStringValue, image), EditorStyles.popup)) diff --git a/spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs b/spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs index 3558ee1d7..0e9c0aba2 100644 --- a/spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs +++ b/spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs @@ -1,410 +1,410 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF - * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -// Contributed by: Mitch Thompson - -using UnityEngine; -using System.Collections; -using System.Collections.Generic; - -namespace Spine.Unity.Modules { - [RequireComponent(typeof(SkeletonRenderer))] - public class SkeletonRagdoll2D : MonoBehaviour { - static Transform parentSpaceHelper; - - #region Inspector - [Header("Hierarchy")] - [SpineBone] - public string startingBoneName = ""; - [SpineBone] - public List stopBoneNames = new List(); - - [Header("Parameters")] - public bool applyOnStart; - [Tooltip("Warning! You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")] - public bool disableIK = true; - public bool disableOtherConstraints = false; - [Space] - [Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")] - public bool pinStartBone; - public float gravityScale = 1; - [Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")] - public float thickness = 0.125f; - [Tooltip("Default rotational limit value. Min is negative this value, Max is this value.")] - public float rotationLimit = 20; - public float rootMass = 20; - [Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")] - [Range(0.01f, 1f)] - public float massFalloffFactor = 0.4f; - [Tooltip("The layer assigned to all of the rigidbody parts.")] - [SkeletonRagdoll.LayerField] - public int colliderLayer = 0; - [Range(0, 1)] - public float mix = 1; - #endregion - - ISkeletonAnimation targetSkeletonComponent; - Skeleton skeleton; - Dictionary boneTable = new Dictionary(); - Transform ragdollRoot; - public Rigidbody2D RootRigidbody { get; private set; } - public Bone StartingBone { get; private set; } - Vector2 rootOffset; - public Vector3 RootOffset { get { return this.rootOffset; } } - bool isActive; - public bool IsActive { get { return this.isActive; } } - - IEnumerator Start () { - if (parentSpaceHelper == null) { - parentSpaceHelper = (new GameObject("Parent Space Helper")).transform; - } - - targetSkeletonComponent = GetComponent() as ISkeletonAnimation; - if (targetSkeletonComponent == null) Debug.LogError("Attached Spine component does not implement ISkeletonAnimation. This script is not compatible."); - skeleton = targetSkeletonComponent.Skeleton; - - if (applyOnStart) { - yield return null; - Apply(); - } - } - - #region API - public Rigidbody2D[] RigidbodyArray { - get { - if (!isActive) - return new Rigidbody2D[0]; - - var rigidBodies = new Rigidbody2D[boneTable.Count]; - int i = 0; - foreach (Transform t in boneTable.Values) { - rigidBodies[i] = t.GetComponent(); - i++; - } - - return rigidBodies; - } - } - - public Vector3 EstimatedSkeletonPosition { - get { return this.RootRigidbody.position - rootOffset; } - } - - /// Instantiates the ragdoll simulation and applies its transforms to the skeleton. - public void Apply () { - isActive = true; - mix = 1; - - Bone startingBone = this.StartingBone = skeleton.FindBone(startingBoneName); - RecursivelyCreateBoneProxies(startingBone); - - RootRigidbody = boneTable[startingBone].GetComponent(); - RootRigidbody.isKinematic = pinStartBone; - RootRigidbody.mass = rootMass; - var boneColliders = new List(); - foreach (var pair in boneTable) { - var b = pair.Key; - var t = pair.Value; - Transform parentTransform; - boneColliders.Add(t.GetComponent()); - 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)); - } else { - ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0); - ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetPropagatedRotation(b.Parent)); - } - parentTransform = ragdollRoot; - rootOffset = t.position - transform.position; - } else { - parentTransform = boneTable[b.Parent]; - } - - // Add joint and attach to parent. - var rbParent = parentTransform.GetComponent(); - if (rbParent != null) { - var joint = t.gameObject.AddComponent(); - joint.connectedBody = rbParent; - Vector3 localPos = parentTransform.InverseTransformPoint(t.position); - joint.connectedAnchor = localPos; - - joint.GetComponent().mass = joint.connectedBody.mass * massFalloffFactor; - joint.limits = new JointAngleLimits2D { - min = -rotationLimit, - max = rotationLimit - }; - joint.useLimits = true; - } - } - - // Ignore collisions among bones. - for (int x = 0; x < boneColliders.Count; x++) { - for (int y = 0; y < boneColliders.Count; y++) { - if (x == y) continue; - Physics2D.IgnoreCollision(boneColliders[x], boneColliders[y]); - } - } - - // Destroy existing override-mode SkeletonUtility bones. - var utilityBones = GetComponentsInChildren(); - if (utilityBones.Length > 0) { - var destroyedUtilityBoneNames = new List(); - foreach (var ub in utilityBones) { - if (ub.mode == SkeletonUtilityBone.Mode.Override) { - destroyedUtilityBoneNames.Add(ub.gameObject.name); - Destroy(ub.gameObject); - } - } - if (destroyedUtilityBoneNames.Count > 0) { - string msg = "Destroyed Utility Bones: "; - for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) { - msg += destroyedUtilityBoneNames[i]; - if (i != destroyedUtilityBoneNames.Count - 1) { - msg += ","; - } - } - Debug.LogWarning(msg); - } - } - - // Disable skeleton constraints. - if (disableIK) { - var ikConstraints = skeleton.IkConstraints; - for (int i = 0, n = ikConstraints.Count; i < n; i++) - ikConstraints.Items[i].mix = 0; - } - - if (disableOtherConstraints) { - var transformConstraints = skeleton.transformConstraints; - for (int i = 0, n = transformConstraints.Count; i < n; i++) { - transformConstraints.Items[i].rotateMix = 0; - transformConstraints.Items[i].scaleMix = 0; - transformConstraints.Items[i].shearMix = 0; - transformConstraints.Items[i].translateMix = 0; - } - - var pathConstraints = skeleton.pathConstraints; - for (int i = 0, n = pathConstraints.Count; i < n; i++) { - pathConstraints.Items[i].rotateMix = 0; - pathConstraints.Items[i].translateMix = 0; - } - } - - targetSkeletonComponent.UpdateWorld += UpdateSpineSkeleton; - } - - /// Transitions the mix value from the current value to a target value. - public Coroutine SmoothMix (float target, float duration) { - return StartCoroutine(SmoothMixCoroutine(target, duration)); - } - - IEnumerator SmoothMixCoroutine (float target, float duration) { - float startTime = Time.time; - float startMix = mix; - while (mix > 0) { - skeleton.SetBonesToSetupPose(); - mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration); - yield return null; - } - } - - /// Set the transform world position while preserving the ragdoll parts world position. - public void SetSkeletonPosition (Vector3 worldPosition) { - if (!isActive) { - Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!"); - return; - } - - Vector3 offset = worldPosition - transform.position; - transform.position = worldPosition; - foreach (Transform t in boneTable.Values) - t.position -= offset; - - UpdateSpineSkeleton(null); - skeleton.UpdateWorldTransform(); - } - - /// Removes the ragdoll instance and effect from the animated skeleton. - public void Remove () { - isActive = false; - foreach (var t in boneTable.Values) - Destroy(t.gameObject); - - Destroy(ragdollRoot.gameObject); - boneTable.Clear(); - targetSkeletonComponent.UpdateWorld -= UpdateSpineSkeleton; - } - - public Rigidbody2D GetRigidbody (string boneName) { - var bone = skeleton.FindBone(boneName); - return (bone != null && boneTable.ContainsKey(bone)) ? boneTable[bone].GetComponent() : null; - } - #endregion - - /// Generates the ragdoll simulation's Transform and joint setup. - void RecursivelyCreateBoneProxies (Bone b) { - string boneName = b.data.name; - if (stopBoneNames.Contains(boneName)) - return; - - var boneGameObject = new GameObject(boneName); - boneGameObject.layer = this.colliderLayer; - Transform t = boneGameObject.transform; - boneTable.Add(b, t); - - t.parent = transform; - t.localPosition = new Vector3(b.WorldX, b.WorldY, 0); - t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX - b.shearX); - t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 0); - - // MITCH: You left "todo: proper ragdoll branching" - var colliders = AttachBoundingBoxRagdollColliders(b, boneGameObject, skeleton, this.gravityScale); - if (colliders.Count == 0) { - float length = b.data.length; - if (length == 0) { - var circle = boneGameObject.AddComponent(); - circle.radius = thickness * 0.5f; - } else { - var box = boneGameObject.AddComponent(); - box.size = new Vector2(length, thickness); - box.offset = new Vector2(length * 0.5f, 0); // box.center in UNITY_4 - } - } - - var rb = boneGameObject.GetComponent(); - if (rb == null) rb = boneGameObject.AddComponent(); - rb.gravityScale = this.gravityScale; - - foreach (Bone child in b.Children) - RecursivelyCreateBoneProxies(child); - } - - /// Performed every skeleton animation update to translate Unity Transforms positions into Spine bone transforms. - void UpdateSpineSkeleton (ISkeletonAnimation animatedSkeleton) { - bool flipX = skeleton.flipX; - bool flipY = skeleton.flipY; - bool flipXOR = flipX ^ flipY; - bool flipOR = flipX || flipY; - var startingBone = this.StartingBone; - - foreach (var pair in boneTable) { - var b = pair.Key; - var t = pair.Value; - bool isStartingBone = (b == startingBone); - Transform parentTransform = isStartingBone ? ragdollRoot : boneTable[b.Parent]; - Vector3 parentTransformWorldPosition = parentTransform.position; - Quaternion parentTransformWorldRotation = parentTransform.rotation; - - parentSpaceHelper.position = parentTransformWorldPosition; - parentSpaceHelper.rotation = parentTransformWorldRotation; - parentSpaceHelper.localScale = parentTransform.localScale; - - 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?? - } - } - } - - b.x = Mathf.Lerp(b.x, boneLocalPosition.x, mix); - b.y = Mathf.Lerp(b.y, boneLocalPosition.y, mix); - b.rotation = Mathf.Lerp(b.rotation, boneLocalRotation, mix); - //b.AppliedRotation = Mathf.Lerp(b.AppliedRotation, boneLocalRotation, mix); - } - } - - static List AttachBoundingBoxRagdollColliders (Bone b, GameObject go, Skeleton skeleton, float gravityScale) { - const string AttachmentNameMarker = "ragdoll"; - var colliders = new List(); - var skin = skeleton.Skin ?? skeleton.Data.DefaultSkin; - - var attachments = new List(); - foreach (Slot s in skeleton.Slots) { - if (s.bone == b) { - skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(s), attachments); - foreach (var a in attachments) { - var bbAttachment = a as BoundingBoxAttachment; - if (bbAttachment != null) { - if (!a.Name.ToLower().Contains(AttachmentNameMarker)) - continue; - - var bbCollider = SkeletonUtility.AddBoundingBoxAsComponent(bbAttachment, s, go, isTrigger: false, isKinematic: false, gravityScale: gravityScale); - colliders.Add(bbCollider); - } - } - } - } - - 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); - } - - #if UNITY_EDITOR - void OnDrawGizmosSelected () { - if (isActive) { - Gizmos.DrawWireSphere(transform.position, thickness * 1.2f); - Vector3 newTransformPos = RootRigidbody.position - rootOffset; - Gizmos.DrawLine(transform.position, newTransformPos); - Gizmos.DrawWireSphere(newTransformPos, thickness * 1.2f); - } - } - #endif - } - -} +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF + * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +// Contributed by: Mitch Thompson + +using UnityEngine; +using System.Collections; +using System.Collections.Generic; + +namespace Spine.Unity.Modules { + [RequireComponent(typeof(SkeletonRenderer))] + public class SkeletonRagdoll2D : MonoBehaviour { + static Transform parentSpaceHelper; + + #region Inspector + [Header("Hierarchy")] + [SpineBone] + public string startingBoneName = ""; + [SpineBone] + public List stopBoneNames = new List(); + + [Header("Parameters")] + public bool applyOnStart; + [Tooltip("Warning! You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")] + public bool disableIK = true; + public bool disableOtherConstraints = false; + [Space] + [Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")] + public bool pinStartBone; + public float gravityScale = 1; + [Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")] + public float thickness = 0.125f; + [Tooltip("Default rotational limit value. Min is negative this value, Max is this value.")] + public float rotationLimit = 20; + public float rootMass = 20; + [Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")] + [Range(0.01f, 1f)] + public float massFalloffFactor = 0.4f; + [Tooltip("The layer assigned to all of the rigidbody parts.")] + [SkeletonRagdoll.LayerField] + public int colliderLayer = 0; + [Range(0, 1)] + public float mix = 1; + #endregion + + ISkeletonAnimation targetSkeletonComponent; + Skeleton skeleton; + Dictionary boneTable = new Dictionary(); + Transform ragdollRoot; + public Rigidbody2D RootRigidbody { get; private set; } + public Bone StartingBone { get; private set; } + Vector2 rootOffset; + public Vector3 RootOffset { get { return this.rootOffset; } } + bool isActive; + public bool IsActive { get { return this.isActive; } } + + IEnumerator Start () { + if (parentSpaceHelper == null) { + parentSpaceHelper = (new GameObject("Parent Space Helper")).transform; + } + + targetSkeletonComponent = GetComponent() as ISkeletonAnimation; + if (targetSkeletonComponent == null) Debug.LogError("Attached Spine component does not implement ISkeletonAnimation. This script is not compatible."); + skeleton = targetSkeletonComponent.Skeleton; + + if (applyOnStart) { + yield return null; + Apply(); + } + } + + #region API + public Rigidbody2D[] RigidbodyArray { + get { + if (!isActive) + return new Rigidbody2D[0]; + + var rigidBodies = new Rigidbody2D[boneTable.Count]; + int i = 0; + foreach (Transform t in boneTable.Values) { + rigidBodies[i] = t.GetComponent(); + i++; + } + + return rigidBodies; + } + } + + public Vector3 EstimatedSkeletonPosition { + get { return this.RootRigidbody.position - rootOffset; } + } + + /// Instantiates the ragdoll simulation and applies its transforms to the skeleton. + public void Apply () { + isActive = true; + mix = 1; + + Bone startingBone = this.StartingBone = skeleton.FindBone(startingBoneName); + RecursivelyCreateBoneProxies(startingBone); + + RootRigidbody = boneTable[startingBone].GetComponent(); + RootRigidbody.isKinematic = pinStartBone; + RootRigidbody.mass = rootMass; + var boneColliders = new List(); + foreach (var pair in boneTable) { + var b = pair.Key; + var t = pair.Value; + Transform parentTransform; + boneColliders.Add(t.GetComponent()); + 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)); + } else { + ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0); + ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetPropagatedRotation(b.Parent)); + } + parentTransform = ragdollRoot; + rootOffset = t.position - transform.position; + } else { + parentTransform = boneTable[b.Parent]; + } + + // Add joint and attach to parent. + var rbParent = parentTransform.GetComponent(); + if (rbParent != null) { + var joint = t.gameObject.AddComponent(); + joint.connectedBody = rbParent; + Vector3 localPos = parentTransform.InverseTransformPoint(t.position); + joint.connectedAnchor = localPos; + + joint.GetComponent().mass = joint.connectedBody.mass * massFalloffFactor; + joint.limits = new JointAngleLimits2D { + min = -rotationLimit, + max = rotationLimit + }; + joint.useLimits = true; + } + } + + // Ignore collisions among bones. + for (int x = 0; x < boneColliders.Count; x++) { + for (int y = 0; y < boneColliders.Count; y++) { + if (x == y) continue; + Physics2D.IgnoreCollision(boneColliders[x], boneColliders[y]); + } + } + + // Destroy existing override-mode SkeletonUtility bones. + var utilityBones = GetComponentsInChildren(); + if (utilityBones.Length > 0) { + var destroyedUtilityBoneNames = new List(); + foreach (var ub in utilityBones) { + if (ub.mode == SkeletonUtilityBone.Mode.Override) { + destroyedUtilityBoneNames.Add(ub.gameObject.name); + Destroy(ub.gameObject); + } + } + if (destroyedUtilityBoneNames.Count > 0) { + string msg = "Destroyed Utility Bones: "; + for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) { + msg += destroyedUtilityBoneNames[i]; + if (i != destroyedUtilityBoneNames.Count - 1) { + msg += ","; + } + } + Debug.LogWarning(msg); + } + } + + // Disable skeleton constraints. + if (disableIK) { + var ikConstraints = skeleton.IkConstraints; + for (int i = 0, n = ikConstraints.Count; i < n; i++) + ikConstraints.Items[i].mix = 0; + } + + if (disableOtherConstraints) { + var transformConstraints = skeleton.transformConstraints; + for (int i = 0, n = transformConstraints.Count; i < n; i++) { + transformConstraints.Items[i].rotateMix = 0; + transformConstraints.Items[i].scaleMix = 0; + transformConstraints.Items[i].shearMix = 0; + transformConstraints.Items[i].translateMix = 0; + } + + var pathConstraints = skeleton.pathConstraints; + for (int i = 0, n = pathConstraints.Count; i < n; i++) { + pathConstraints.Items[i].rotateMix = 0; + pathConstraints.Items[i].translateMix = 0; + } + } + + targetSkeletonComponent.UpdateWorld += UpdateSpineSkeleton; + } + + /// Transitions the mix value from the current value to a target value. + public Coroutine SmoothMix (float target, float duration) { + return StartCoroutine(SmoothMixCoroutine(target, duration)); + } + + IEnumerator SmoothMixCoroutine (float target, float duration) { + float startTime = Time.time; + float startMix = mix; + while (mix > 0) { + skeleton.SetBonesToSetupPose(); + mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration); + yield return null; + } + } + + /// Set the transform world position while preserving the ragdoll parts world position. + public void SetSkeletonPosition (Vector3 worldPosition) { + if (!isActive) { + Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!"); + return; + } + + Vector3 offset = worldPosition - transform.position; + transform.position = worldPosition; + foreach (Transform t in boneTable.Values) + t.position -= offset; + + UpdateSpineSkeleton(null); + skeleton.UpdateWorldTransform(); + } + + /// Removes the ragdoll instance and effect from the animated skeleton. + public void Remove () { + isActive = false; + foreach (var t in boneTable.Values) + Destroy(t.gameObject); + + Destroy(ragdollRoot.gameObject); + boneTable.Clear(); + targetSkeletonComponent.UpdateWorld -= UpdateSpineSkeleton; + } + + public Rigidbody2D GetRigidbody (string boneName) { + var bone = skeleton.FindBone(boneName); + return (bone != null && boneTable.ContainsKey(bone)) ? boneTable[bone].GetComponent() : null; + } + #endregion + + /// Generates the ragdoll simulation's Transform and joint setup. + void RecursivelyCreateBoneProxies (Bone b) { + string boneName = b.data.name; + if (stopBoneNames.Contains(boneName)) + return; + + var boneGameObject = new GameObject(boneName); + boneGameObject.layer = this.colliderLayer; + Transform t = boneGameObject.transform; + boneTable.Add(b, t); + + t.parent = transform; + t.localPosition = new Vector3(b.WorldX, b.WorldY, 0); + t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX - b.shearX); + t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 0); + + // MITCH: You left "todo: proper ragdoll branching" + var colliders = AttachBoundingBoxRagdollColliders(b, boneGameObject, skeleton, this.gravityScale); + if (colliders.Count == 0) { + float length = b.data.length; + if (length == 0) { + var circle = boneGameObject.AddComponent(); + circle.radius = thickness * 0.5f; + } else { + var box = boneGameObject.AddComponent(); + box.size = new Vector2(length, thickness); + box.offset = new Vector2(length * 0.5f, 0); // box.center in UNITY_4 + } + } + + var rb = boneGameObject.GetComponent(); + if (rb == null) rb = boneGameObject.AddComponent(); + rb.gravityScale = this.gravityScale; + + foreach (Bone child in b.Children) + RecursivelyCreateBoneProxies(child); + } + + /// Performed every skeleton animation update to translate Unity Transforms positions into Spine bone transforms. + void UpdateSpineSkeleton (ISkeletonAnimation animatedSkeleton) { + bool flipX = skeleton.flipX; + bool flipY = skeleton.flipY; + bool flipXOR = flipX ^ flipY; + bool flipOR = flipX || flipY; + var startingBone = this.StartingBone; + + foreach (var pair in boneTable) { + var b = pair.Key; + var t = pair.Value; + bool isStartingBone = (b == startingBone); + Transform parentTransform = isStartingBone ? ragdollRoot : boneTable[b.Parent]; + Vector3 parentTransformWorldPosition = parentTransform.position; + Quaternion parentTransformWorldRotation = parentTransform.rotation; + + parentSpaceHelper.position = parentTransformWorldPosition; + parentSpaceHelper.rotation = parentTransformWorldRotation; + parentSpaceHelper.localScale = parentTransform.localScale; + + 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?? + } + } + } + + b.x = Mathf.Lerp(b.x, boneLocalPosition.x, mix); + b.y = Mathf.Lerp(b.y, boneLocalPosition.y, mix); + b.rotation = Mathf.Lerp(b.rotation, boneLocalRotation, mix); + //b.AppliedRotation = Mathf.Lerp(b.AppliedRotation, boneLocalRotation, mix); + } + } + + static List AttachBoundingBoxRagdollColliders (Bone b, GameObject go, Skeleton skeleton, float gravityScale) { + const string AttachmentNameMarker = "ragdoll"; + var colliders = new List(); + var skin = skeleton.Skin ?? skeleton.Data.DefaultSkin; + + var attachments = new List(); + foreach (Slot s in skeleton.Slots) { + if (s.bone == b) { + skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(s), attachments); + foreach (var a in attachments) { + var bbAttachment = a as BoundingBoxAttachment; + if (bbAttachment != null) { + if (!a.Name.ToLower().Contains(AttachmentNameMarker)) + continue; + + var bbCollider = SkeletonUtility.AddBoundingBoxAsComponent(bbAttachment, s, go, isTrigger: false, isKinematic: false, gravityScale: gravityScale); + colliders.Add(bbCollider); + } + } + } + } + + 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); + } + + #if UNITY_EDITOR + void OnDrawGizmosSelected () { + if (isActive) { + Gizmos.DrawWireSphere(transform.position, thickness * 1.2f); + Vector3 newTransformPos = RootRigidbody.position - rootOffset; + Gizmos.DrawLine(transform.position, newTransformPos); + Gizmos.DrawWireSphere(newTransformPos, thickness * 1.2f); + } + } + #endif + } + +} diff --git a/spine-unity/Assets/spine-unity/SkeletonAnimation.cs b/spine-unity/Assets/spine-unity/SkeletonAnimation.cs index 7296c4616..f69546429 100644 --- a/spine-unity/Assets/spine-unity/SkeletonAnimation.cs +++ b/spine-unity/Assets/spine-unity/SkeletonAnimation.cs @@ -126,7 +126,7 @@ namespace Spine.Unity { } #endregion - protected override void ClearState () { + public override void ClearState () { base.ClearState(); if (state != null) state.ClearTracks(); } diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index a643a5c28..78b114194 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -149,7 +149,7 @@ namespace Spine.Unity { rendererBuffers.Dispose(); } - protected virtual void ClearState () { + public virtual void ClearState () { meshFilter.sharedMesh = null; currentInstructions.Clear(); if (skeleton != null) skeleton.SetToSetupPose(); diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs index b44cb5306..9765e4b66 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs +++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs @@ -38,7 +38,7 @@ namespace Spine.Unity { [RequireComponent(typeof(ISkeletonAnimation))] [ExecuteInEditMode] public class SkeletonUtility : MonoBehaviour { - + #region BoundingBoxAttachment public static PolygonCollider2D AddBoundingBoxGameObject (Skeleton skeleton, string skinName, string slotName, string attachmentName, Transform parent, bool isTrigger = true) { Skin skin = string.IsNullOrEmpty(skinName) ? skeleton.data.defaultSkin : skeleton.data.FindSkin(skinName); @@ -225,7 +225,7 @@ namespace Spine.Unity { var ikConstraints = skeleton.IkConstraints; for (int i = 0, n = ikConstraints.Count; i < n; i++) constraintTargets.Add(ikConstraints.Items[i].target); - + var transformConstraints = skeleton.TransformConstraints; for (int i = 0, n = transformConstraints.Count; i < n; i++) constraintTargets.Add(transformConstraints.Items[i].target); @@ -246,7 +246,7 @@ namespace Spine.Unity { if (hasTransformBones || hasUtilityConstraints) skeletonAnimation.UpdateWorld += UpdateWorld; - + if (hasUtilityConstraints) skeletonAnimation.UpdateComplete += UpdateComplete; } @@ -283,7 +283,7 @@ namespace Spine.Unity { void UpdateAllBones () { if (boneRoot == null) CollectBones(); - + var utilityBones = this.utilityBones; if (utilityBones == null) return; for (int i = 0, n = utilityBones.Count; i < n; i++)