diff --git a/spine-unity/Assets/Examples/Scenes/Ragdoll.unity b/spine-unity/Assets/Examples/Scenes/Ragdoll.unity new file mode 100644 index 000000000..b35ed7554 Binary files /dev/null and b/spine-unity/Assets/Examples/Scenes/Ragdoll.unity differ diff --git a/spine-unity/Assets/Examples/Scenes/Ragdoll.unity.meta b/spine-unity/Assets/Examples/Scenes/Ragdoll.unity.meta new file mode 100644 index 000000000..cd725ce04 --- /dev/null +++ b/spine-unity/Assets/Examples/Scenes/Ragdoll.unity.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 031930e4cebf68345b71c664bfa622cf +DefaultImporter: + userData: diff --git a/spine-unity/Assets/Examples/Scripts/RaggedySpineboy.cs b/spine-unity/Assets/Examples/Scripts/RaggedySpineboy.cs new file mode 100644 index 000000000..eea04f694 --- /dev/null +++ b/spine-unity/Assets/Examples/Scripts/RaggedySpineboy.cs @@ -0,0 +1,82 @@ +using UnityEngine; +using System.Collections; + +public class RaggedySpineboy : MonoBehaviour { + + public LayerMask groundMask; + public float restoreDuration = 0.5f; + public Vector2 launchVelocity = new Vector2(50,100); + + SkeletonRagdoll2D ragdoll; + Collider2D naturalCollider; + + void Start () { + + ragdoll = GetComponent(); + naturalCollider = GetComponent(); + } + + void AddRigidbody () { + var rb = gameObject.AddComponent(); + rb.fixedAngle = true; + naturalCollider.enabled = true; + } + + void RemoveRigidbody () { + Destroy(GetComponent()); + naturalCollider.enabled = false; + } + + void Update () { + + } + + void OnMouseUp () { + if (naturalCollider.enabled) { + Launch(); + } + } + + void Launch () { + RemoveRigidbody(); + ragdoll.Apply(); + ragdoll.RootRigidbody.velocity = new Vector2(Random.Range(-launchVelocity.x, launchVelocity.x), launchVelocity.y); + StartCoroutine(WaitUntilStopped()); + } + + IEnumerator Restore () { + Vector3 estimatedPos = ragdoll.EstimatedSkeletonPosition; + Vector3 rbPosition = ragdoll.RootRigidbody.position; + + Ray ray = new Ray(rbPosition, estimatedPos - rbPosition); + Vector3 skeletonPoint = estimatedPos; + RaycastHit2D hit = Physics2D.Raycast((Vector2)rbPosition, (Vector2)(estimatedPos - rbPosition), Vector3.Distance(estimatedPos, rbPosition), groundMask); + if (hit.collider != null) + skeletonPoint = hit.point; + + + ragdoll.RootRigidbody.isKinematic = true; + ragdoll.SetSkeletonPosition(skeletonPoint); + + yield return ragdoll.SmoothMix(0, restoreDuration); + ragdoll.Remove(); + + AddRigidbody(); + } + + IEnumerator WaitUntilStopped () { + yield return new WaitForSeconds(0.5f); + + float t = 0; + while (t < 0.5f) { + if (ragdoll.RootRigidbody.velocity.magnitude > 0.06f) + t = 0; + else + t += Time.deltaTime; + + yield return null; + } + + StartCoroutine(Restore()); + } +} diff --git a/spine-unity/Assets/Examples/Scripts/RaggedySpineboy.cs.meta b/spine-unity/Assets/Examples/Scripts/RaggedySpineboy.cs.meta new file mode 100644 index 000000000..5c864d277 --- /dev/null +++ b/spine-unity/Assets/Examples/Scripts/RaggedySpineboy.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 849a7739a7df0754882fcb34c09df4c1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy.meta b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy.meta new file mode 100644 index 000000000..ff4d0f512 --- /dev/null +++ b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 31a18437d3dfcde44a2e4b24361a3620 +folderAsset: yes +DefaultImporter: + userData: diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy.prefab b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy.prefab new file mode 100644 index 000000000..618b8cd95 Binary files /dev/null and b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy.prefab differ diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy.prefab.meta b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy.prefab.meta new file mode 100644 index 000000000..cba1ddd6d --- /dev/null +++ b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy.prefab.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 5c60df38c5334a249b38ac8cddc6433b +NativeFormatImporter: + userData: diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.atlas.txt b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.atlas.txt new file mode 100644 index 000000000..5597c2893 --- /dev/null +++ b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.atlas.txt @@ -0,0 +1,34 @@ + +Raggedy Spineboy.png +size: 256,256 +format: RGBA8888 +filter: Linear,Linear +repeat: none +arm + rotate: false + xy: 140, 178 + size: 71, 75 + orig: 71, 75 + offset: 0, 0 + index: -1 +head + rotate: false + xy: 2, 66 + size: 136, 187 + orig: 136, 187 + offset: 0, 0 + index: -1 +leg + rotate: false + xy: 140, 77 + size: 36, 99 + orig: 36, 99 + offset: 0, 0 + index: -1 +torso + rotate: true + xy: 2, 2 + size: 62, 95 + orig: 62, 95 + offset: 0, 0 + index: -1 diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.atlas.txt.meta b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.atlas.txt.meta new file mode 100644 index 000000000..6d92e370d --- /dev/null +++ b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.atlas.txt.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: bdfc7a081d52b68499e44aa82689a73d +TextScriptImporter: + userData: diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.json b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.json new file mode 100644 index 000000000..41815f4bb --- /dev/null +++ b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.json @@ -0,0 +1,374 @@ +{ +"skeleton": { "hash": "VwRlHLlX3k1oQzXmdPiYJ828MGo", "spine": "2.1.27", "width": 157.46, "height": 364.95, "images": "" }, +"bones": [ + { "name": "root" }, + { "name": "hip", "parent": "root", "x": -0.79, "y": 91.41 }, + { "name": "L-thigh", "parent": "hip", "length": 29.76, "x": 17.31, "y": -5.19, "rotation": -81.94 }, + { "name": "R-thigh", "parent": "hip", "length": 29.49, "x": -18.18, "y": -6.06, "rotation": -93.15 }, + { "name": "abdomen", "parent": "hip", "length": 33.49, "y": -0.1, "rotation": 89.54 }, + { "name": "L-foot", "parent": "L-thigh", "length": 37.25, "x": 37.35, "y": -1.78, "rotation": -6.29 }, + { "name": "R-foot", "parent": "R-thigh", "length": 39.98, "x": 36.41, "y": 0.27, "rotation": -1.8 }, + { "name": "chest", "parent": "abdomen", "length": 29.58, "x": 38.07, "y": 0.72 }, + { "name": "L-arm", "parent": "chest", "length": 32.67, "x": 24.63, "y": -16.69, "rotation": -121.22 }, + { "name": "R-arm", "parent": "chest", "length": 36.76, "x": 26, "y": 13.63, "rotation": 133.37 }, + { "name": "head", "parent": "chest", "length": 94.23, "x": 41.01, "y": -0.1, "rotation": -2.25 }, + { "name": "L-forearm", "parent": "L-arm", "length": 33.69, "x": 39.09, "y": -2.34, "rotation": -12.09 }, + { "name": "R-forearm", "parent": "R-arm", "length": 36.13, "x": 41.65, "y": 0.28, "rotation": 2.72 }, + { "name": "scalp", "parent": "head", "length": 31.94, "x": 129.34, "y": 15.1, "rotation": -29.89 }, + { "name": "hair1", "parent": "scalp", "length": 23, "x": 36.51, "y": 4.12, "rotation": 68.48 }, + { "name": "hair2", "parent": "hair1", "length": 23.49, "x": 29.03, "y": 1.58, "rotation": 59.55 } +], +"slots": [ + { "name": "R-arm", "bone": "R-arm", "attachment": "arm" }, + { "name": "L-arm", "bone": "L-arm", "attachment": "arm" }, + { "name": "L-leg", "bone": "L-thigh", "attachment": "leg" }, + { "name": "R-leg", "bone": "R-thigh", "attachment": "leg" }, + { "name": "torso", "bone": "abdomen", "attachment": "torso" }, + { "name": "head", "bone": "head", "attachment": "head" } +], +"skins": { + "default": { + "L-arm": { + "arm": { + "type": "skinnedmesh", + "uvs": [ 1, 0.16417, 0.90367, 0.30177, 0.80735, 0.43937, 0.75345, 0.50663, 0.71536, 0.55416, 0.6656, 0.61625, 0.63233, 0.65777, 0.59417, 0.7054, 0.45366, 0.8527, 0.31315, 1, 0.15657, 1, 0, 1, 0, 0.71457, 0.13235, 0.59073, 0.2647, 0.46689, 0.34675, 0.39836, 0.39153, 0.36096, 0.43007, 0.32876, 0.4689, 0.29633, 0.52302, 0.25112, 0.59417, 0.19169, 0.72983, 0.09584, 0.86549, 0, 1, 0, 0.15702, 0.83582, 0.46721, 0.51561, 0.78995, 0.22527, 0.34029, 0.70958, 0.62889, 0.38429 ], + "triangles": [ 10, 24, 9, 9, 27, 8, 9, 24, 27, 10, 11, 24, 11, 12, 24, 8, 27, 7, 12, 13, 24, 24, 13, 27, 13, 14, 27, 27, 25, 7, 25, 27, 14, 7, 25, 6, 6, 25, 5, 18, 4, 17, 28, 4, 18, 4, 28, 3, 15, 16, 25, 16, 17, 25, 25, 17, 5, 17, 4, 5, 3, 28, 2, 28, 26, 2, 2, 26, 1, 18, 19, 28, 19, 20, 28, 28, 20, 26, 1, 26, 0, 20, 21, 26, 26, 22, 0, 26, 21, 22, 22, 23, 0, 25, 14, 15 ], + "vertices": [ 1, 8, -11.38, 11.4, 1, 1, 8, 0.99, 11.79, 1, 1, 8, 13.36, 12.17, 1, 1, 8, 19.69, 11.97, 1, 2, 8, 24.16, 11.82, 0.91747, 11, -17.57, 10.72, 0.08252, 2, 8, 30, 11.63, 0.75238, 11, -11.82, 11.76, 0.24761, 2, 8, 33.91, 11.5, 0.44551, 11, -7.97, 12.46, 0.55448, 2, 8, 38.39, 11.36, 0.2127, 11, -3.56, 13.25, 0.78729, 2, 8, 53.17, 9.6, 0.07308, 11, 11.25, 14.64, 0.92691, 2, 8, 67.94999, 7.85, 0.00873, 11, 26.07, 16.03, 0.99126, 1, 11, 34.25, 8.51, 1, 1, 11, 42.44, 0.99, 1, 1, 11, 27.96, -14.77, 1, 2, 8, 50.32, -20.36, 0.05493, 11, 14.75, -15.25, 0.94506, 2, 8, 37.31, -18.06, 0.23231, 11, 1.55, -15.73, 0.76768, 2, 8, 29.75, -16.27, 0.47867, 11, -6.21, -15.58, 0.52132, 2, 8, 25.63, -15.3, 0.71242, 11, -10.43999, -15.49, 0.28757, 2, 8, 22.07, -14.47, 0.81875, 11, -14.09, -15.42, 0.18124, 2, 8, 18.5, -13.62, 0.9506, 11, -17.77, -15.34, 0.04939, 2, 8, 13.51, -12.45, 0.97879, 11, -22.89, -15.24, 0.0212, 2, 8, 6.95, -10.9, 0.99703, 11, -29.63, -15.11, 0.00296, 1, 8, -4.46999, -7.2, 1, 1, 8, -15.9, -3.49, 1, 1, 8, -21.42, 4.29, 1, 1, 11, 25.9, -0.52999, 1, 2, 8, 31.98, -4.21, 0.80128, 11, -6.55, -3.32, 0.19871, 1, 8, 0.97, 1.89, 1, 1, 11, 9.91, 1.29, 1, 1, 8, 17.31, -0.54, 1 ], + "hull": 24, + "edges": [ 0, 2, 2, 4, 4, 6, 14, 16, 16, 18, 18, 20, 20, 22, 22, 24, 24, 26, 26, 28, 28, 30, 38, 40, 40, 42, 42, 44, 44, 46, 46, 0, 10, 34, 30, 32, 32, 34, 10, 12, 12, 14, 6, 8, 8, 10, 34, 36, 36, 38, 8, 36 ], + "width": 71, + "height": 75 + } + }, + "L-leg": { + "leg": { + "type": "skinnedmesh", + "uvs": [ 1, 0.23128, 1, 0.29497, 1, 0.37025, 1, 0.44552, 1, 0.50921, 1, 0.65975, 1, 0.71765, 1, 0.87399, 0.73923, 1, 0.2297, 1, 0, 0.89715, 0, 0.64817, 0.01978, 0.59915, 0.08516, 0.43711, 0.10541, 0.38693, 0.13057, 0.32458, 0.15317, 0.26858, 0.17799, 0.20706, 0.26155, 0, 1, 0, 0.61185, 0.12127, 0.51631, 0.54395 ], + "triangles": [ 21, 13, 4, 21, 4, 5, 12, 13, 21, 12, 21, 5, 12, 5, 6, 11, 12, 6, 9, 10, 11, 11, 6, 9, 6, 8, 9, 7, 8, 6, 20, 18, 19, 20, 19, 0, 17, 18, 20, 17, 20, 0, 17, 0, 1, 16, 17, 1, 16, 1, 2, 15, 16, 2, 15, 2, 3, 14, 15, 3, 14, 3, 4, 13, 14, 4 ], + "vertices": [ 1, 2, 11.02, 15.14, 1, 1, 2, 17.31, 14.75, 1, 2, 2, 24.75, 14.29, 0.95576, 5, -14.28, 14.6, 0.04423, 2, 2, 32.18999, 13.82, 0.71873, 5, -6.84, 14.95, 0.28126, 2, 2, 38.48, 13.43, 0.37176, 5, -0.54, 15.25, 0.62822, 2, 2, 53.36, 12.51, 0.00735, 5, 14.34, 15.96, 0.99264, 1, 5, 20.06, 16.23, 1, 1, 5, 35.52, 16.96999, 1, 1, 5, 48.43, 8.18, 1, 1, 5, 49.3, -10.13, 1, 1, 5, 39.52, -18.87, 1, 2, 2, 49.98, -23.34, 0.00312, 5, 14.9, -20.04, 0.99687, 2, 2, 45.18, -22.33, 0.02542, 5, 10.02, -19.56, 0.97457, 2, 2, 29.31, -18.99, 0.4709, 5, -6.1, -17.98, 0.52909, 2, 2, 24.4, -17.95, 0.69967, 5, -11.1, -17.48, 0.30032, 2, 2, 18.29, -16.66, 0.89625, 5, -17.31, -16.87, 0.10374, 2, 2, 12.81, -15.51, 0.97789, 5, -22.89, -16.32, 0.0221, 1, 2, 6.79, -14.24, 1, 1, 2, -13.48, -9.96, 1, 1, 2, -11.83, 16.56, 1, 1, 2, -0.71, 1.87, 1, 1, 5, 3.71, -1.97, 1 ], + "hull": 20, + "edges": [ 36, 38, 20, 22, 18, 20, 16, 18, 16, 14, 22, 24, 24, 10, 10, 12, 12, 14, 12, 22, 24, 26, 10, 8, 26, 8, 8, 6, 26, 28, 6, 28, 28, 30, 6, 4, 30, 4, 4, 2, 30, 32, 2, 32, 32, 34, 34, 36, 2, 0, 0, 38, 34, 0 ], + "width": 36, + "height": 99 + } + }, + "R-arm": { + "arm": { + "type": "skinnedmesh", + "uvs": [ 1, 0.16417, 0.90367, 0.30177, 0.80735, 0.43937, 0.75345, 0.50663, 0.71536, 0.55416, 0.6656, 0.61625, 0.63233, 0.65777, 0.59417, 0.7054, 0.45366, 0.8527, 0.31315, 1, 0.15657, 1, 0, 1, 0, 0.71457, 0.13235, 0.59073, 0.2647, 0.46689, 0.34675, 0.39836, 0.39153, 0.36096, 0.43007, 0.32876, 0.4689, 0.29633, 0.52302, 0.25112, 0.59417, 0.19169, 0.72983, 0.09584, 0.86549, 0, 1, 0, 0.15702, 0.83582, 0.46721, 0.51561, 0.78995, 0.22527, 0.34029, 0.70958, 0.62889, 0.38429 ], + "triangles": [ 10, 24, 9, 9, 27, 8, 9, 24, 27, 10, 11, 24, 11, 12, 24, 8, 27, 7, 12, 13, 24, 24, 13, 27, 13, 14, 27, 27, 25, 7, 25, 14, 15, 25, 27, 14, 7, 25, 6, 22, 23, 0, 26, 22, 0, 1, 26, 0, 6, 25, 5, 18, 4, 17, 28, 4, 18, 4, 28, 3, 15, 16, 25, 16, 17, 25, 25, 17, 5, 17, 4, 5, 3, 28, 2, 28, 26, 2, 2, 26, 1, 18, 19, 28, 19, 20, 28, 28, 20, 26, 20, 21, 26, 26, 21, 22 ], + "vertices": [ 1, 9, -6.97, 5.02, 1, 1, 9, 5.06, 7.92, 1, 1, 9, 17.09, 10.82, 1, 2, 9, 23.33, 11.91, 0.99563, 12, -17.74, 12.48, 0.00436, 2, 9, 27.74, 12.68, 0.95467, 12, -13.3, 13.04, 0.04532, 2, 9, 33.5, 13.68, 0.75827, 12, -7.5, 13.77, 0.24172, 2, 9, 37.34999, 14.35, 0.53963, 12, -3.63, 14.26, 0.46036, 2, 9, 41.75999, 15.12, 0.29362, 12, 0.81, 14.82, 0.70637, 2, 9, 56.59, 16.42, 3.9E-4, 12, 15.69, 15.4, 0.9996, 1, 12, 30.56, 15.99, 1, 1, 12, 38.33, 8.04, 1, 1, 12, 46.1, 0.1, 1, 1, 12, 30.79, -14.86, 1, 2, 9, 59.92, -13.5, 4.7E-4, 12, 17.58, -14.63, 0.99952, 2, 9, 46.71, -13.9, 0.17384, 12, 4.37, -14.41, 0.82615, 2, 9, 38.93999, -13.69, 0.56829, 12, -3.36, -13.83, 0.4317, 2, 9, 34.71, -13.58, 0.79613, 12, -7.59, -13.52, 0.20386, 2, 9, 31.06, -13.49, 0.92361, 12, -11.23, -13.25, 0.07638, 2, 9, 27.38, -13.39, 0.98277, 12, -14.9, -12.98, 0.01722, 1, 9, 22.26, -13.26, 1, 1, 9, 15.53, -13.08, 1, 1, 9, 3.58, -11.78, 1, 1, 9, -8.35999, -10.49, 1, 1, 9, -15.36, -3.99, 1, 1, 12, 29.5, -0.52999, 1, 2, 9, 38.66999, -1.43, 0.57762, 12, -3.06, -1.57, 0.42237, 1, 9, 7.06, -1.77, 1, 1, 12, 13.64, 2.15, 1, 1, 9, 23.56, -0.82, 1 ], + "hull": 24, + "edges": [ 0, 2, 2, 4, 4, 6, 14, 16, 16, 18, 18, 20, 20, 22, 22, 24, 24, 26, 26, 28, 28, 30, 38, 40, 40, 42, 42, 44, 44, 46, 46, 0, 10, 34, 30, 32, 32, 34, 10, 12, 12, 14, 6, 8, 8, 10, 34, 36, 36, 38, 8, 36 ], + "width": 71, + "height": 75 + } + }, + "R-leg": { + "leg": { + "type": "skinnedmesh", + "uvs": [ 1, 0.23128, 1, 0.29497, 1, 0.37025, 1, 0.44552, 1, 0.50921, 1, 0.65975, 1, 0.71765, 1, 0.87399, 0.73923, 1, 0.2297, 1, 0, 0.89715, 0, 0.64817, 0.01978, 0.59915, 0.08516, 0.43711, 0.10541, 0.38693, 0.13057, 0.32458, 0.15317, 0.26858, 0.17799, 0.20706, 0.26155, 0, 1, 0, 0.61185, 0.12127, 0.51631, 0.54395 ], + "triangles": [ 21, 13, 4, 21, 4, 5, 12, 13, 21, 12, 21, 5, 12, 5, 6, 11, 12, 6, 9, 10, 11, 11, 6, 9, 6, 8, 9, 7, 8, 6, 20, 18, 19, 20, 19, 0, 17, 18, 20, 17, 20, 0, 17, 0, 1, 16, 17, 1, 16, 1, 2, 15, 16, 2, 15, 2, 3, 14, 15, 3, 14, 3, 4, 13, 14, 4 ], + "vertices": [ 1, 3, 7.41, 14.89, 1, 2, 3, 13.7, 15.23, 0.99431, 6, -23.16, 14.24, 0.00568, 2, 3, 21.14, 15.64, 0.9183, 6, -15.74, 14.88, 0.08169, 2, 3, 28.58, 16.04999, 0.65731, 6, -8.31, 15.53, 0.34268, 2, 3, 34.88, 16.4, 0.33128, 6, -2.03, 16.07, 0.66871, 2, 3, 49.76, 17.21999, 0.004, 6, 12.81, 17.36, 0.99598, 1, 6, 18.52, 17.85, 1, 2, 3, 70.94, 18.39, 0, 6, 33.93999, 19.19, 0.99999, 2, 3, 83.91, 9.7, 0, 6, 47.18, 10.92, 0.99999, 2, 3, 84.92, -8.60999, 0, 6, 48.76, -7.35, 1, 2, 3, 75.21, -17.42, 0, 6, 39.33, -16.46999, 1, 2, 3, 50.6, -18.78, 0.01347, 6, 14.78, -18.6, 0.98652, 2, 3, 45.71, -18.34, 0.05686, 6, 9.88, -18.31, 0.94313, 2, 3, 29.56, -16.87, 0.66681, 6, -6.3, -17.35, 0.33318, 2, 3, 24.56, -16.41, 0.86313, 6, -11.31, -17.04999, 0.13686, 2, 3, 18.35, -15.85, 0.97672, 6, -17.54, -16.68, 0.02327, 2, 3, 12.77, -15.34, 0.99935, 6, -23.13, -16.35, 6.4E-4, 1, 3, 6.64, -14.78, 1, 2, 3, -13.98, -12.91, 0.99999, 6, -49.96, -14.76, 0, 2, 3, -15.45, 13.63, 0.99999, 6, -52.25, 11.72, 0, 2, 3, -2.69, 0.33, 0.99999, 6, -39.09, -1.16, 0, 2, 3, 39.27, -0.79, 0.02734, 6, 2.89, -0.97, 0.97265 ], + "hull": 20, + "edges": [ 36, 38, 20, 22, 18, 20, 16, 18, 16, 14, 22, 24, 24, 10, 10, 12, 12, 14, 12, 22, 24, 26, 10, 8, 26, 8, 8, 6, 26, 28, 6, 28, 28, 30, 6, 4, 30, 4, 4, 2, 30, 32, 2, 32, 32, 34, 34, 36, 2, 0, 0, 38, 34, 0 ], + "width": 36, + "height": 99 + } + }, + "head": { + "head": { + "type": "skinnedmesh", + "uvs": [ 0.60755, 0.01863, 0.64145, 0.03354, 0.70226, 0.06028, 0.76687, 0.08869, 0.80695, 0.14523, 0.84157, 0.19407, 1, 0.41294, 1, 0.78561, 0.67348, 1, 0.38213, 1, 0.13934, 0.8937, 0.07948, 0.78807, 0.05898, 0.75189, 0, 0.6478, 0, 0.40213, 0.15055, 0.27783, 0.25631, 0.21733, 0.28424, 0.20136, 0.31116, 0.18596, 0.32033, 0.16739, 0.32984, 0.14813, 0.3317, 0.12797, 0.33358, 0.1076, 0.29622, 0.08869, 0.21778, 0.06977, 0.2514, 0.03194, 0.32658, 0.01699, 0.3752, 0.00732, 0.41202, 0, 0.45684, 0, 0.49046, 0, 0.53154, 0, 0.56516, 0, 0.55022, 0.1049, 0.46057, 0.06437, 0.38587, 0.05086, 0.31116, 0.04815, 0.54649, 0.17515, 0.35972, 0.28864, 0.14308, 0.41294, 0.13187, 0.57777, 0.24766, 0.43185, 0.43816, 0.37511, 0.59878, 0.3616, 0.78181, 0.43726, 0.8976, 0.53994, 0.87616, 0.37786 ], + "triangles": [ 36, 25, 26, 35, 27, 28, 23, 25, 36, 24, 25, 23, 26, 35, 36, 35, 26, 27, 22, 36, 35, 23, 36, 22, 28, 29, 34, 35, 28, 34, 21, 35, 34, 35, 21, 22, 34, 29, 30, 33, 31, 32, 33, 32, 0, 31, 34, 30, 34, 20, 21, 31, 33, 34, 37, 34, 33, 1, 33, 0, 2, 33, 1, 33, 2, 37, 37, 20, 34, 37, 38, 20, 19, 20, 38, 18, 19, 38, 17, 18, 38, 2, 4, 37, 4, 2, 3, 43, 4, 5, 43, 37, 4, 42, 38, 37, 43, 42, 37, 6, 46, 5, 44, 43, 5, 39, 14, 15, 41, 15, 16, 39, 15, 41, 16, 17, 38, 41, 16, 38, 41, 38, 42, 46, 44, 5, 45, 46, 6, 44, 46, 45, 40, 14, 39, 40, 39, 41, 13, 14, 40, 12, 13, 40, 45, 6, 7, 11, 12, 40, 9, 10, 40, 11, 40, 10, 9, 41, 42, 9, 40, 41, 8, 9, 42, 42, 43, 8, 44, 8, 43, 8, 44, 45, 8, 45, 7 ], + "vertices": [ 1, 14, 17.03, -22.65, 1, 3, 10, 187.59, -11.93, 0.00181, 13, 63.97, 5.58, 0.0238, 14, 11.42, -25.01, 0.97437, 2, 10, 182.37, -21.52, 0.62993, 14, 1.35, -29.25, 0.37005, 3, 10, 176.82, -31.71, 0.82289, 13, 64.49, -16.93, 0.07936, 14, -9.33, -33.75, 0.09774, 3, 10, 165.13, -38.41999, 0.8635, 13, 57.69, -28.57, 0.08155, 14, -22.66, -31.7, 0.05493, 3, 10, 155.03, -44.22, 0.89858, 13, 51.83, -38.63, 0.08345, 14, -34.16999, -29.93, 0.01796, 1, 10, 109.8, -70.69999, 1, 1, 10, 30.83, -74.44, 1, 1, 10, -16.95999, -26.54, 1, 1, 10, -19.08, 18.11, 1, 1, 10, 1.67, 56.39, 1, 1, 10, 23.62, 66.62999, 1, 1, 10, 31.14, 70.12999, 1, 1, 10, 52.77, 80.22, 1, 2, 10, 104.83, 82.69, 0.99073, 13, -54.92, 46.39, 0.00926, 3, 10, 132.26, 60.86, 0.88784, 13, -20.26, 41.13, 0.11168, 15, 48.07, 46.13, 4.7E-4, 4, 10, 145.85, 45.25, 0.85196, 13, -0.71, 34.37, 0.12365, 14, 14.48, 45.72, 0.00832, 15, 30.69, 34.9, 0.01603, 4, 10, 149.43, 41.13, 0.84249, 13, 4.44999, 32.58, 0.12681, 14, 14.71, 40.25999, 0.01053, 15, 26.1, 31.93, 0.02015, 4, 10, 152.89, 37.16, 0.83335, 13, 9.43, 30.86, 0.12986, 14, 14.94, 35, 0.01265, 15, 21.68, 29.07, 0.02412, 4, 10, 156.9, 35.93999, 0.60487, 13, 13.5, 31.8, 0.21602, 14, 17.31, 31.55, 0.05833, 15, 19.9, 25.28, 0.12076, 4, 10, 161.05, 34.68, 0.368, 13, 17.73, 32.77, 0.30535, 14, 19.76, 27.97, 0.10568, 15, 18.06, 21.35, 0.22096, 4, 10, 165.33, 34.59999, 0.18496, 13, 21.49, 34.83, 0.23674, 14, 23.06, 25.23, 0.12789, 15, 17.37, 17.12, 0.45039, 3, 13, 25.28, 36.91999, 0.1674, 14, 26.39, 22.46, 0.15034, 15, 16.67, 12.85, 0.68225, 3, 13, 25.58, 43.91, 0.03309, 14, 33, 24.76, 0.02128, 15, 21.99, 8.31, 0.94562, 1, 15, 33.59999, 3.17, 1, 1, 15, 27.7, -4.32, 1, 1, 15, 15.91, -6.38, 1, 1, 15, 8.29, -7.71, 1, 1, 15, 2.51, -8.72, 1, 2, 14, 33.79, -6.23, 0.33703, 15, -4.32, -8.06, 0.66296, 2, 14, 30.77, -10.41, 0.58777, 15, -9.46, -7.57, 0.41222, 2, 14, 27.07, -15.52, 0.81446, 15, -15.74, -6.97, 0.18553, 2, 14, 24.05, -19.7, 0.97838, 15, -20.87, -6.48, 0.02161, 1, 14, 7.36, -4.8, 1, 1, 14, 22.39, 1.29999, 1, 1, 15, 7.54, 1.63, 1, 3, 13, 34.06, 46.61, 0.01617, 14, 38.62, 17.86, 0.00459, 15, 18.89, -0.02, 0.97922, 1, 13, 30.81, 1.67, 1, 3, 10, 131.49, 28.69, 0.99827, 14, -7.07, 41.73, 7.0E-5, 15, 16.33, 51.46, 0.00165, 1, 10, 103.58, 60.65, 1, 1, 10, 68.57, 60.71, 1, 1, 10, 100.33, 44.43, 1, 1, 10, 113.74, 15.79, 1, 1, 10, 117.77, -8.68, 1, 1, 10, 103.06, -37.5, 1, 1, 10, 82.15, -56.28, 1, 3, 10, 116.33, -51.36, 0.97904, 13, 21.84, -64.11, 0.01724, 14, -68.86, -11.37, 0.00371 ], + "hull": 33, + "edges": [ 16, 14, 16, 18, 18, 20, 26, 28, 28, 30, 44, 46, 46, 48, 48, 50, 14, 12, 10, 12, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 60, 62, 62, 64, 2, 0, 0, 64, 2, 4, 4, 6, 20, 22, 22, 24, 24, 26, 80, 82, 82, 84, 84, 86, 86, 88, 88, 90, 90, 12, 80, 26, 34, 36, 30, 32, 32, 34, 36, 38, 38, 40, 40, 42, 42, 44, 12, 92, 6, 8, 8, 10 ], + "width": 136, + "height": 187 + }, + "ragdoll": { + "type": "boundingbox", + "vertices": [ -14.19607, -1.49276, -7.91528, -29.96175, 23.08404, -59.72487, 60.33676, -65.35634, 95.9493, -71.06551, 150.43092, -41.36028, 163.83543, 5.30173, 162.47502, 34.00399, 115.66124, 67.94895, 85.4782, 80.49074, 48.92517, 71.36101, 11.9019, 54.81194, -9.19035, 31.6207 ] + } + }, + "torso": { + "ragdoll": { + "type": "boundingbox", + "vertices": [ 0.62625, -28.95774, 35.77471, -25.70054, 37.14599, 27.3694, 1.96002, 28.88128 ] + }, + "torso": { + "type": "skinnedmesh", + "uvs": [ 0.87097, 0.13351, 1, 0.26702, 1, 0.45027, 1, 0.63351, 1, 0.81675, 1, 1, 0.75, 1, 0.5, 1, 0.25, 1, 0, 1, 0, 0.72402, 0, 0.44804, 0.09822, 0.22402, 0.19645, 0, 0.4692, 0, 0.74194, 0, 0.58868, 0.13131, 0.40099, 0.46062, 0.83539, 0.50155, 0.42394, 0.26749, 0.36228, 0.63165, 0.58838, 0.76773, 0.71972, 0.25772, 0.84057, 0.76485, 0.57726, 0.50305, 0.24069, 0.44015, 0.19158, 0.80079, 0.29694, 0.12288, 0.37842, 0.84005, 0.71037, 0.63432, 0.15888, 0.60895 ], + "triangles": [ 8, 26, 28, 8, 28, 7, 9, 26, 8, 9, 10, 26, 23, 4, 5, 6, 23, 5, 7, 21, 6, 6, 21, 23, 23, 3, 4, 22, 19, 16, 22, 0, 1, 19, 14, 16, 19, 27, 14, 22, 15, 0, 22, 16, 15, 12, 13, 27, 16, 14, 15, 27, 13, 14, 22, 24, 19, 1, 18, 22, 25, 27, 19, 25, 12, 27, 17, 19, 24, 24, 22, 18, 17, 25, 19, 7, 28, 21, 26, 20, 28, 28, 20, 21, 10, 30, 26, 26, 30, 20, 20, 24, 21, 21, 29, 23, 21, 24, 29, 29, 18, 23, 23, 18, 3, 10, 11, 30, 29, 24, 18, 18, 2, 3, 30, 25, 20, 20, 17, 24, 20, 25, 17, 30, 11, 25, 2, 18, 1, 11, 12, 25 ], + "vertices": [ 1, 7, 31.68, -23.15, 1, 2, 4, 57.14, -30.52, 0.39506, 7, 19.06, -31.25, 0.60493, 2, 4, 39.73, -30.66, 0.60493, 7, 1.66, -31.38, 0.39506, 2, 4, 22.33, -30.79, 0.79012, 7, -15.74, -31.52, 0.20987, 1, 2, -7.76, 14.88, 1, 1, 2, 9.47, 12.45, 1, 1, 2, 7.3, -2.89, 1, 2, 2, 5.13, -18.24, 0.488, 3, 5.76, 18.5, 0.51199, 2, 2, 2.96, -33.59, 0.16266, 3, 6.61, 3.02, 0.83733, 3, 4, -12.97, 30.92, 0.26337, 7, -51.04, 30.19, 0.06995, 3, 7.46, -12.45, 0.66666, 1, 3, -18.70999, -13.88, 1, 2, 4, 39.46, 31.33, 0.60493, 7, 1.38, 30.6, 0.39506, 2, 4, 60.79, 25.41, 0.39506, 7, 22.71, 24.68, 0.60493, 1, 7, 44.04, 18.76, 1, 1, 7, 44.17, 1.85, 1, 1, 7, 44.3, -15.05, 1, 1, 7, 31.75, -5.65, 1, 2, 4, 38.46, 6.46, 0.55198, 7, 0.38, 5.73, 0.448, 2, 4, 34.78, -20.49, 0.55198, 7, -3.29, -21.22, 0.448, 1, 7, 18.74, 4.46, 1, 1, 4, 22.19, 8.72999, 1, 2, 4, 9.37, -5.38, 0.52, 2, -15.94, -9.72, 0.48, 1, 7, 19.81, -13.86, 1, 2, 4, 9.77, -21.01, 0.52, 2, -14.02, 5.79, 0.48, 2, 4, 34.50999, -4.48999, 0.55198, 7, -3.55, -5.21999, 0.448, 2, 4, 40.32, 16.42, 0.55198, 7, 2.25, 15.69, 0.448, 2, 4, 6.04, 19.19, 0.584, 3, -12.08, -1.62, 0.41599, 1, 7, 32.41, 12.44, 1, 2, 4, 2.4, 7.58, 0.584, 3, -8.99, 10.14, 0.41599, 1, 4, 22.11, -12.84, 1, 1, 4, 24.25, 21.36, 1 ], + "hull": 16, + "edges": [ 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18, 20, 20, 22, 22, 24, 24, 26, 26, 28, 28, 30, 30, 0 ], + "width": 62, + "height": 95 + } + } + } +}, +"animations": { + "animation": { + "bones": { + "abdomen": { + "rotate": [ + { + "time": 0, + "angle": 0, + "curve": [ 0.25, 0, 0.374, 1 ] + }, + { "time": 0.3333, "angle": 2.47 }, + { "time": 1.3333, "angle": 0 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + }, + "chest": { + "rotate": [ + { + "time": 0, + "angle": 0, + "curve": [ 0.25, 0, 0.374, 1 ] + }, + { + "time": 0.3333, + "angle": 21.85, + "curve": [ 0.25, 0, 0.434, 1 ] + }, + { "time": 1.3333, "angle": 0 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + }, + "head": { + "rotate": [ + { + "time": 0, + "angle": 0, + "curve": [ 0.348, 0, 0.608, 0.5 ] + }, + { + "time": 0.1, + "angle": -10.88, + "curve": [ 0.25, 0, 0.75, 1 ] + }, + { + "time": 0.4333, + "angle": 3.79, + "curve": [ 0.803, 0, 0.592, 0.98 ] + }, + { "time": 1.3333, "angle": 0 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + }, + "R-arm": { + "rotate": [ + { + "time": 0, + "angle": 0, + "curve": [ 0.659, -0.5, 0.608, 0.5 ] + }, + { + "time": 0.3333, + "angle": -11.69, + "curve": [ 0.25, 0, 0.75, 1 ] + }, + { "time": 1.3333, "angle": 0 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + }, + "L-arm": { + "rotate": [ + { + "time": 0, + "angle": 0, + "curve": [ 0.25, 0, 0.374, 1 ] + }, + { + "time": 0.3333, + "angle": 53.01, + "curve": [ 0.659, 0.01, 0.734, 0.42 ] + }, + { + "time": 0.7666, + "angle": 56.78, + "curve": [ 0.44, 0.4, 0.695, 1 ] + }, + { "time": 1.3333, "angle": 0 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + }, + "R-forearm": { + "rotate": [ + { + "time": 0, + "angle": 0, + "curve": [ 0.25, 0, 0.374, 1 ] + }, + { + "time": 0.3333, + "angle": 9.78, + "curve": [ 0.25, 0, 0.471, 1 ] + }, + { "time": 1.3333, "angle": 0 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + }, + "L-forearm": { + "rotate": [ + { + "time": 0, + "angle": 14.89, + "curve": [ 0.33, -5.56, 0.527, 1 ] + }, + { + "time": 0.4333, + "angle": 32.07, + "curve": [ 0.641, 0, 0.317, 1 ] + }, + { + "time": 0.6333, + "angle": 9.77, + "curve": [ 0.25, 0, 0.317, 1 ] + }, + { + "time": 0.9, + "angle": 58, + "curve": [ 0.25, 0, 0.628, 1 ] + }, + { "time": 1.3333, "angle": 14.89 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + }, + "scalp": { + "rotate": [ + { + "time": 0, + "angle": -7.01, + "curve": [ 0.357, 0, 0.642, 0.45 ] + }, + { + "time": 0.2666, + "angle": 7.61, + "curve": [ 0.208, 0.44, 0.478, 1 ] + }, + { "time": 0.6666, "angle": 0 }, + { "time": 1.3333, "angle": -7.01 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + }, + "hair1": { + "rotate": [ + { + "time": 0, + "angle": -8.8, + "curve": [ 0.25, 0, 0.374, 1 ] + }, + { + "time": 0.2666, + "angle": -16.02, + "curve": [ 0.25, 0, 0.535, 1 ] + }, + { + "time": 0.5333, + "angle": 29.38, + "curve": [ 0.25, 0, 0.438, 1 ] + }, + { "time": 1.3333, "angle": -8.8 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + }, + "hair2": { + "rotate": [ + { + "time": 0, + "angle": 4.65, + "curve": [ 0.282, 0.3, 0.374, 1 ] + }, + { + "time": 0.2666, + "angle": -17.96, + "curve": [ 0.25, 0, 0.535, 1 ] + }, + { + "time": 0.6333, + "angle": 6.62, + "curve": [ 0.25, 0, 0.438, 1 ] + }, + { "time": 1.3333, "angle": 4.65 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + }, + "root": { + "rotate": [ + { "time": 0, "angle": 0 } + ], + "translate": [ + { "time": 0, "x": -0.59, "y": 0 } + ] + }, + "R-foot": { + "rotate": [ + { "time": 0, "angle": 0 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + }, + "R-thigh": { + "rotate": [ + { "time": 0, "angle": 0 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + }, + "L-foot": { + "rotate": [ + { "time": 0, "angle": 0 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + }, + "L-thigh": { + "rotate": [ + { "time": 0, "angle": 0 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + }, + "hip": { + "rotate": [ + { "time": 0, "angle": 0 } + ], + "translate": [ + { "time": 0, "x": 0, "y": 0 } + ] + } + } + } +} +} \ No newline at end of file diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.json.meta b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.json.meta new file mode 100644 index 000000000..2f3417f5b --- /dev/null +++ b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.json.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: e6f1c85da28190c49a9aaa887894ab0d +TextScriptImporter: + userData: diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.png b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.png new file mode 100644 index 000000000..cb07c5df1 Binary files /dev/null and b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.png differ diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.png.meta b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.png.meta new file mode 100644 index 000000000..3f00c1513 --- /dev/null +++ b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy.png.meta @@ -0,0 +1,47 @@ +fileFormatVersion: 2 +guid: b29bbacbc2368c94a9c942d176ac6f59 +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Atlas.asset b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Atlas.asset new file mode 100644 index 000000000..6f99b08ed Binary files /dev/null and b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Atlas.asset differ diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Atlas.asset.meta b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Atlas.asset.meta new file mode 100644 index 000000000..28738eda5 --- /dev/null +++ b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Atlas.asset.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: a9d85e8796d75384199c06f6fdbb0d73 +NativeFormatImporter: + userData: diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Material.mat b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Material.mat new file mode 100644 index 000000000..48ee5e073 Binary files /dev/null and b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Material.mat differ diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Material.mat.meta b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Material.mat.meta new file mode 100644 index 000000000..58813197c --- /dev/null +++ b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_Material.mat.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 4ad4f7167d4983147ad870f93ebc9416 +NativeFormatImporter: + userData: diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_SkeletonData.asset b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_SkeletonData.asset new file mode 100644 index 000000000..31e9c71fa Binary files /dev/null and b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_SkeletonData.asset differ diff --git a/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_SkeletonData.asset.meta b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_SkeletonData.asset.meta new file mode 100644 index 000000000..076aa16cb --- /dev/null +++ b/spine-unity/Assets/Examples/Spine/Raggedy Spineboy/Raggedy Spineboy_SkeletonData.asset.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 57484171e9b9c7243aa3117bc663e7b9 +NativeFormatImporter: + userData: diff --git a/spine-unity/Assets/Examples/Spine/dragon.prefab b/spine-unity/Assets/Examples/Spine/dragon.prefab index d11770576..f70e632e4 100644 Binary files a/spine-unity/Assets/Examples/Spine/dragon.prefab and b/spine-unity/Assets/Examples/Spine/dragon.prefab differ diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs.meta b/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs.meta index 1e73fe1df..37b13c997 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs.meta +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs.meta @@ -1,10 +1,8 @@ fileFormatVersion: 2 -guid: 8dc542c228b046648ae29be625ecd1b4 +guid: 687d9be457ea4eb44bf09c35c95ee5cd MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: - assetBundleName: - assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs.meta b/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs.meta index 5a602df97..fba64b6e3 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs.meta +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs.meta @@ -6,5 +6,3 @@ MonoImporter: executionOrder: 0 icon: {instanceID: 0} userData: - assetBundleName: - assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs.meta b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs.meta index 858912afe..544e47769 100644 --- a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs.meta +++ b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs.meta @@ -6,5 +6,3 @@ MonoImporter: executionOrder: 0 icon: {instanceID: 0} userData: - assetBundleName: - assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Ragdoll.meta b/spine-unity/Assets/spine-unity/Ragdoll.meta new file mode 100644 index 000000000..cb9062592 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Ragdoll.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 90af663b37d994841b7ac03ae30fe2a9 +folderAsset: yes +DefaultImporter: + userData: diff --git a/spine-unity/Assets/spine-unity/Ragdoll/Editor.meta b/spine-unity/Assets/spine-unity/Ragdoll/Editor.meta new file mode 100644 index 000000000..6cac463d2 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Ragdoll/Editor.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 7220dc1e8d545e849a2eb63e8633349b +folderAsset: yes +DefaultImporter: + userData: diff --git a/spine-unity/Assets/spine-unity/Ragdoll/Editor/SkeletonRagdoll2DInspector.cs b/spine-unity/Assets/spine-unity/Ragdoll/Editor/SkeletonRagdoll2DInspector.cs new file mode 100644 index 000000000..f059aae31 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Ragdoll/Editor/SkeletonRagdoll2DInspector.cs @@ -0,0 +1,49 @@ +/***************************************************************************** + * SkeletonRagdoll2D added by Mitch Thompson + * Full irrevocable rights and permissions granted to Esoteric Software +*****************************************************************************/ + +using UnityEngine; +using UnityEditor; +using System.Collections; +using System.Collections.Generic; + +[CustomEditor(typeof(SkeletonRagdoll2D))] +public class SkeletonRagdoll2DInspector : Editor { + SerializedProperty startingBoneName, stopBoneNames, applyOnStart, pinStartBone, enableJointCollision, gravityScale, disableIK, defaultThickness, rotationLimit, colliderLayer, mix; + + void OnEnable () { + startingBoneName = serializedObject.FindProperty("startingBoneName"); + stopBoneNames = serializedObject.FindProperty("stopBoneNames"); + applyOnStart = serializedObject.FindProperty("applyOnStart"); + pinStartBone = serializedObject.FindProperty("pinStartBone"); + enableJointCollision = serializedObject.FindProperty("enableJointCollision"); + gravityScale = serializedObject.FindProperty("gravityScale"); + disableIK = serializedObject.FindProperty("disableIK"); + defaultThickness = serializedObject.FindProperty("defaultThickness"); + rotationLimit = serializedObject.FindProperty("rotationLimit"); + colliderLayer = serializedObject.FindProperty("colliderLayer"); + mix = serializedObject.FindProperty("mix"); + } + + public override void OnInspectorGUI () { + EditorGUILayout.PropertyField(startingBoneName); + EditorGUILayout.PropertyField(stopBoneNames, true); + EditorGUILayout.PropertyField(applyOnStart); + EditorGUILayout.PropertyField(pinStartBone); + EditorGUILayout.PropertyField(enableJointCollision); + EditorGUILayout.PropertyField(gravityScale); + EditorGUILayout.PropertyField(disableIK); + EditorGUILayout.PropertyField(defaultThickness); + EditorGUILayout.PropertyField(rotationLimit); + colliderLayer.intValue = EditorGUILayout.LayerField(colliderLayer.displayName, colliderLayer.intValue); + EditorGUILayout.PropertyField(mix); + + serializedObject.ApplyModifiedProperties(); + } + + void Header (string name) { + GUILayout.Space(20); + EditorGUILayout.LabelField(name, EditorStyles.boldLabel); + } +} diff --git a/spine-unity/Assets/spine-unity/Ragdoll/Editor/SkeletonRagdoll2DInspector.cs.meta b/spine-unity/Assets/spine-unity/Ragdoll/Editor/SkeletonRagdoll2DInspector.cs.meta new file mode 100644 index 000000000..08480207a --- /dev/null +++ b/spine-unity/Assets/spine-unity/Ragdoll/Editor/SkeletonRagdoll2DInspector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b6dd0b99faf3aeb4d803eb9989cb369c +timeCreated: 1431741936 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Ragdoll/Editor/SkeletonRagdollInspector.cs b/spine-unity/Assets/spine-unity/Ragdoll/Editor/SkeletonRagdollInspector.cs new file mode 100644 index 000000000..a92f570e2 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Ragdoll/Editor/SkeletonRagdollInspector.cs @@ -0,0 +1,49 @@ +/***************************************************************************** + * SkeletonRagdoll added by Mitch Thompson + * Full irrevocable rights and permissions granted to Esoteric Software +*****************************************************************************/ + +using UnityEngine; +using UnityEditor; +using System.Collections; +using System.Collections.Generic; + +[CustomEditor(typeof(SkeletonRagdoll))] +public class SkeletonRagdollInspector : Editor { + SerializedProperty startingBoneName, stopBoneNames, applyOnStart, pinStartBone, enableJointCollision, useGravity, disableIK, defaultThickness, rotationLimit, colliderLayer, mix; + + void OnEnable () { + startingBoneName = serializedObject.FindProperty("startingBoneName"); + stopBoneNames = serializedObject.FindProperty("stopBoneNames"); + applyOnStart = serializedObject.FindProperty("applyOnStart"); + pinStartBone = serializedObject.FindProperty("pinStartBone"); + enableJointCollision = serializedObject.FindProperty("enableJointCollision"); + useGravity = serializedObject.FindProperty("useGravity"); + disableIK = serializedObject.FindProperty("disableIK"); + defaultThickness = serializedObject.FindProperty("defaultThickness"); + rotationLimit = serializedObject.FindProperty("rotationLimit"); + colliderLayer = serializedObject.FindProperty("colliderLayer"); + mix = serializedObject.FindProperty("mix"); + } + + public override void OnInspectorGUI () { + EditorGUILayout.PropertyField(startingBoneName); + EditorGUILayout.PropertyField(stopBoneNames, true); + EditorGUILayout.PropertyField(applyOnStart); + EditorGUILayout.PropertyField(pinStartBone); + EditorGUILayout.PropertyField(enableJointCollision); + EditorGUILayout.PropertyField(useGravity); + EditorGUILayout.PropertyField(disableIK); + EditorGUILayout.PropertyField(defaultThickness); + EditorGUILayout.PropertyField(rotationLimit); + colliderLayer.intValue = EditorGUILayout.LayerField(colliderLayer.displayName, colliderLayer.intValue); + EditorGUILayout.PropertyField(mix); + + serializedObject.ApplyModifiedProperties(); + } + + void Header (string name) { + GUILayout.Space(20); + EditorGUILayout.LabelField(name, EditorStyles.boldLabel); + } +} diff --git a/spine-unity/Assets/spine-unity/Ragdoll/Editor/SkeletonRagdollInspector.cs.meta b/spine-unity/Assets/spine-unity/Ragdoll/Editor/SkeletonRagdollInspector.cs.meta new file mode 100644 index 000000000..7c478ae50 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Ragdoll/Editor/SkeletonRagdollInspector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c95a670c56447c644a0f062e4cdd448e +timeCreated: 1431740230 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Ragdoll/SkeletonRagdoll.cs b/spine-unity/Assets/spine-unity/Ragdoll/SkeletonRagdoll.cs new file mode 100644 index 000000000..ac43ad1cd --- /dev/null +++ b/spine-unity/Assets/spine-unity/Ragdoll/SkeletonRagdoll.cs @@ -0,0 +1,379 @@ +/***************************************************************************** + * SkeletonRagdoll added by Mitch Thompson + * Full irrevocable rights and permissions granted to Esoteric Software +*****************************************************************************/ + +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using Spine; + +[RequireComponent(typeof(SkeletonRenderer))] +public class SkeletonRagdoll : MonoBehaviour { + private static Transform helper; + + [Header("Hierarchy")] + [SpineBone] + public string startingBoneName = ""; + [SpineBone] + public List stopBoneNames = new List(); + + [Header("Parameters")] + public bool applyOnStart; + [Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")] + public bool pinStartBone; + [Tooltip("Enable Collision between adjacent ragdoll elements (IE: Neck and Head)")] + public bool enableJointCollision; + public bool useGravity = true; + [Tooltip("Warning! You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")] + public bool disableIK = true; + [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 defaultThickness = 0.125f; + [Tooltip("Default rotational limit value. Min is negative this value, Max is this value.")] + public float rotationLimit = 20; + [Tooltip("The layer assigned to all of the rigidbody parts.")] + public int colliderLayer = 0; + [Range(0, 1)] + public float mix = 1; + + public Rigidbody RootRigidbody { + get { + return this.rootRigidbody; + } + } + + public Vector3 RootOffset { + get { + return this.rootOffset; + } + } + + public Vector3 EstimatedSkeletonPosition { + get { + return rootRigidbody.position - rootOffset; + } + } + + public bool IsActive { + get { + return this.isActive; + } + } + + private Rigidbody rootRigidbody; + private ISkeletonAnimation skeletonAnim; + private Skeleton skeleton; + private Dictionary boneTable = new Dictionary(); + private Bone startingBone; + private Transform ragdollRoot; + private Vector3 rootOffset; + private bool isActive; + + IEnumerator Start () { + skeletonAnim = (ISkeletonAnimation)GetComponent(); + if (helper == null) { + helper = (Transform)(new GameObject("Helper")).transform; + helper.hideFlags = HideFlags.HideInHierarchy; + } + + if (applyOnStart) { + yield return null; + Apply(); + } + } + + 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) { + mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration); + yield return null; + } + } + + 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; + } + } + + public void Remove () { + isActive = false; + foreach (var t in boneTable.Values) { + Destroy(t.gameObject); + } + Destroy(ragdollRoot.gameObject); + + boneTable.Clear(); + skeletonAnim.UpdateWorld -= UpdateWorld; + } + + public void Apply () { + isActive = true; + skeleton = skeletonAnim.Skeleton; + mix = 1; + + var ragdollRootBone = skeleton.FindBone(startingBoneName); + startingBone = ragdollRootBone; + RecursivelyCreateBoneProxies(ragdollRootBone); + + rootRigidbody = boneTable[ragdollRootBone].GetComponent(); + rootRigidbody.isKinematic = pinStartBone; + + List boneColliders = new List(); + + foreach (var pair in boneTable) { + var b = pair.Key; + var t = pair.Value; + Bone parentBone = null; + Transform parentTransform = transform; + + boneColliders.Add(t.GetComponent()); + + if (b != startingBone) { + parentBone = b.Parent; + parentTransform = boneTable[parentBone]; + } else { + ragdollRoot = new GameObject("RagdollRoot").transform; + ragdollRoot.parent = transform; + + if (b == skeleton.RootBone) { + ragdollRoot.localPosition = new Vector3(b.WorldX, b.WorldY, 0); + ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b)); + parentTransform = ragdollRoot; + } else { + ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0); + ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b.Parent)); + parentTransform = ragdollRoot; + } + + rootOffset = t.position - transform.position; + } + + var rbParent = parentTransform.GetComponent(); + + if (rbParent != null) { + var joint = t.gameObject.AddComponent(); + joint.connectedBody = rbParent; + Vector3 localPos = parentTransform.InverseTransformPoint(t.position); + localPos.x *= 1; + joint.connectedAnchor = localPos; + joint.axis = Vector3.forward; + joint.GetComponent().mass = joint.connectedBody.mass * 0.75f; + JointLimits limits = new JointLimits(); + limits.min = -rotationLimit; + limits.max = rotationLimit; + joint.limits = limits; + joint.useLimits = true; + joint.enableCollision = enableJointCollision; + } + } + + for (int x = 0; x < boneColliders.Count; x++) { + for (int y = 0; y < boneColliders.Count; y++) { + Physics.IgnoreCollision(boneColliders[x], boneColliders[y]); + } + } + + var utilityBones = GetComponentsInChildren(); + if (utilityBones.Length > 0) { + List 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); + } + } + + if (disableIK) { + foreach (IkConstraint ik in skeleton.IkConstraints) { + ik.Mix = 0; + } + } + + skeletonAnim.UpdateWorld += UpdateWorld; + } + + void RecursivelyCreateBoneProxies (Bone b) { + if (stopBoneNames.Contains(b.Data.Name)) + return; + + GameObject go = new GameObject(b.Data.Name); + go.layer = colliderLayer; + Transform t = go.transform; + boneTable.Add(b, t); + + t.parent = transform; + + t.localPosition = new Vector3(b.WorldX, b.WorldY, 0); + t.localRotation = Quaternion.Euler(0, 0, b.WorldFlipX ^ b.WorldFlipY ? -b.WorldRotation : b.WorldRotation); + t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 1); + + float length = b.Data.Length; + + var colliders = AttachBoundingBoxRagdollColliders(b); + + if (length == 0) { + //physics + if (colliders.Count == 0) { + var ball = go.AddComponent(); + ball.radius = defaultThickness / 2f; + } + } else { + //physics + if (colliders.Count == 0) { + var box = go.AddComponent(); + box.size = new Vector3(length, defaultThickness, defaultThickness); + box.center = new Vector3((b.WorldFlipX ? -length : length) / 2, 0); + } + } + + var rb = go.AddComponent(); + rb.constraints = RigidbodyConstraints.FreezePositionZ; + foreach (Bone child in b.Children) { + + RecursivelyCreateBoneProxies(child); + } + } + + List AttachBoundingBoxRagdollColliders (Bone b) { + List colliders = new List(); + + Transform t = boneTable[b]; + GameObject go = t.gameObject; + var skin = skeleton.Skin; + if (skin == null) + skin = skeleton.Data.DefaultSkin; + + bool flipX = b.WorldFlipX; + bool flipY = b.WorldFlipY; + + List 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) { + if (a is BoundingBoxAttachment) { + if (!a.Name.ToLower().Contains("ragdoll")) + continue; + + var collider = go.AddComponent(); + var bounds = SkeletonUtility.GetBoundingBoxBounds((BoundingBoxAttachment)a, defaultThickness); + + collider.center = bounds.center; + collider.size = bounds.size; + + if (flipX || flipY) { + Vector3 center = collider.center; + + if (flipX) + center.x *= -1; + + if (flipY) + center.y *= -1; + + collider.center = center; + } + + colliders.Add(collider); + } + } + } + } + + return colliders; + } + + void UpdateWorld (SkeletonRenderer skeletonRenderer) { + foreach (var pair in boneTable) { + var b = pair.Key; + var t = pair.Value; + bool flip = false; + bool flipX = false; //TODO: deal with negative scale instead of Flip Key for Spine 3.0 + bool flipY = false; //TODO: deal with negative scale instead of Flip Key for Spine 3.0 + Bone parentBone = null; + Transform parentTransform = transform; + + if (b != startingBone) { + parentBone = b.Parent; + parentTransform = boneTable[parentBone]; + flipX = parentBone.WorldFlipX; + flipY = parentBone.WorldFlipY; + + } else { + parentBone = b.Parent; + parentTransform = ragdollRoot; + if (b.Parent != null) { + flipX = b.worldFlipX; + flipY = b.WorldFlipY; + } else { + flipX = b.Skeleton.FlipX; + flipY = b.Skeleton.FlipY; + } + } + + flip = flipX ^ flipY; + + helper.position = parentTransform.position; + helper.rotation = parentTransform.rotation; + helper.localScale = new Vector3(flipX ? -parentTransform.localScale.x : parentTransform.localScale.x, flipY ? -parentTransform.localScale.y : parentTransform.localScale.y, 1); + + + Vector3 pos = t.position; + pos = helper.InverseTransformPoint(pos); + b.X = Mathf.Lerp(b.X, pos.x, mix); + b.Y = Mathf.Lerp(b.Y, pos.y, mix); + + Vector3 right = helper.InverseTransformDirection(t.right); + + float a = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg; + + if (b.WorldFlipX ^ b.WorldFlipY) { + a *= -1; + } + + if (parentBone != null) { + if ((b.WorldFlipX ^ b.WorldFlipY) != flip) { + a -= GetCompensatedRotationIK(parentBone) * 2; + } + } + + b.Rotation = Mathf.Lerp(b.Rotation, a, mix); + b.RotationIK = Mathf.Lerp(b.rotationIK, a, mix); + } + } + + float GetCompensatedRotationIK (Bone b) { + Bone parent = b.Parent; + float a = b.RotationIK; + while (parent != null) { + a += parent.RotationIK; + parent = parent.parent; + } + + return a; + } +} diff --git a/spine-unity/Assets/spine-unity/Ragdoll/SkeletonRagdoll.cs.meta b/spine-unity/Assets/spine-unity/Ragdoll/SkeletonRagdoll.cs.meta new file mode 100644 index 000000000..f19d6808f --- /dev/null +++ b/spine-unity/Assets/spine-unity/Ragdoll/SkeletonRagdoll.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 373527d2bf3351348b9fcc499ce9ea23 +timeCreated: 1430552693 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Ragdoll/SkeletonRagdoll2D.cs b/spine-unity/Assets/spine-unity/Ragdoll/SkeletonRagdoll2D.cs new file mode 100644 index 000000000..88eba0990 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Ragdoll/SkeletonRagdoll2D.cs @@ -0,0 +1,388 @@ +/***************************************************************************** + * SkeletonRagdoll2D added by Mitch Thompson + * Full irrevocable rights and permissions granted to Esoteric Software +*****************************************************************************/ + +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using Spine; + +[RequireComponent(typeof(SkeletonRenderer))] +public class SkeletonRagdoll2D : MonoBehaviour { + private static Transform helper; + + [Header("Hierarchy")] + [SpineBone] + public string startingBoneName = ""; + [SpineBone] + public List stopBoneNames = new List(); + + [Header("Parameters")] + public bool applyOnStart; + [Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")] + public bool pinStartBone; + [Tooltip("Enable Collision between adjacent ragdoll elements (IE: Neck and Head)")] + public bool enableJointCollision; + public float gravityScale = 1; + [Tooltip("Warning! You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")] + public bool disableIK = true; + [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 defaultThickness = 0.125f; + [Tooltip("Default rotational limit value. Min is negative this value, Max is this value.")] + public float rotationLimit = 20; + [Tooltip("The layer assigned to all of the rigidbody parts.")] + public int colliderLayer = 0; + [Range(0, 1)] + public float mix = 1; + + public Rigidbody2D RootRigidbody { + get { + return this.rootRigidbody; + } + } + + public Vector3 RootOffset { + get { + return this.rootOffset; + } + } + + public Vector3 EstimatedSkeletonPosition { + get { + return this.rootRigidbody.position - rootOffset; + } + } + + public bool IsActive { + get { + return this.isActive; + } + } + + private Rigidbody2D rootRigidbody; + private ISkeletonAnimation skeletonAnim; + private Skeleton skeleton; + private Dictionary boneTable = new Dictionary(); + private Bone startingBone; + private Transform ragdollRoot; + private Vector2 rootOffset; + private bool isActive; + + + IEnumerator Start () { + skeletonAnim = (ISkeletonAnimation)GetComponent(); + if (helper == null) { + helper = (Transform)(new GameObject("Helper")).transform; + helper.hideFlags = HideFlags.HideInHierarchy; + } + + if (applyOnStart) { + yield return null; + Apply(); + } + } + + 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) { + mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration); + yield return null; + } + } + + 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; + } + + UpdateWorld(null); + skeleton.UpdateWorldTransform(); + //skeletonAnim.LateUpdate(); + } + + public void Remove () { + isActive = false; + foreach (var t in boneTable.Values) { + Destroy(t.gameObject); + } + Destroy(ragdollRoot.gameObject); + + boneTable.Clear(); + skeletonAnim.UpdateWorld -= UpdateWorld; + } + + public void Apply () { + isActive = true; + skeleton = skeletonAnim.Skeleton; + mix = 1; + + var ragdollRootBone = skeleton.FindBone(startingBoneName); + startingBone = ragdollRootBone; + RecursivelyCreateBoneProxies(ragdollRootBone); + + rootRigidbody = boneTable[ragdollRootBone].GetComponent(); + rootRigidbody.isKinematic = pinStartBone; + + List boneColliders = new List(); + + foreach (var pair in boneTable) { + var b = pair.Key; + var t = pair.Value; + Bone parentBone = null; + Transform parentTransform = transform; + + boneColliders.Add(t.GetComponent()); + + if (b != startingBone) { + parentBone = b.Parent; + parentTransform = boneTable[parentBone]; + } else { + ragdollRoot = new GameObject("RagdollRoot").transform; + ragdollRoot.parent = transform; + + if (b == skeleton.RootBone) { + ragdollRoot.localPosition = new Vector3(b.WorldX, b.WorldY, 0); + ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b)); + parentTransform = ragdollRoot; + } else { + ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0); + ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b.Parent)); + parentTransform = ragdollRoot; + } + + rootOffset = t.position - transform.position; + } + + var rbParent = parentTransform.GetComponent(); + + if (rbParent != null) { + var joint = t.gameObject.AddComponent(); + joint.connectedBody = rbParent; + Vector3 localPos = parentTransform.InverseTransformPoint(t.position); + localPos.x *= 1; + joint.connectedAnchor = localPos; + joint.GetComponent().mass = joint.connectedBody.mass * 0.75f; + JointAngleLimits2D limits = new JointAngleLimits2D(); + limits.min = -rotationLimit; + limits.max = rotationLimit; + joint.limits = limits; + joint.useLimits = enableJointCollision; + } + } + + for (int x = 0; x < boneColliders.Count; x++) { + for (int y = 0; y < boneColliders.Count; y++) { + Physics2D.IgnoreCollision(boneColliders[x], boneColliders[y]); + } + } + + var utilityBones = GetComponentsInChildren(); + if (utilityBones.Length > 0) { + List 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); + } + } + + if (disableIK) { + foreach (IkConstraint ik in skeleton.IkConstraints) { + ik.Mix = 0; + } + } + + skeletonAnim.UpdateWorld += UpdateWorld; + } + + void RecursivelyCreateBoneProxies (Bone b) { + if (stopBoneNames.Contains(b.Data.Name)) + return; + + GameObject go = new GameObject(b.Data.Name); + go.layer = colliderLayer; + Transform t = go.transform; + boneTable.Add(b, t); + + t.parent = transform; + + t.localPosition = new Vector3(b.WorldX, b.WorldY, 0); + //TODO: deal with WorldFlipY + t.localRotation = Quaternion.Euler(0, 0, b.WorldFlipX ? -b.WorldRotation : b.WorldRotation); + t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 0); + + float length = b.Data.Length; + + //TODO proper ragdoll branching + var colliders = AttachBoundingBoxRagdollColliders(b); + + if (length == 0) { + //physics + if (colliders.Count == 0) { + var circle = go.AddComponent(); + circle.radius = defaultThickness / 2f; + } + } else { + //physics + if (colliders.Count == 0) { + var box = go.AddComponent(); + box.size = new Vector2(length, defaultThickness); +#if UNITY_5_0 + box.offset = new Vector2((b.WorldFlipX ? -length : length) / 2, 0); +#else + box.center = new Vector2((b.WorldFlipX ? -length : length) / 2, 0); +#endif + } + } + + var rb = go.AddComponent(); + rb.gravityScale = gravityScale; + + foreach (Bone child in b.Children) { + RecursivelyCreateBoneProxies(child); + } + } + + List AttachBoundingBoxRagdollColliders (Bone b) { + List colliders = new List(); + Transform t = boneTable[b]; + GameObject go = t.gameObject; + var skin = skeleton.Skin; + if (skin == null) + skin = skeleton.Data.DefaultSkin; + + bool flipX = b.WorldFlipX; + bool flipY = b.WorldFlipY; + + List 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) { + if (a is BoundingBoxAttachment) { + if (!a.Name.ToLower().Contains("ragdoll")) + continue; + + var collider = SkeletonUtility.AddBoundingBoxAsComponent((BoundingBoxAttachment)a, go, false); + + if (flipX || flipY) { + Vector2[] points = collider.points; + + for (int i = 0; i < points.Length; i++) { + if (flipX) + points[i].x *= -1; + + if (flipY) + points[i].y *= -1; + } + + collider.points = points; + } + + colliders.Add(collider); + } + } + } + } + + return colliders; + } + + void UpdateWorld (SkeletonRenderer skeletonRenderer) { + foreach (var pair in boneTable) { + var b = pair.Key; + var t = pair.Value; + bool flip = false; + bool flipX = false; //TODO: deal with negative scale instead of Flip Key + bool flipY = false; //TODO: deal with negative scale instead of Flip Key + Bone parentBone = null; + Transform parentTransform = transform; + + if (b != startingBone) { + parentBone = b.Parent; + parentTransform = boneTable[parentBone]; + flipX = parentBone.WorldFlipX; + flipY = parentBone.WorldFlipY; + + } else { + flipX = b.worldFlipX; + flipY = b.WorldFlipY; + } + + flip = flipX ^ flipY; + + helper.position = parentTransform.position; + helper.rotation = parentTransform.rotation; + helper.localScale = new Vector3(flipX ? -parentTransform.localScale.x : parentTransform.localScale.x, flipY ? -parentTransform.localScale.y : parentTransform.localScale.y, 1); + + + Vector3 pos = t.position; + pos = helper.InverseTransformPoint(pos); + b.X = Mathf.Lerp(b.X, pos.x, mix); + b.Y = Mathf.Lerp(b.Y, pos.y, mix); + + Vector3 right = helper.InverseTransformDirection(t.right); + + float a = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg; + + if (b.WorldFlipX ^ b.WorldFlipY) { + a *= -1; + } + + if (parentBone != null) { + if ((b.WorldFlipX ^ b.WorldFlipY) != flip) { + a -= GetCompensatedRotationIK(parentBone) * 2; + } + } + + b.Rotation = Mathf.Lerp(b.Rotation, a, mix); + b.RotationIK = Mathf.Lerp(b.rotationIK, a, mix); + } + } + + float GetCompensatedRotationIK (Bone b) { + Bone parent = b.Parent; + float a = b.RotationIK; + while (parent != null) { + a += parent.RotationIK; + parent = parent.parent; + } + + return a; + } + + void OnDrawGizmosSelected () { + if (isActive) { + Gizmos.DrawWireSphere(transform.position, defaultThickness * 1.2f); + Vector3 newTransformPos = rootRigidbody.position - rootOffset; + Gizmos.DrawLine(transform.position, newTransformPos); + Gizmos.DrawWireSphere(newTransformPos, defaultThickness * 1.2f); + } + } + +} diff --git a/spine-unity/Assets/spine-unity/Ragdoll/SkeletonRagdoll2D.cs.meta b/spine-unity/Assets/spine-unity/Ragdoll/SkeletonRagdoll2D.cs.meta new file mode 100644 index 000000000..ed29795fe --- /dev/null +++ b/spine-unity/Assets/spine-unity/Ragdoll/SkeletonRagdoll2D.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e74a49a26242a214d9084fde00bfe3ab +timeCreated: 1431497383 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/SkeletonAnimation.cs b/spine-unity/Assets/spine-unity/SkeletonAnimation.cs index be8f0299b..0384417bd 100644 --- a/spine-unity/Assets/spine-unity/SkeletonAnimation.cs +++ b/spine-unity/Assets/spine-unity/SkeletonAnimation.cs @@ -42,7 +42,7 @@ public class SkeletonAnimation : SkeletonRenderer, ISkeletonAnimation { public bool loop; public Spine.AnimationState state; - + public event UpdateBonesDelegate UpdateLocal { add { _UpdateLocal += value; } @@ -63,6 +63,12 @@ public class SkeletonAnimation : SkeletonRenderer, ISkeletonAnimation { protected event UpdateBonesDelegate _UpdateWorld; protected event UpdateBonesDelegate _UpdateComplete; + public Skeleton Skeleton { + get { + return this.skeleton; + } + } + [SerializeField] private String _animationName; diff --git a/spine-unity/Assets/spine-unity/SkeletonAnimationInterface.cs b/spine-unity/Assets/spine-unity/SkeletonAnimationInterface.cs index 03d3036ce..520114fd8 100644 --- a/spine-unity/Assets/spine-unity/SkeletonAnimationInterface.cs +++ b/spine-unity/Assets/spine-unity/SkeletonAnimationInterface.cs @@ -31,6 +31,7 @@ using UnityEngine; using System.Collections; +using Spine; public delegate void UpdateBonesDelegate (SkeletonRenderer skeletonRenderer); public interface ISkeletonAnimation { @@ -39,4 +40,5 @@ public interface ISkeletonAnimation { event UpdateBonesDelegate UpdateComplete; void LateUpdate (); + Skeleton Skeleton { get; } } diff --git a/spine-unity/Assets/spine-unity/SkeletonAnimator.cs b/spine-unity/Assets/spine-unity/SkeletonAnimator.cs index 038ef46ef..4daeda41e 100644 --- a/spine-unity/Assets/spine-unity/SkeletonAnimator.cs +++ b/spine-unity/Assets/spine-unity/SkeletonAnimator.cs @@ -15,6 +15,10 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { public enum MixMode { AlwaysMix, MixNext, SpineStyle } public MixMode[] layerMixModes = new MixMode[0]; + public Skeleton GetSkeleton () { + return this.skeleton; + + } public event UpdateBonesDelegate UpdateLocal { add { _UpdateLocal += value; } remove { _UpdateLocal -= value; } @@ -34,6 +38,12 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation { protected event UpdateBonesDelegate _UpdateWorld; protected event UpdateBonesDelegate _UpdateComplete; + public Skeleton Skeleton { + get { + return this.skeleton; + } + } + Dictionary animationTable = new Dictionary(); Animator animator; diff --git a/spine-unity/Assets/spine-unity/SkeletonExtensions.cs.meta b/spine-unity/Assets/spine-unity/SkeletonExtensions.cs.meta index 0ec145755..427cdd10a 100644 --- a/spine-unity/Assets/spine-unity/SkeletonExtensions.cs.meta +++ b/spine-unity/Assets/spine-unity/SkeletonExtensions.cs.meta @@ -6,5 +6,3 @@ MonoImporter: executionOrder: 0 icon: {instanceID: 0} userData: - assetBundleName: - assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs index 3252ee5cb..a236c2c78 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs +++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs @@ -95,6 +95,22 @@ public class SkeletonUtility : MonoBehaviour { return collider; } + public static Bounds GetBoundingBoxBounds (BoundingBoxAttachment boundingBox, float depth = 0) { + float[] floats = boundingBox.Vertices; + int floatCount = floats.Length; + + Bounds bounds = new Bounds(); + + bounds.center = new Vector3(floats[0], floats[1], 0); + for (int i = 2; i < floatCount; i += 2) { + bounds.Encapsulate(new Vector3(floats[i], floats[i + 1], 0)); + } + Vector3 size = bounds.size; + size.z = depth; + bounds.size = size; + + return bounds; + } public delegate void SkeletonUtilityDelegate ();