Эх сурвалжийг харах

Merge branch 'master' into dev

badlogic 9 жил өмнө
parent
commit
21de61a094
100 өөрчлөгдсөн 6404 нэмэгдсэн , 5881 устгасан
  1. 14 15
      LICENSE
  2. 4 0
      README.md
  3. BIN
      examples/alien/alien.spine
  4. 138 109
      examples/alien/export/alien.json
  5. BIN
      examples/alien/export/alien.skel
  6. 1 1
      examples/dragon/export/dragon.json
  7. BIN
      examples/dragon/export/dragon.skel
  8. 0 92
      examples/export/export.bat
  9. 107 0
      examples/export/export.sh
  10. 0 26
      examples/export/runtimes.bat
  11. 221 0
      examples/export/runtimes.sh
  12. 1 1
      examples/goblins/export/goblins-mesh.json
  13. BIN
      examples/goblins/export/goblins-mesh.skel
  14. 1 1
      examples/goblins/export/goblins.json
  15. BIN
      examples/goblins/export/goblins.skel
  16. 1 1
      examples/hero/export/hero-mesh.json
  17. BIN
      examples/hero/export/hero-mesh.skel
  18. 1 1
      examples/hero/export/hero.json
  19. BIN
      examples/hero/export/hero.skel
  20. 1 1
      examples/powerup/export/powerup.json
  21. BIN
      examples/powerup/export/powerup.skel
  22. 17 17
      examples/raptor/export/raptor.json
  23. BIN
      examples/raptor/export/raptor.skel
  24. 1 1
      examples/speedy/export/speedy.json
  25. BIN
      examples/speedy/export/speedy.skel
  26. 1 1
      examples/spineboy-old/export/spineboy-old.json
  27. BIN
      examples/spineboy-old/export/spineboy-old.skel
  28. 8 8
      examples/spineboy/export/spineboy-hover.json
  29. BIN
      examples/spineboy/export/spineboy-hover.skel
  30. 6 15
      examples/spineboy/export/spineboy-mesh.json
  31. BIN
      examples/spineboy/export/spineboy-mesh.skel
  32. 1 1
      examples/spineboy/export/spineboy.json
  33. BIN
      examples/spineboy/export/spineboy.skel
  34. 1 1
      examples/spinosaurus/export/spinosaurus.json
  35. BIN
      examples/spinosaurus/export/spinosaurus.skel
  36. 7 7
      examples/stretchyman/export/stretchyman.json
  37. BIN
      examples/stretchyman/export/stretchyman.skel
  38. 279 279
      examples/tank/export/tank.json
  39. BIN
      examples/tank/export/tank.skel
  40. BIN
      examples/tank/tank.spine
  41. 9 9
      examples/test/export/test-pma.atlas
  42. BIN
      examples/test/export/test-pma.png
  43. 20 0
      examples/test/export/test.atlas
  44. 278 0
      examples/test/export/test.json
  45. BIN
      examples/test/export/test.png
  46. BIN
      examples/test/export/test.skel
  47. BIN
      examples/test/images/logo.png
  48. BIN
      examples/test/images/spine.png
  49. BIN
      examples/test/test.spine
  50. 15 15
      examples/vine/export/vine.json
  51. BIN
      examples/vine/export/vine.skel
  52. BIN
      examples/vine/vine.spine
  53. 15 16
      spine-as3/LICENSE
  54. 1 1
      spine-as3/README.md
  55. BIN
      spine-as3/spine-as3-example/lib/spine-as3.swc
  56. 93 94
      spine-as3/spine-as3-example/src/spine/examples/Main.as
  57. 1 1
      spine-as3/spine-as3-example/src/spineboy.json
  58. 43 44
      spine-as3/spine-as3/src/spine/BlendMode.as
  59. 353 354
      spine-as3/spine-as3/src/spine/Bone.as
  60. 72 73
      spine-as3/spine-as3/src/spine/BoneData.as
  61. 52 53
      spine-as3/spine-as3/src/spine/Event.as
  62. 50 51
      spine-as3/spine-as3/src/spine/EventData.as
  63. 227 228
      spine-as3/spine-as3/src/spine/IkConstraint.as
  64. 51 52
      spine-as3/spine-as3/src/spine/IkConstraintData.as
  65. 49 50
      spine-as3/spine-as3/src/spine/MathUtils.as
  66. 416 417
      spine-as3/spine-as3/src/spine/PathConstraint.as
  67. 58 59
      spine-as3/spine-as3/src/spine/PathConstraintData.as
  68. 79 80
      spine-as3/spine-as3/src/spine/Polygon.as
  69. 35 36
      spine-as3/spine-as3/src/spine/PositionMode.as
  70. 36 37
      spine-as3/spine-as3/src/spine/RotateMode.as
  71. 445 441
      spine-as3/spine-as3/src/spine/Skeleton.as
  72. 149 150
      spine-as3/spine-as3/src/spine/SkeletonBounds.as
  73. 177 178
      spine-as3/spine-as3/src/spine/SkeletonData.as
  74. 734 734
      spine-as3/spine-as3/src/spine/SkeletonJson.as
  75. 90 91
      spine-as3/spine-as3/src/spine/Skin.as
  76. 103 104
      spine-as3/spine-as3/src/spine/Slot.as
  77. 67 68
      spine-as3/spine-as3/src/spine/SlotData.as
  78. 36 37
      spine-as3/spine-as3/src/spine/SpacingMode.as
  79. 129 130
      spine-as3/spine-as3/src/spine/TransformConstraint.as
  80. 63 64
      spine-as3/spine-as3/src/spine/TransformConstraintData.as
  81. 34 35
      spine-as3/spine-as3/src/spine/Updatable.as
  82. 130 131
      spine-as3/spine-as3/src/spine/animation/Animation.as
  83. 238 239
      spine-as3/spine-as3/src/spine/animation/AnimationState.as
  84. 65 66
      spine-as3/spine-as3/src/spine/animation/AnimationStateData.as
  85. 67 68
      spine-as3/spine-as3/src/spine/animation/AttachmentTimeline.as
  86. 99 100
      spine-as3/spine-as3/src/spine/animation/ColorTimeline.as
  87. 115 116
      spine-as3/spine-as3/src/spine/animation/CurveTimeline.as
  88. 102 103
      spine-as3/spine-as3/src/spine/animation/DeformTimeline.as
  89. 76 77
      spine-as3/spine-as3/src/spine/animation/DrawOrderTimeline.as
  90. 78 79
      spine-as3/spine-as3/src/spine/animation/EventTimeline.as
  91. 76 77
      spine-as3/spine-as3/src/spine/animation/IkConstraintTimeline.as
  92. 60 61
      spine-as3/spine-as3/src/spine/animation/Listeners.as
  93. 79 80
      spine-as3/spine-as3/src/spine/animation/PathConstraintMixTimeline.as
  94. 74 75
      spine-as3/spine-as3/src/spine/animation/PathConstraintPositionTimeline.as
  95. 58 59
      spine-as3/spine-as3/src/spine/animation/PathConstraintSpacingTimeline.as
  96. 89 90
      spine-as3/spine-as3/src/spine/animation/RotateTimeline.as
  97. 61 62
      spine-as3/spine-as3/src/spine/animation/ScaleTimeline.as
  98. 62 32
      spine-as3/spine-as3/src/spine/animation/ShearTimeline.as
  99. 37 38
      spine-as3/spine-as3/src/spine/animation/Timeline.as
  100. 47 48
      spine-as3/spine-as3/src/spine/animation/TrackEntry.as

+ 14 - 15
LICENSE

@@ -1,17 +1,16 @@
-Spine Runtimes Software License
-Version 2.4
+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 (the "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 otherwise create derivative works, improvements of
-the Software or develop new applications using the Software or (b) remove,
-delete, alter or obscure any trademarks or any copyright, trademark, patent
+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.
@@ -21,8 +20,8 @@ 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; LOSS OF USE, DATA, OR PROFITS;
-OR BUSINESS INTERRUPTION) 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.
+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.

+ 4 - 0
README.md

@@ -12,6 +12,10 @@ The Spine Runtimes are developed with the intent to be used with data exported f
 
 See the Spine [runtime documentation](http://esotericsoftware.com/spine-documentation#runtimesTitle) for documentation applicable to all runtimes. See each runtime's `README.md` for runtime specific documentation.
 
+## Bugs, enhancements, and tasks
+
+Review our backlog of bugs, enhancements, and tasks in the [spine-runtimes](https://github.com/EsotericSoftware/spine-runtimes/issues) and [spine-editor](https://github.com/EsotericSoftware/spine-editor/issues) issue trackers. However, you may find it more convenient to use the [spine-runtimes waffle](https://waffle.io/EsotericSoftware/spine-runtimes) and [spine-editor waffle](https://waffle.io/EsotericSoftware/spine-editor), which provide a nicer view of the same issue tracker information.
+
 ## Versioning
 
 The code provided here is continuously under development. Generally the latest Git `master` source works with the data exported from the latest version of Spine. The Spine version can be [frozen](http://esotericsoftware.com/spine-settings#Version) at a specific Spine version that matches the Spine Runtimes source being used. Occaisionally the Spine Runtimes are [tagged](https://github.com/EsotericSoftware/spine-runtimes/releases) to work with a specific Spine version.

BIN
examples/alien/alien.spine


+ 138 - 109
examples/alien/export/alien.json

@@ -1,12 +1,12 @@
 {
-"skeleton": { "hash": "V4Hi+nECzrockiU2TB2cDcvEn38", "spine": "3.4.00", "width": 365.8, "height": 429.96, "images": "./images/" },
+"skeleton": { "hash": "ojVnF+IXlzxTZnAzaREvaOo8Rdw", "spine": "3.4.02", "width": 365.79, "height": 391.47, "images": "./images/" },
 "bones": [
 	{ "name": "root" },
 	{ "name": "hip", "parent": "root", "x": -8.17, "y": 73.5, "color": "fff200ff" },
 	{ "name": "back_thigh", "parent": "hip", "length": 44.3, "rotation": -54.08, "x": -2.82, "y": -2.64, "color": "ff0008ff" },
 	{ "name": "back_shin", "parent": "back_thigh", "length": 31.17, "rotation": -50.15, "x": 44.3, "y": 0.06, "color": "ff0008ff" },
 	{ "name": "back_foot", "parent": "back_shin", "length": 11.75, "rotation": 91.8, "x": 31.17, "y": 0.09, "color": "ff0008ff" },
-	{ "name": "body", "parent": "hip", "length": 116.25, "rotation": 99.84, "x": -34.28, "y": 4.2, "color": "fff200ff" },
+	{ "name": "body", "parent": "hip", "length": 116.25, "rotation": 99.84, "x": -34.28, "y": 4.19, "color": "fff200ff" },
 	{ "name": "head", "parent": "body", "length": 213.84, "rotation": -36.34, "x": 116.32, "y": 1.79, "color": "fff200ff" },
 	{ "name": "blown_up_nck", "parent": "head", "x": -6.12, "y": -25.01, "color": "fff200ff" },
 	{ "name": "front_thigh", "parent": "hip", "length": 52.72, "rotation": -55.89, "x": -42.79, "y": 4.11, "color": "04ff00ff" },
@@ -26,13 +26,13 @@
 	{
 		"name": "lower_back_arm",
 		"parent": "upper_back_arm",
-		"length": 65.27,
+		"length": 65.26,
 		"rotation": 74.17,
 		"x": 50.28,
 		"y": -0.11,
 		"color": "ff0008ff"
 	},
-	{ "name": "metaljaw", "parent": "root", "length": 75.82, "rotation": -74.86, "x": -37.1, "y": 230.8, "color": "fff200ff" },
+	{ "name": "metaljaw", "parent": "root", "length": 75.82, "rotation": -74.86, "x": -37.09, "y": 230.8, "color": "fff200ff" },
 	{ "name": "splat", "parent": "root", "x": -11.57, "y": 253.52 }
 ],
 "slots": [
@@ -43,7 +43,7 @@
 	{ "name": "back_shin", "bone": "back_shin", "attachment": "back_shin" },
 	{ "name": "backarmor", "bone": "body", "attachment": "backarmor" },
 	{ "name": "blown_up_nck", "bone": "blown_up_nck" },
-	{ "name": "head", "bone": "head", "attachment": "burst01" },
+	{ "name": "head", "bone": "head", "attachment": "head" },
 	{ "name": "splat01", "bone": "splat" },
 	{ "name": "body", "bone": "body", "attachment": "body" },
 	{ "name": "front_thigh", "bone": "front_thigh", "attachment": "front_thigh" },
@@ -86,7 +86,7 @@
 			"front_thigh": { "x": 26.99, "y": 0.4, "rotation": 55.89, "width": 54, "height": 54 }
 		},
 		"front_upper_arm": {
-			"front_upper_arm": { "x": 35.92, "y": 6.58, "rotation": 174.62, "width": 113, "height": 55 }
+			"front_upper_arm": { "x": 35.91, "y": 6.58, "rotation": 174.62, "width": 113, "height": 55 }
 		},
 		"head": {
 			"burst01": { "x": 104.65, "y": -32.91, "rotation": -63.5, "width": 286, "height": 309 },
@@ -101,8 +101,8 @@
 		},
 		"splat01": {
 			"splat01": { "x": 77.57, "y": 167.97, "width": 514, "height": 503 },
-			"splat02": { "x": 69.07, "y": -3.02, "width": 734, "height": 511 },
-			"splat03": { "x": 14.57, "y": -102.52, "width": 723, "height": 339 }
+			"splat02": { "x": 43.42, "y": 106.44, "width": 734, "height": 511 },
+			"splat03": { "x": 14.57, "y": 119.84, "width": 723, "height": 339 }
 		},
 		"upper_back_arm": {
 			"upper_back_arm": { "x": 38.71, "y": 2.9, "rotation": 68.76, "width": 60, "height": 86 }
@@ -130,24 +130,32 @@
 			},
 			"splat01": {
 				"color": [
-					{ "time": 0.9333, "color": "ffffffff" },
+					{ "time": 1.0333, "color": "ffffffff" },
 					{
-						"time": 1.0333,
+						"time": 1.2,
 						"color": "ffffffbb",
-						"curve": [ 0.353, 0.02, 0.686, 0.37 ]
+						"curve": [ 0.498, 0, 0.753, 0.37 ]
 					},
-					{ "time": 1.1333, "color": "ffffff00" }
+					{ "time": 1.3333, "color": "ffffff00" }
 				],
 				"attachment": [
 					{ "time": 0, "name": null },
 					{ "time": 0.8333, "name": "splat01" },
-					{ "time": 0.9333, "name": "splat02" },
-					{ "time": 1.0333, "name": "splat03" },
-					{ "time": 1.1333, "name": null }
+					{ "time": 1.0333, "name": "splat02" },
+					{ "time": 1.2, "name": "splat03" },
+					{ "time": 1.3333, "name": null }
 				]
 			}
 		},
 		"bones": {
+			"blown_up_nck": {
+				"translate": [
+					{ "time": 0.9333, "x": 6.73, "y": 10.57 }
+				],
+				"scale": [
+					{ "time": 0.8333, "x": 0.684, "y": 0.503 }
+				]
+			},
 			"head": {
 				"rotate": [
 					{ "time": 0, "angle": 0 },
@@ -157,7 +165,7 @@
 				"translate": [
 					{ "time": 0, "x": 0, "y": 0, "curve": "stepped" },
 					{ "time": 0.0333, "x": 0, "y": 0 },
-					{ "time": 0.1, "x": -10.63, "y": -18.38 }
+					{ "time": 0.1, "x": -10.63, "y": -18.37 }
 				],
 				"scale": [
 					{ "time": 0, "x": 1, "y": 1 },
@@ -167,16 +175,66 @@
 					{ "time": 0.8333, "x": 1.461, "y": 1.987 }
 				]
 			},
+			"splat": {
+				"rotate": [
+					{ "time": 0, "angle": -6.77 },
+					{
+						"time": 0.8333,
+						"angle": -9.39,
+						"curve": [ 0.232, 0.6, 0.67, 0.88 ]
+					},
+					{
+						"time": 1.1,
+						"angle": 12.41,
+						"curve": [ 0.227, 0.04, 0.687, 0.42 ]
+					},
+					{ "time": 1.3333, "angle": -3.34 }
+				],
+				"translate": [
+					{ "time": 0, "x": 0, "y": -40.5 },
+					{ "time": 0.8333, "x": -13.63, "y": -23.39 },
+					{
+						"time": 1.0333,
+						"x": -84.44,
+						"y": 2.75,
+						"curve": [ 0.309, 0.61, 0.75, 1 ]
+					},
+					{
+						"time": 1.2333,
+						"x": -144.96,
+						"y": 135.8,
+						"curve": [ 0.25, 0, 0.725, 0.48 ]
+					},
+					{ "time": 1.3333, "x": -220.9, "y": -323.14 }
+				],
+				"scale": [
+					{ "time": 0, "x": 1.113, "y": 1.113 },
+					{
+						"time": 0.8333,
+						"x": 1,
+						"y": 1,
+						"curve": [ 0.212, 0.35, 0.681, 0.84 ]
+					},
+					{
+						"time": 1.0333,
+						"x": 1.216,
+						"y": 1.555,
+						"curve": [ 0.374, 0.64, 0.713, 1 ]
+					},
+					{ "time": 1.2, "x": 1.768, "y": 1.374 },
+					{ "time": 1.3333, "x": 1.77, "y": 0.94 }
+				]
+			},
 			"hip": {
 				"rotate": [
 					{ "time": 0, "angle": 0 }
 				],
 				"translate": [
 					{ "time": 0, "x": 0, "y": 0 },
-					{ "time": 0.1333, "x": 0, "y": -9.23, "curve": "stepped" },
-					{ "time": 0.9333, "x": 0, "y": -9.23 },
+					{ "time": 0.1333, "x": 0, "y": -9.22, "curve": "stepped" },
+					{ "time": 0.9333, "x": 0, "y": -9.22 },
 					{ "time": 1.0333, "x": -20.27, "y": -19.1 },
-					{ "time": 1.1666, "x": -39.1, "y": -19.1 }
+					{ "time": 1.1666, "x": -39.09, "y": -19.1 }
 				],
 				"scale": [
 					{ "time": 0, "x": 1, "y": 1 }
@@ -207,7 +265,7 @@
 					},
 					{ "time": 0.8333, "angle": 10.74 },
 					{ "time": 1.0333, "angle": 30.29 },
-					{ "time": 1.1666, "angle": 74.27 }
+					{ "time": 1.1666, "angle": 74.26 }
 				],
 				"translate": [
 					{ "time": 0, "x": 0, "y": 0 }
@@ -388,7 +446,7 @@
 					},
 					{
 						"time": 0.9,
-						"angle": -39.1,
+						"angle": -39.09,
 						"curve": [ 0.476, 0.47, 0.829, 0.81 ]
 					},
 					{ "time": 0.9333, "angle": -44.9 },
@@ -516,44 +574,15 @@
 					{
 						"time": 1.7666,
 						"x": -89.22,
-						"y": -149.43,
+						"y": -149.42,
 						"curve": [ 0.432, 0, 0.75, 1 ]
 					},
-					{ "time": 1.8666, "x": -78.33, "y": -135.43 }
+					{ "time": 1.8666, "x": -78.33, "y": -135.42 }
 				],
 				"scale": [
 					{ "time": 0, "x": 1, "y": 1 }
 				]
 			},
-			"splat": {
-				"rotate": [
-					{ "time": 0, "angle": -6.77 },
-					{ "time": 0.8333, "angle": -9.4 },
-					{ "time": 1.0333, "angle": 0 }
-				],
-				"translate": [
-					{ "time": 0, "x": 0, "y": -40.51 },
-					{ "time": 0.8333, "x": -13.63, "y": -32.56 },
-					{ "time": 0.9333, "x": -30.67, "y": -20.06 },
-					{ "time": 1.0333, "x": -75.55, "y": 85.08 },
-					{ "time": 1.1333, "x": -75.55, "y": -8.8 }
-				],
-				"scale": [
-					{ "time": 0, "x": 1.113, "y": 1.113 },
-					{ "time": 0.8333, "x": 1, "y": 1 },
-					{ "time": 0.9333, "x": 1.229, "y": 1.229 },
-					{ "time": 1.0333, "x": 1.37, "y": 1.37 },
-					{ "time": 1.1333, "x": 1.37, "y": 0.94 }
-				]
-			},
-			"blown_up_nck": {
-				"translate": [
-					{ "time": 0.9333, "x": 6.73, "y": 10.57 }
-				],
-				"scale": [
-					{ "time": 0.8333, "x": 0.684, "y": 0.503 }
-				]
-			},
 			"root": {
 				"rotate": [
 					{ "time": 0, "angle": 0 }
@@ -605,6 +634,28 @@
 			}
 		},
 		"bones": {
+			"blown_up_nck": {
+				"rotate": [
+					{ "time": 0, "angle": 0 }
+				],
+				"translate": [
+					{ "time": 0, "x": 0, "y": 0 }
+				],
+				"scale": [
+					{ "time": 0, "x": 1, "y": 1 }
+				]
+			},
+			"splat": {
+				"rotate": [
+					{ "time": 0, "angle": 0 }
+				],
+				"translate": [
+					{ "time": 0, "x": 0, "y": 0 }
+				],
+				"scale": [
+					{ "time": 0, "x": 1, "y": 1 }
+				]
+			},
 			"root": {
 				"rotate": [
 					{ "time": 0, "angle": 0 }
@@ -623,7 +674,7 @@
 				],
 				"translate": [
 					{ "time": 0, "x": -17.33, "y": 19.69 },
-					{ "time": 0.3333, "x": -2.36, "y": 6.3 }
+					{ "time": 0.3333, "x": -2.35, "y": 6.3 }
 				],
 				"scale": [
 					{ "time": 0, "x": 1, "y": 1 }
@@ -642,24 +693,13 @@
 					{ "time": 0, "x": 1, "y": 1 }
 				]
 			},
-			"splat": {
-				"rotate": [
-					{ "time": 0, "angle": 0 }
-				],
-				"translate": [
-					{ "time": 0, "x": 0, "y": 0 }
-				],
-				"scale": [
-					{ "time": 0, "x": 1, "y": 1 }
-				]
-			},
 			"back_thigh": {
 				"rotate": [
 					{ "time": 0, "angle": 71.89 },
 					{ "time": 0.3333, "angle": 7.6 }
 				],
 				"translate": [
-					{ "time": 0, "x": -18.91, "y": 2.36 },
+					{ "time": 0, "x": -18.91, "y": 2.35 },
 					{ "time": 0.3333, "x": 0, "y": 0 }
 				],
 				"scale": [
@@ -763,17 +803,6 @@
 					{ "time": 0, "x": 1, "y": 1 }
 				]
 			},
-			"blown_up_nck": {
-				"rotate": [
-					{ "time": 0, "angle": 0 }
-				],
-				"translate": [
-					{ "time": 0, "x": 0, "y": 0 }
-				],
-				"scale": [
-					{ "time": 0, "x": 1, "y": 1 }
-				]
-			},
 			"front_foot": {
 				"rotate": [
 					{ "time": 0, "angle": 0 },
@@ -824,10 +853,21 @@
 			}
 		},
 		"bones": {
+			"blown_up_nck": {
+				"rotate": [
+					{ "time": 0, "angle": 0 }
+				],
+				"translate": [
+					{ "time": 0, "x": 0, "y": 0 }
+				],
+				"scale": [
+					{ "time": 0, "x": 1, "y": 1 }
+				]
+			},
 			"front_thigh": {
 				"rotate": [
 					{ "time": 0, "angle": 26.18 },
-					{ "time": 0.1, "angle": -77.7 },
+					{ "time": 0.1, "angle": -77.69 },
 					{ "time": 0.2333, "angle": -99.82 },
 					{ "time": 0.4, "angle": -96.94 },
 					{ "time": 0.4333, "angle": -99.54 },
@@ -849,7 +889,7 @@
 					{ "time": 0.4, "angle": 45.02 },
 					{ "time": 0.4333, "angle": 45.34 },
 					{ "time": 0.5, "angle": -20.45 },
-					{ "time": 0.6666, "angle": -38.85 }
+					{ "time": 0.6666, "angle": -38.84 }
 				],
 				"translate": [
 					{ "time": 0, "x": 0, "y": 0 }
@@ -886,7 +926,7 @@
 				"translate": [
 					{ "time": 0, "x": 0, "y": -13.1 },
 					{ "time": 0.0666, "x": 0, "y": 12.04 },
-					{ "time": 0.1, "x": 0, "y": -2.1 },
+					{ "time": 0.1, "x": 0, "y": -2.09 },
 					{ "time": 0.1666, "x": 0, "y": 7.95 },
 					{ "time": 0.4333, "x": -71.74, "y": -9.07 },
 					{ "time": 0.5, "x": 0, "y": -2.89, "curve": "stepped" },
@@ -901,7 +941,7 @@
 					{ "time": 0, "angle": 28.25 },
 					{ "time": 0.1, "angle": 5.51 },
 					{ "time": 0.2333, "angle": -1.94 },
-					{ "time": 0.4333, "angle": -9.19 },
+					{ "time": 0.4333, "angle": -9.18 },
 					{ "time": 0.5, "angle": 21.79 },
 					{ "time": 0.6666, "angle": 26.9 }
 				],
@@ -911,7 +951,7 @@
 					{ "time": 0.2333, "x": 31.77, "y": 9.62 },
 					{ "time": 0.4333, "x": 61.21, "y": -63.32 },
 					{ "time": 0.5, "x": 109.6, "y": -49.68 },
-					{ "time": 0.6666, "x": 39.09, "y": 4.74 }
+					{ "time": 0.6666, "x": 39.09, "y": 4.73 }
 				],
 				"scale": [
 					{ "time": 0, "x": 1, "y": 1 },
@@ -938,7 +978,7 @@
 				"rotate": [
 					{ "time": 0, "angle": -11.37 },
 					{ "time": 0.1, "angle": -287.29 },
-					{ "time": 0.2333, "angle": -268.61 },
+					{ "time": 0.2333, "angle": -268.6 },
 					{ "time": 0.4333, "angle": 4.09 },
 					{ "time": 0.5, "angle": 6.27 },
 					{ "time": 0.6666, "angle": 12.39 }
@@ -955,7 +995,7 @@
 					{ "time": 0, "angle": 9.75 },
 					{ "time": 0.2333, "angle": -22.81 },
 					{ "time": 0.4333, "angle": -72.32 },
-					{ "time": 0.5, "angle": -72.27 },
+					{ "time": 0.5, "angle": -72.26 },
 					{ "time": 0.6666, "angle": 3.89 }
 				],
 				"translate": [
@@ -969,7 +1009,7 @@
 				"rotate": [
 					{ "time": 0, "angle": -339.16 },
 					{ "time": 0.1, "angle": -79.86 },
-					{ "time": 0.2333, "angle": -291.77 },
+					{ "time": 0.2333, "angle": -291.76 },
 					{ "time": 0.5, "angle": -71.4 },
 					{ "time": 0.6666, "angle": -341.82 }
 				],
@@ -1044,8 +1084,8 @@
 					{ "time": 0, "x": 0, "y": 0 },
 					{ "time": 0.2333, "x": 16.33, "y": -5.62 },
 					{ "time": 0.4333, "x": 21.99, "y": -5.09 },
-					{ "time": 0.5, "x": 35.17, "y": -16.94, "curve": "stepped" },
-					{ "time": 0.6666, "x": 35.17, "y": -16.94 }
+					{ "time": 0.5, "x": 35.16, "y": -16.94, "curve": "stepped" },
+					{ "time": 0.6666, "x": 35.16, "y": -16.94 }
 				],
 				"scale": [
 					{ "time": 0, "x": 1, "y": 1 },
@@ -1068,17 +1108,6 @@
 					{ "time": 0, "x": 1, "y": 1 }
 				]
 			},
-			"blown_up_nck": {
-				"rotate": [
-					{ "time": 0, "angle": 0 }
-				],
-				"translate": [
-					{ "time": 0, "x": 0, "y": 0 }
-				],
-				"scale": [
-					{ "time": 0, "x": 1, "y": 1 }
-				]
-			},
 			"front_foot": {
 				"rotate": [
 					{ "time": 0, "angle": 0 },
@@ -1105,6 +1134,11 @@
 			}
 		},
 		"bones": {
+			"blown_up_nck": {
+				"scale": [
+					{ "time": 0, "x": 1, "y": 1 }
+				]
+			},
 			"front_shin": {
 				"rotate": [
 					{ "time": 0, "angle": 46.48 },
@@ -1136,12 +1170,12 @@
 					{ "time": 0.1, "angle": 8.31 },
 					{ "time": 0.1333, "angle": 29.38 },
 					{ "time": 0.1666, "angle": 15.43 },
-					{ "time": 0.2, "angle": 2.12 },
+					{ "time": 0.2, "angle": 2.11 },
 					{ "time": 0.2333, "angle": -0.97 },
-					{ "time": 0.2666, "angle": -38.85 },
+					{ "time": 0.2666, "angle": -38.84 },
 					{ "time": 0.3, "angle": -63.94 },
 					{ "time": 0.3333, "angle": -88.2 },
-					{ "time": 0.3666, "angle": -76.84 },
+					{ "time": 0.3666, "angle": -76.83 },
 					{ "time": 0.4, "angle": -86.45 }
 				],
 				"translate": [
@@ -1186,7 +1220,7 @@
 					{ "time": 0.1, "angle": 1.28 },
 					{ "time": 0.2, "angle": -7.86 },
 					{ "time": 0.2333, "angle": 18.54 },
-					{ "time": 0.2666, "angle": 16.13 },
+					{ "time": 0.2666, "angle": 16.12 },
 					{ "time": 0.3, "angle": -33.84 },
 					{ "time": 0.3333, "angle": -15.97 },
 					{ "time": 0.4, "angle": -22.78 }
@@ -1317,7 +1351,7 @@
 					{ "time": 0, "angle": 0 },
 					{ "time": 0.0333, "angle": 11.49 },
 					{ "time": 0.0666, "angle": -39.11 },
-					{ "time": 0.1, "angle": -67.88 },
+					{ "time": 0.1, "angle": -67.87 },
 					{ "time": 0.1333, "angle": -87.79 },
 					{ "time": 0.1666, "angle": -74.85 },
 					{ "time": 0.2, "angle": -54.57 },
@@ -1359,7 +1393,7 @@
 					},
 					{
 						"time": 0.2,
-						"angle": 4.2,
+						"angle": 4.19,
 						"curve": [ 0.337, 0.34, 0.675, 0.69 ]
 					},
 					{
@@ -1442,7 +1476,7 @@
 					},
 					{
 						"time": 0.2,
-						"angle": 4.2,
+						"angle": 4.19,
 						"curve": [ 0.337, 0.34, 0.675, 0.69 ]
 					},
 					{
@@ -1485,11 +1519,6 @@
 					{ "time": 0.4, "x": 1, "y": 1 }
 				]
 			},
-			"blown_up_nck": {
-				"scale": [
-					{ "time": 0, "x": 1, "y": 1 }
-				]
-			},
 			"splat": {
 				"scale": [
 					{ "time": 0, "x": 1, "y": 1 }

BIN
examples/alien/export/alien.skel


+ 1 - 1
examples/dragon/export/dragon.json

@@ -1,5 +1,5 @@
 {
-"skeleton": { "hash": "9MKo2cmJTDc3IPV4B3LRJxWbl04", "spine": "3.4.00", "width": 897, "height": 716.36, "images": "./images/" },
+"skeleton": { "hash": "9MKo2cmJTDc3IPV4B3LRJxWbl04", "spine": "3.4.02", "width": 897, "height": 716.36, "images": "./images/" },
 "bones": [
 	{ "name": "root", "y": -176.12 },
 	{ "name": "COG", "parent": "root", "y": 176.12 },

BIN
examples/dragon/export/dragon.skel


+ 0 - 92
examples/export/export.bat

@@ -1,92 +0,0 @@
-@echo off
-
-echo Cleaning...
-del /q ..\alien\export\*
-del /q ..\dragon\export\*
-del /q ..\goblins\export\*
-del /q ..\hero\export\*
-del /q ..\powerup\export\*
-del /q ..\speedy\export\*
-del /q ..\spineboy\export\*
-del /q ..\spineboy-old\export\*
-del /q ..\spinosaurus\export\*
-del /q ..\stretchyman\export\*
-del /q ..\raptor\export\*
-del /q ..\tank\export\*
-del /q ..\vine\export\*
-
-echo.
-echo Exporting...
-"C:\Program Files (x86)\Spine\Spine.com" ^
--i ../alien/alien.spine -o ../alien/export -e json.json ^
--i ../alien/alien.spine -o ../alien/export -e binary.json ^
--i ../alien/images -o ../alien/export -n alien -p atlas-0.5.json ^
--i ../alien/images -o ../alien/export -n alien-pma -p atlas-0.5-pma.json ^
-
--i ../dragon/dragon.spine -o ../dragon/export -e json.json ^
--i ../dragon/dragon.spine -o ../dragon/export -e binary.json ^
--i ../dragon/images -o ../dragon/export -n dragon -p atlas-1.0.json ^
--i ../dragon/images -o ../dragon/export -n dragon-pma -p atlas-1.0-pma.json ^
-
--i ../goblins/goblins.spine -o ../goblins/export -e json.json ^
--i ../goblins/goblins.spine -o ../goblins/export -e binary.json ^
--i ../goblins/goblins-mesh.spine -o ../goblins/export -e json.json ^
--i ../goblins/goblins-mesh.spine -o ../goblins/export -e binary.json ^
--i ../goblins/images -o ../goblins/export -n goblins -p atlas-1.0.json ^
--i ../goblins/images -o ../goblins/export -n goblins-pma -p atlas-1.0-pma.json ^
-
--i ../hero/hero.spine -o ../hero/export -e json.json ^
--i ../hero/hero.spine -o ../hero/export -e binary.json ^
--i ../hero/hero-mesh.spine -o ../hero/export -e json.json ^
--i ../hero/hero-mesh.spine -o ../hero/export -e binary.json ^
--i ../hero/images -o ../hero/export -n hero -p atlas-1.0.json ^
--i ../hero/images -o ../hero/export -n hero-pma -p atlas-1.0-pma.json ^
-
--i ../powerup/powerup.spine -o ../powerup/export -e json.json ^
--i ../powerup/powerup.spine -o ../powerup/export -e binary.json ^
--i ../powerup/images -o ../powerup/export -n powerup -p atlas-1.0.json ^
--i ../powerup/images -o ../powerup/export -n powerup-pma -p atlas-1.0-pma.json ^
-
--i ../speedy/speedy.spine -o ../speedy/export -e json.json ^
--i ../speedy/speedy.spine -o ../speedy/export -e binary.json ^
--i ../speedy/images -o ../speedy/export -n speedy -p atlas-1.0.json ^
--i ../speedy/images -o ../speedy/export -n speedy-pma -p atlas-1.0-pma.json ^
-
--i ../spineboy/spineboy.spine -o ../spineboy/export -e json.json ^
--i ../spineboy/spineboy.spine -o ../spineboy/export -e binary.json ^
--i ../spineboy/spineboy-mesh.spine -o ../spineboy/export -e json.json ^
--i ../spineboy/spineboy-mesh.spine -o ../spineboy/export -e binary.json ^
--i ../spineboy/images -o ../spineboy/export -n spineboy -p atlas-1.0.json ^
--i ../spineboy/images -o ../spineboy/export -n spineboy-pma -p atlas-1.0-pma.json ^
-
--i ../spineboy-old/spineboy-old.spine -o ../spineboy-old/export -e json.json ^
--i ../spineboy-old/spineboy-old.spine -o ../spineboy-old/export -e binary.json ^
--i ../spineboy-old/images -o ../spineboy-old/export -n spineboy-old -p atlas-1.0.json ^
--i ../spineboy-old/images -o ../spineboy-old/export -n spineboy-old-pma -p atlas-1.0-pma.json ^
--i ../spineboy-old/normal -o ../spineboy-old/export -n spineboy-old-normal -p atlas-1.0.json ^
--i ../spineboy-old/diffuse -o ../spineboy-old/export -n spineboy-old-diffuse -p atlas-1.0.json ^
-
--i ../spinosaurus/spinosaurus.spine -o ../spinosaurus/export -e json.json ^
--i ../spinosaurus/spinosaurus.spine -o ../spinosaurus/export -e binary.json ^
-
--i ../stretchyman/stretchyman.spine -o ../stretchyman/export -e json.json ^
--i ../stretchyman/stretchyman.spine -o ../stretchyman/export -e binary.json ^
--i ../stretchyman/images -o ../stretchyman/export -n stretchyman -p atlas-1.0.json ^
--i ../stretchyman/images -o ../stretchyman/export -n stretchyman-pma -p atlas-1.0-pma.json ^
-
--i ../raptor/raptor.spine -o ../raptor/export -e json.json ^
--i ../raptor/raptor.spine -o ../raptor/export -e binary.json ^
--i ../raptor/images -o ../raptor/export -n raptor -p atlas-0.5.json ^
--i ../raptor/images -o ../raptor/export -n raptor-pma -p atlas-0.5-pma.json ^
-
--i ../tank/tank.spine -o ../tank/export -e json.json ^
--i ../tank/tank.spine -o ../tank/export -e binary.json ^
--i ../tank/images -o ../tank/export -n tank -p atlas-0.5.json ^
--i ../tank/images -o ../tank/export -n tank-pma -p atlas-0.5-pma.json ^
-
--i ../vine/vine.spine -o ../vine/export -e json.json ^
--i ../vine/vine.spine -o ../vine/export -e binary.json ^
--i ../vine/images -o ../vine/export -n vine -p atlas-1.0.json ^
--i ../vine/images -o ../vine/export -n vine-pma -p atlas-1.0-pma.json
-
-del /q ..\spineboy-old\export\*-normal.atlas

+ 107 - 0
examples/export/export.sh

@@ -0,0 +1,107 @@
+#!/bin/sh
+set -e
+
+SPINE_EXE="C:/Program Files (x86)/Spine/Spine.com"
+PLATFORM=`uname`
+echo $PLATFORM
+if [[ $PLATFORM == "Darwin" ]]; then
+	SPINE_EXE="/Applications/Spine/Spine.app/Contents/MacOS/Spine"
+fi
+echo "Spine exe: $SPINE_EXE"
+
+echo "Cleaning..."
+rm -rf ../alien/export/*
+rm -rf ../dragon/export/*
+rm -rf ../goblins/export/*
+rm -rf ../hero/export/*
+rm -rf ../powerup/export/*
+rm -rf ../speedy/export/*
+rm -rf ../spineboy/export/*
+rm -rf ../spineboy-old/export/*
+rm -rf ../spinosaurus/export/*
+rm -rf ../stretchyman/export/*
+rm -rf ../raptor/export/*
+rm -rf ../tank/export/*
+rm -rf ../vine/export/*
+rm -rf ../test/export/*
+
+echo ""
+echo "Exporting..."
+"$SPINE_EXE" \
+-i ../alien/alien.spine -o ../alien/export -e json.json \
+-i ../alien/alien.spine -o ../alien/export -e binary.json \
+-i ../alien/images -o ../alien/export -n alien -p atlas-0.5.json \
+-i ../alien/images -o ../alien/export -n alien-pma -p atlas-0.5-pma.json \
+\
+-i ../dragon/dragon.spine -o ../dragon/export -e json.json \
+-i ../dragon/dragon.spine -o ../dragon/export -e binary.json \
+-i ../dragon/images -o ../dragon/export -n dragon -p atlas-1.0.json \
+-i ../dragon/images -o ../dragon/export -n dragon-pma -p atlas-1.0-pma.json \
+\
+-i ../goblins/goblins.spine -o ../goblins/export -e json.json \
+-i ../goblins/goblins.spine -o ../goblins/export -e binary.json \
+-i ../goblins/goblins-mesh.spine -o ../goblins/export -e json.json \
+-i ../goblins/goblins-mesh.spine -o ../goblins/export -e binary.json \
+-i ../goblins/images -o ../goblins/export -n goblins -p atlas-1.0.json \
+-i ../goblins/images -o ../goblins/export -n goblins-pma -p atlas-1.0-pma.json \
+\
+-i ../hero/hero.spine -o ../hero/export -e json.json \
+-i ../hero/hero.spine -o ../hero/export -e binary.json \
+-i ../hero/hero-mesh.spine -o ../hero/export -e json.json \
+-i ../hero/hero-mesh.spine -o ../hero/export -e binary.json \
+-i ../hero/images -o ../hero/export -n hero -p atlas-1.0.json \
+-i ../hero/images -o ../hero/export -n hero-pma -p atlas-1.0-pma.json \
+\
+-i ../powerup/powerup.spine -o ../powerup/export -e json.json \
+-i ../powerup/powerup.spine -o ../powerup/export -e binary.json \
+-i ../powerup/images -o ../powerup/export -n powerup -p atlas-1.0.json \
+-i ../powerup/images -o ../powerup/export -n powerup-pma -p atlas-1.0-pma.json \
+\
+-i ../speedy/speedy.spine -o ../speedy/export -e json.json \
+-i ../speedy/speedy.spine -o ../speedy/export -e binary.json \
+-i ../speedy/images -o ../speedy/export -n speedy -p atlas-1.0.json \
+-i ../speedy/images -o ../speedy/export -n speedy-pma -p atlas-1.0-pma.json \
+\
+-i ../spineboy/spineboy.spine -o ../spineboy/export -e json.json \
+-i ../spineboy/spineboy.spine -o ../spineboy/export -e binary.json \
+-i ../spineboy/spineboy-mesh.spine -o ../spineboy/export -e json.json \
+-i ../spineboy/spineboy-mesh.spine -o ../spineboy/export -e binary.json \
+-i ../spineboy/images -o ../spineboy/export -n spineboy -p atlas-1.0.json \
+-i ../spineboy/images -o ../spineboy/export -n spineboy-pma -p atlas-1.0-pma.json \
+\
+-i ../spineboy-old/spineboy-old.spine -o ../spineboy-old/export -e json.json \
+-i ../spineboy-old/spineboy-old.spine -o ../spineboy-old/export -e binary.json \
+-i ../spineboy-old/images -o ../spineboy-old/export -n spineboy-old -p atlas-1.0.json \
+-i ../spineboy-old/images -o ../spineboy-old/export -n spineboy-old-pma -p atlas-1.0-pma.json \
+-i ../spineboy-old/normal -o ../spineboy-old/export -n spineboy-old-normal -p atlas-1.0.json \
+-i ../spineboy-old/diffuse -o ../spineboy-old/export -n spineboy-old-diffuse -p atlas-1.0.json \
+\
+-i ../spinosaurus/spinosaurus.spine -o ../spinosaurus/export -e json.json \
+-i ../spinosaurus/spinosaurus.spine -o ../spinosaurus/export -e binary.json \
+\
+-i ../stretchyman/stretchyman.spine -o ../stretchyman/export -e json.json \
+-i ../stretchyman/stretchyman.spine -o ../stretchyman/export -e binary.json \
+-i ../stretchyman/images -o ../stretchyman/export -n stretchyman -p atlas-1.0.json \
+-i ../stretchyman/images -o ../stretchyman/export -n stretchyman-pma -p atlas-1.0-pma.json \
+\
+-i ../raptor/raptor.spine -o ../raptor/export -e json.json \
+-i ../raptor/raptor.spine -o ../raptor/export -e binary.json \
+-i ../raptor/images -o ../raptor/export -n raptor -p atlas-0.5.json \
+-i ../raptor/images -o ../raptor/export -n raptor-pma -p atlas-0.5-pma.json \
+\
+-i ../tank/tank.spine -o ../tank/export -e json.json \
+-i ../tank/tank.spine -o ../tank/export -e binary.json \
+-i ../tank/images -o ../tank/export -n tank -p atlas-0.5.json \
+-i ../tank/images -o ../tank/export -n tank-pma -p atlas-0.5-pma.json \
+\
+-i ../test/test.spine -o ../test/export -e json.json \
+-i ../test/test.spine -o ../test/export -e binary.json \
+-i ../test/images -o ../test/export -n test -p atlas-0.5.json \
+-i ../test/images -o ../test/export -n test-pma -p atlas-0.5-pma.json \
+\
+-i ../vine/vine.spine -o ../vine/export -e json.json \
+-i ../vine/vine.spine -o ../vine/export -e binary.json \
+-i ../vine/images -o ../vine/export -n vine -p atlas-1.0.json \
+-i ../vine/images -o ../vine/export -n vine-pma -p atlas-1.0-pma.json
+
+rm -rf ../spineboy-old/export/*-normal.atlas

+ 0 - 26
examples/export/runtimes.bat

@@ -1,26 +0,0 @@
-@echo off
-echo Copying to runtimes...
-
-echo.
-echo. spine-libgdx
-del /q ..\..\spine-libgdx\spine-libgdx-tests\assets\goblins\*
-copy /Y ..\goblins\export\*.json ..\..\spine-libgdx\spine-libgdx-tests\assets\goblins\
-copy /Y ..\goblins\export\*.skel ..\..\spine-libgdx\spine-libgdx-tests\assets\goblins\
-copy /Y ..\goblins\export\*-pma.* ..\..\spine-libgdx\spine-libgdx-tests\assets\goblins\
-
-del /q ..\..\spine-libgdx\spine-libgdx-tests\assets\raptor\*
-copy /Y ..\raptor\export\*.json ..\..\spine-libgdx\spine-libgdx-tests\assets\raptor\
-copy /Y ..\raptor\export\*.skel ..\..\spine-libgdx\spine-libgdx-tests\assets\raptor\
-copy /Y ..\raptor\export\*-pma.* ..\..\spine-libgdx\spine-libgdx-tests\assets\raptor\
-
-del /q ..\..\spine-libgdx\spine-libgdx-tests\assets\spineboy\*
-copy /Y ..\spineboy\export\*.json ..\..\spine-libgdx\spine-libgdx-tests\assets\spineboy\
-copy /Y ..\spineboy\export\*.skel ..\..\spine-libgdx\spine-libgdx-tests\assets\spineboy\
-copy /Y ..\spineboy\export\*-pma.* ..\..\spine-libgdx\spine-libgdx-tests\assets\spineboy\
-
-del /q ..\..\spine-libgdx\spine-libgdx-tests\assets\spineboy-old\*
-copy /Y ..\spineboy-old\export\*.json ..\..\spine-libgdx\spine-libgdx-tests\assets\spineboy-old\
-copy /Y ..\spineboy-old\export\*.skel ..\..\spine-libgdx\spine-libgdx-tests\assets\spineboy-old\
-copy /Y ..\spineboy-old\export\*-pma.* ..\..\spine-libgdx\spine-libgdx-tests\assets\spineboy-old\
-copy /Y ..\spineboy-old\export\*-diffuse.* ..\..\spine-libgdx\spine-libgdx-tests\assets\spineboy-old\
-copy /Y ..\spineboy-old\export\*-normal.* ..\..\spine-libgdx\spine-libgdx-tests\assets\spineboy-old\

+ 221 - 0
examples/export/runtimes.sh

@@ -0,0 +1,221 @@
+#!/bin/sh
+set -e
+echo "Copying assets to runtimes..."
+
+echo ""
+echo "spine-libgdx"
+rm -rf ../../spine-libgdx/spine-libgdx-tests/assets/goblins/*
+cp -f ../goblins/export/*.json ../../spine-libgdx/spine-libgdx-tests/assets/goblins/
+cp -f ../goblins/export/*.skel ../../spine-libgdx/spine-libgdx-tests/assets/goblins/
+cp -f ../goblins/export/*-pma.* ../../spine-libgdx/spine-libgdx-tests/assets/goblins/
+
+rm -rf ../../spine-libgdx/spine-libgdx-tests/assets/raptor/*
+cp -f ../raptor/export/*.json ../../spine-libgdx/spine-libgdx-tests/assets/raptor/
+cp -f ../raptor/export/*.skel ../../spine-libgdx/spine-libgdx-tests/assets/raptor/
+cp -f ../raptor/export/*-pma.* ../../spine-libgdx/spine-libgdx-tests/assets/raptor/
+
+rm -rf ../../spine-libgdx/spine-libgdx-tests/assets/spineboy/*
+cp -f ../spineboy/export/*.json ../../spine-libgdx/spine-libgdx-tests/assets/spineboy/
+cp -r ../spineboy/export/*.skel ../../spine-libgdx/spine-libgdx-tests/assets/spineboy/
+cp -r ../spineboy/export/*-pma.* ../../spine-libgdx/spine-libgdx-tests/assets/spineboy/
+
+rm -rf ../../spine-libgdx/spine-libgdx-tests/assets/spineboy-old/*
+cp -f ../spineboy-old/export/*.json ../../spine-libgdx/spine-libgdx-tests/assets/spineboy-old/
+cp -f ../spineboy-old/export/*.skel ../../spine-libgdx/spine-libgdx-tests/assets/spineboy-old/
+cp -f ../spineboy-old/export/*-pma.* ../../spine-libgdx/spine-libgdx-tests/assets/spineboy-old/
+cp -f ../spineboy-old/export/*-diffuse.* ../../spine-libgdx/spine-libgdx-tests/assets/spineboy-old/
+cp -f ../spineboy-old/export/*-normal.* ../../spine-libgdx/spine-libgdx-tests/assets/spineboy-old/
+
+echo "spine-as3"
+rm -f ../../spine-as3/spine-as3-example/src/spineboy.*
+cp -f ../spineboy/export/spineboy.json ../../spine-as3/spine-as3-example/src/
+cp -f ../spineboy/export/spineboy.atlas ../../spine-as3/spine-as3-example/src/
+cp -f ../spineboy/export/spineboy.png ../../spine-as3/spine-as3-example/src/
+
+echo "spine-cocos2d-objc"
+rm -f ../../spine-cocos2d-objc/Resources/*
+cp -f ../goblins/export/goblins-mesh.json ../../spine-cocos2d-objc/Resources/
+cp -f ../goblins/export/goblins.atlas ../../spine-cocos2d-objc/Resources/
+cp -f ../goblins/export/goblins.png ../../spine-cocos2d-objc/Resources/
+
+cp -f ../raptor/export/raptor.json ../../spine-cocos2d-objc/Resources/
+cp -f ../raptor/export/raptor.atlas ../../spine-cocos2d-objc/Resources/
+cp -f ../raptor/export/raptor.png ../../spine-cocos2d-objc/Resources/
+
+cp -f ../spineboy/export/spineboy.json ../../spine-cocos2d-objc/Resources/
+cp -f ../spineboy/export/spineboy.atlas ../../spine-cocos2d-objc/Resources/
+cp -f ../spineboy/export/spineboy.png ../../spine-cocos2d-objc/Resources/
+
+cp -f ../tank/export/tank.json ../../spine-cocos2d-objc/Resources/
+cp -f ../tank/export/tank.atlas ../../spine-cocos2d-objc/Resources/
+cp -f ../tank/export/tank.png ../../spine-cocos2d-objc/Resources/
+
+echo "spine-cocos2dx"
+rm -f ../../spine-cocos2dx/example/Resources/common/*
+cp -f ../goblins/export/goblins-mesh.json ../../spine-cocos2dx/example/Resources/common/
+cp -f ../goblins/export/goblins.atlas ../../spine-cocos2dx/example/Resources/common/
+cp -f ../goblins/export/goblins.png ../../spine-cocos2dx/example/Resources/common/
+
+cp -f ../raptor/export/raptor.json ../../spine-cocos2dx/example/Resources/common/
+cp -f ../raptor/export/raptor.atlas ../../spine-cocos2dx/example/Resources/common/
+cp -f ../raptor/export/raptor.png ../../spine-cocos2dx/example/Resources/common/
+
+cp -f ../spineboy/export/spineboy.json ../../spine-cocos2dx/example/Resources/common/
+cp -f ../spineboy/export/spineboy.atlas ../../spine-cocos2dx/example/Resources/common/
+cp -f ../spineboy/export/spineboy.png ../../spine-cocos2dx/example/Resources/common/
+
+cp -f ../tank/export/tank.json ../../spine-cocos2dx/example/Resources/common/
+cp -f ../tank/export/tank.atlas ../../spine-cocos2dx/example/Resources/common/
+cp -f ../tank/export/tank.png ../../spine-cocos2dx/example/Resources/common/
+
+echo "spine-love"
+rm -f ../../spine-love/data/*
+cp -f ../goblins/export/goblins-mesh.json ../../spine-love/data
+cp -f ../goblins/export/goblins.atlas ../../spine-love/data
+cp -f ../goblins/export/goblins.png ../../spine-love/data
+
+cp -f ../raptor/export/raptor.json ../../spine-love/data
+cp -f ../raptor/export/raptor.atlas ../../spine-love/data
+cp -f ../raptor/export/raptor.png ../../spine-love/data
+
+cp -f ../spineboy/export/spineboy.json ../../spine-love/data
+cp -f ../spineboy/export/spineboy.atlas ../../spine-love/data
+cp -f ../spineboy/export/spineboy.png ../../spine-love/data
+
+cp -f ../tank/export/tank.json ../../spine-love/data
+cp -f ../tank/export/tank.atlas ../../spine-love/data
+cp -f ../tank/export/tank.png ../../spine-love/data
+
+cp -f ../vine/export/vine.json ../../spine-love/data
+cp -f ../vine/export/vine.atlas ../../spine-love/data
+cp -f ../vine/export/vine.png ../../spine-love/data
+
+cp -f ../stretchyman/export/stretchyman.json ../../spine-love/data
+cp -f ../stretchyman/export/stretchyman.atlas ../../spine-love/data
+cp -f ../stretchyman/export/stretchyman.png ../../spine-love/data
+
+cp -f ../test/export/test.json ../../spine-love/data
+cp -f ../test/export/test.atlas ../../spine-love/data
+cp -f ../test/export/test.png ../../spine-love/data
+
+echo "spine-sfml"
+rm -f ../../spine-sfml/data/*
+cp -f ../goblins/export/goblins-mesh.json ../../spine-sfml/data/
+cp -f ../goblins/export/goblins-mesh.skel ../../spine-sfml/data/
+cp -f ../goblins/export/goblins.atlas ../../spine-sfml/data/
+cp -f ../goblins/export/goblins.png ../../spine-sfml/data/
+
+cp -f ../raptor/export/raptor.json ../../spine-sfml/data/
+cp -f ../raptor/export/raptor.skel ../../spine-sfml/data/
+cp -f ../raptor/export/raptor.atlas ../../spine-sfml/data/
+cp -f ../raptor/export/raptor.png ../../spine-sfml/data/
+
+cp -f ../spineboy/export/spineboy.json ../../spine-sfml/data/
+cp -f ../spineboy/export/spineboy.skel ../../spine-sfml/data/
+cp -f ../spineboy/export/spineboy.atlas ../../spine-sfml/data/
+cp -f ../spineboy/export/spineboy.png ../../spine-sfml/data/
+
+cp -f ../tank/export/tank.json ../../spine-sfml/data/
+cp -f ../tank/export/tank.skel ../../spine-sfml/data/
+cp -f ../tank/export/tank.atlas ../../spine-sfml/data/
+cp -f ../tank/export/tank.png ../../spine-sfml/data/
+
+cp -f ../vine/export/vine.json ../../spine-sfml/data/
+cp -f ../vine/export/vine.skel ../../spine-sfml/data/
+cp -f ../vine/export/vine.atlas ../../spine-sfml/data/
+cp -f ../vine/export/vine.png ../../spine-sfml/data/
+
+cp -f ../stretchyman/export/stretchyman.json ../../spine-sfml/data/
+cp -f ../stretchyman/export/stretchyman.skel ../../spine-sfml/data/
+cp -f ../stretchyman/export/stretchyman.atlas ../../spine-sfml/data/
+cp -f ../stretchyman/export/stretchyman.png ../../spine-sfml/data/
+
+echo "spine-starling"
+# DO NOT DELETE EVERYTHING IN SOURCE, ESPECIALLY goblins-mesh-starling.png/.xml
+cp -f ../goblins/export/goblins-mesh.json ../../spine-starling/spine-starling-example/src/
+cp -f ../goblins/export/goblins.atlas ../../spine-starling/spine-starling-example/src/
+cp -f ../goblins/export/goblins.png ../../spine-starling/spine-starling-example/src/
+
+cp -f ../raptor/export/raptor.json ../../spine-starling/spine-starling-example/src/
+cp -f ../raptor/export/raptor.atlas ../../spine-starling/spine-starling-example/src/
+cp -f ../raptor/export/raptor.png ../../spine-starling/spine-starling-example/src/
+
+cp -f ../spineboy/export/spineboy.json ../../spine-starling/spine-starling-example/src/
+cp -f ../spineboy/export/spineboy.atlas ../../spine-starling/spine-starling-example/src/
+cp -f ../spineboy/export/spineboy.png ../../spine-starling/spine-starling-example/src/
+
+cp -f ../tank/export/tank.json ../../spine-starling/spine-starling-example/src/
+cp -f ../tank/export/tank.atlas ../../spine-starling/spine-starling-example/src/
+cp -f ../tank/export/tank.png ../../spine-starling/spine-starling-example/src/
+
+cp -f ../vine/export/vine.json ../../spine-starling/spine-starling-example/src/
+cp -f ../vine/export/vine.atlas ../../spine-starling/spine-starling-example/src/
+cp -f ../vine/export/vine.png ../../spine-starling/spine-starling-example/src/
+
+
+echo "spine-ts"
+rm -f ../../spine-ts/webgl/example/assets/*
+cp -f ../goblins/export/goblins-mesh.json ../../spine-ts/webgl/example/assets/
+cp -f ../goblins/export/goblins.atlas ../../spine-ts/webgl/example/assets/goblins-mesh.atlas
+cp -f ../goblins/export/goblins.png ../../spine-ts/webgl/example/assets/goblins.png
+
+cp -f ../raptor/export/raptor.json ../../spine-ts/webgl/example/assets/
+cp -f ../raptor/export/raptor.atlas ../../spine-ts/webgl/example/assets/
+cp -f ../raptor/export/raptor.png ../../spine-ts/webgl/example/assets/
+
+cp -f ../spineboy/export/spineboy.json ../../spine-ts/webgl/example/assets/
+cp -f ../spineboy/export/spineboy.atlas ../../spine-ts/webgl/example/assets/
+cp -f ../spineboy/export/spineboy.png ../../spine-ts/webgl/example/assets/
+
+cp -f ../tank/export/tank.json ../../spine-ts/webgl/example/assets/
+cp -f ../tank/export/tank.atlas ../../spine-ts/webgl/example/assets/
+cp -f ../tank/export/tank.png ../../spine-ts/webgl/example/assets/
+
+cp -f ../vine/export/vine.json ../../spine-ts/webgl/example/assets/
+cp -f ../vine/export/vine.atlas ../../spine-ts/webgl/example/assets/
+cp -f ../vine/export/vine.png ../../spine-ts/webgl/example/assets/
+
+cp -f ../stretchyman/export/stretchyman.json ../../spine-ts/webgl/example/assets/
+cp -f ../stretchyman/export/stretchyman.atlas ../../spine-ts/webgl/example/assets/
+cp -f ../stretchyman/export/stretchyman.png ../../spine-ts/webgl/example/assets/
+
+rm -f ../../spine-ts/canvas/example/assets/*
+cp -f ../spineboy/export/spineboy.json ../../spine-ts/canvas/example/assets/
+cp -f ../spineboy/export/spineboy.atlas ../../spine-ts/canvas/example/assets/
+cp -f ../spineboy/export/spineboy.png ../../spine-ts/canvas/example/assets/
+
+rm -f ../../spine-ts/threejs/example/assets/*
+cp -f ../raptor/export/raptor.json ../../spine-ts/threejs/example/assets/
+cp -f ../raptor/export/raptor.atlas ../../spine-ts/threejs/example/assets/
+cp -f ../raptor/export/raptor.png ../../spine-ts/threejs/example/assets/
+
+rm -f ../../spine-ts/widget/example/assets/*
+cp -f ../raptor/export/raptor.json ../../spine-ts/widget/example/assets/
+cp -f ../raptor/export/raptor.atlas ../../spine-ts/widget/example/assets/
+cp -f ../raptor/export/raptor.png ../../spine-ts/widget/example/assets/
+
+cp -f ../spineboy/export/spineboy.json ../../spine-ts/widget/example/assets/
+cp -f ../spineboy/export/spineboy.atlas ../../spine-ts/widget/example/assets/
+cp -f ../spineboy/export/spineboy.png ../../spine-ts/widget/example/assets/
+
+echo "spine-xna"
+rm -f ../../spine-xna/example/data/*
+cp -f ../goblins/export/goblins-mesh.json ../../spine-xna/example/data/
+cp -f ../goblins/export/goblins-mesh.skel ../../spine-xna/example/data/
+cp -f ../goblins/export/goblins.atlas ../../spine-xna/example/data/goblins-mesh.atlas
+cp -f ../goblins/export/goblins.png ../../spine-xna/example/data/
+
+cp -f ../raptor/export/raptor.json ../../spine-xna/example/data/
+cp -f ../raptor/export/raptor.skel ../../spine-xna/example/data/
+cp -f ../raptor/export/raptor.atlas ../../spine-xna/example/data/
+cp -f ../raptor/export/raptor.png ../../spine-xna/example/data/
+
+cp -f ../spineboy/export/spineboy.json ../../spine-xna/example/data/
+cp -f ../spineboy/export/spineboy.skel ../../spine-xna/example/data/
+cp -f ../spineboy/export/spineboy.atlas ../../spine-xna/example/data/
+cp -f ../spineboy/export/spineboy.png ../../spine-xna/example/data/
+
+cp -f ../tank/export/tank.json ../../spine-xna/example/data/
+cp -f ../tank/export/tank.skel ../../spine-xna/example/data/
+cp -f ../tank/export/tank.atlas ../../spine-xna/example/data/
+cp -f ../tank/export/tank.png ../../spine-xna/example/data/

+ 1 - 1
examples/goblins/export/goblins-mesh.json

@@ -1,5 +1,5 @@
 {
-"skeleton": { "hash": "3Z6FWT/Kylgd8cbSWBEwAsOcPEM", "spine": "3.4.00", "width": 266.87, "height": 349.55, "images": "./images/" },
+"skeleton": { "hash": "3Z6FWT/Kylgd8cbSWBEwAsOcPEM", "spine": "3.4.02", "width": 266.87, "height": 349.55, "images": "./images/" },
 "bones": [
 	{ "name": "root" },
 	{ "name": "hip", "parent": "root", "x": 0.64, "y": 114.41 },

BIN
examples/goblins/export/goblins-mesh.skel


+ 1 - 1
examples/goblins/export/goblins.json

@@ -1,5 +1,5 @@
 {
-"skeleton": { "hash": "XWev9W//Ru9qTfd6z9xOs5YG8F0", "spine": "3.4.00", "width": 234.01, "height": 354.84, "images": "./images/" },
+"skeleton": { "hash": "XWev9W//Ru9qTfd6z9xOs5YG8F0", "spine": "3.4.02", "width": 234.01, "height": 354.84, "images": "./images/" },
 "bones": [
 	{ "name": "root" },
 	{ "name": "hip", "parent": "root", "x": 0.64, "y": 114.41 },

BIN
examples/goblins/export/goblins.skel


+ 1 - 1
examples/hero/export/hero-mesh.json

@@ -1,5 +1,5 @@
 {
-"skeleton": { "hash": "9LrmMaI967fC0/XZwO4Ntbo7Ww8", "spine": "3.4.00", "width": 318.71, "height": 333.7, "images": "./images/" },
+"skeleton": { "hash": "9LrmMaI967fC0/XZwO4Ntbo7Ww8", "spine": "3.4.02", "width": 318.71, "height": 333.7, "images": "./images/" },
 "bones": [
 	{ "name": "root" },
 	{ "name": "Hip", "parent": "root", "y": 94.88 },

BIN
examples/hero/export/hero-mesh.skel


+ 1 - 1
examples/hero/export/hero.json

@@ -1,5 +1,5 @@
 {
-"skeleton": { "hash": "G8Hn+I+pLLpQJV630iP0YYkYAHQ", "spine": "3.4.00", "width": 319.35, "height": 337.01, "images": "./images/" },
+"skeleton": { "hash": "G8Hn+I+pLLpQJV630iP0YYkYAHQ", "spine": "3.4.02", "width": 319.35, "height": 337.01, "images": "./images/" },
 "bones": [
 	{ "name": "root" },
 	{ "name": "Hip", "parent": "root", "y": 94.88 },

BIN
examples/hero/export/hero.skel


+ 1 - 1
examples/powerup/export/powerup.json

@@ -1,5 +1,5 @@
 {
-"skeleton": { "hash": "NDIwB/eCc9kyjtXoMAlUrSBw0+Q", "spine": "3.4.00", "width": 413.18, "height": 195.71, "images": "./images/" },
+"skeleton": { "hash": "NDIwB/eCc9kyjtXoMAlUrSBw0+Q", "spine": "3.4.02", "width": 413.18, "height": 195.71, "images": "./images/" },
 "bones": [
 	{ "name": "root" },
 	{ "name": "powerup", "parent": "root", "x": 1.48, "y": 134.02 },

BIN
examples/powerup/export/powerup.skel


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 17 - 17
examples/raptor/export/raptor.json


BIN
examples/raptor/export/raptor.skel


+ 1 - 1
examples/speedy/export/speedy.json

@@ -1,5 +1,5 @@
 {
-"skeleton": { "hash": "tmPhvJxT1yYlfE25wzds+8X1E44", "spine": "3.4.00", "width": 196.03, "height": 305.44, "images": "./images/" },
+"skeleton": { "hash": "tmPhvJxT1yYlfE25wzds+8X1E44", "spine": "3.4.02", "width": 196.03, "height": 305.44, "images": "./images/" },
 "bones": [
 	{ "name": "root" },
 	{ "name": "hip", "parent": "root", "x": -0.02, "y": 51.91 },

BIN
examples/speedy/export/speedy.skel


+ 1 - 1
examples/spineboy-old/export/spineboy-old.json

@@ -1,5 +1,5 @@
 {
-"skeleton": { "hash": "DIwMYpCxf9hwB7YgCS6TSSPK/5A", "spine": "3.4.00", "width": 161.12, "height": 343.58, "images": "./images/" },
+"skeleton": { "hash": "DIwMYpCxf9hwB7YgCS6TSSPK/5A", "spine": "3.4.02", "width": 161.12, "height": 343.58, "images": "./images/" },
 "bones": [
 	{ "name": "root" },
 	{ "name": "hip", "parent": "root", "x": 0.64, "y": 114.41 },

BIN
examples/spineboy-old/export/spineboy-old.skel


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 8 - 8
examples/spineboy/export/spineboy-hover.json


BIN
examples/spineboy/export/spineboy-hover.skel


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 6 - 15
examples/spineboy/export/spineboy-mesh.json


BIN
examples/spineboy/export/spineboy-mesh.skel


+ 1 - 1
examples/spineboy/export/spineboy.json

@@ -1,5 +1,5 @@
 {
-"skeleton": { "hash": "rPoYyBLFG6F0CGZ5wsUEBKDJU9U", "spine": "3.4.00", "width": 470.9, "height": 731.49, "images": "./images/" },
+"skeleton": { "hash": "rPoYyBLFG6F0CGZ5wsUEBKDJU9U", "spine": "3.4.02", "width": 470.9, "height": 731.49, "images": "./images/" },
 "bones": [
 	{ "name": "hip", "y": 247.47 },
 	{ "name": "torso", "parent": "hip", "length": 127.55, "rotation": 103.82, "x": -1.61, "y": 4.9, "color": "e0da19ff" },

BIN
examples/spineboy/export/spineboy.skel


+ 1 - 1
examples/spinosaurus/export/spinosaurus.json

@@ -1,5 +1,5 @@
 {
-"skeleton": { "hash": "+jy97FaQm8tosWwFNGbQGD2+FlY", "spine": "3.4.00", "width": 1680, "height": 1782.27, "images": "./images/" },
+"skeleton": { "hash": "+jy97FaQm8tosWwFNGbQGD2+FlY", "spine": "3.4.02", "width": 1680, "height": 1782.27, "images": "./images/" },
 "bones": [
 	{ "name": "root", "y": -526.31 },
 	{ "name": "leaves", "parent": "root", "x": -0.16, "y": 1310.1 },

BIN
examples/spinosaurus/export/spinosaurus.skel


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 7 - 7
examples/stretchyman/export/stretchyman.json


BIN
examples/stretchyman/export/stretchyman.skel


+ 279 - 279
examples/tank/export/tank.json

@@ -1,5 +1,5 @@
 {
-"skeleton": { "hash": "prAbugErg4ObQ7MEDGj8zq4mn74", "spine": "3.4.00", "width": 1914.53, "height": 964.03, "images": "" },
+"skeleton": { "hash": "6mxwgn4gKXrDy2eixknadUxKY1c", "spine": "3.4.02", "width": 1914.53, "height": 964.05, "images": "./images/" },
 "bones": [
 	{ "name": "root" },
 	{ "name": "tankRoot", "parent": "root", "y": 200 },
@@ -14,8 +14,8 @@
 	{ "name": "antenna5", "parent": "antenna4", "length": 42, "x": 42, "color": "ffee00ff" },
 	{ "name": "antenna6", "parent": "antenna5", "length": 42, "x": 42, "color": "ffee00ff" },
 	{ "name": "cannonConnector", "parent": "guntower", "x": -235.04, "y": 96.07 },
-	{ "name": "cannon", "parent": "cannonConnector", "length": 946.68, "rotation": 180, "color": "ff4000ff" },
 	{ "name": "cannonTarget", "parent": "tankRoot", "x": -1486.66, "y": 351.82, "color": "ff3f00ff" },
+	{ "name": "cannon", "parent": "cannonConnector", "length": 946.68, "rotation": 180, "color": "ff4000ff" },
 	{ "name": "cannonTip", "parent": "cannon", "x": 946.68, "color": "ff4000ff" },
 	{ "name": "machineGunTarget", "parent": "tankRoot", "x": -1474, "y": 559.42, "color": "ff3f00ff" },
 	{
@@ -115,192 +115,192 @@
 	{ "name": "wheel-small3", "parent": "wheel-smallRoot3" }
 ],
 "slots": [
-	{ "name": "tankBody-shadow", "bone": "tankBody", "color": "ffffffb9", "attachment": "images/tankBottom-shadow" },
-	{ "name": "bottom", "bone": "tankBody", "attachment": "images/tankBottom" },
-	{ "name": "tread-inside1", "bone": "tread", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside53", "bone": "tread27", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside27", "bone": "tread14", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside3", "bone": "tread2", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside55", "bone": "tread28", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside29", "bone": "tread15", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside5", "bone": "tread3", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside57", "bone": "tread29", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside31", "bone": "tread16", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside7", "bone": "tread4", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside59", "bone": "tread30", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside33", "bone": "tread17", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside9", "bone": "tread5", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside61", "bone": "tread31", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside35", "bone": "tread18", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside11", "bone": "tread6", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside63", "bone": "tread32", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside37", "bone": "tread19", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside13", "bone": "tread7", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside65", "bone": "tread33", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside39", "bone": "tread20", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside15", "bone": "tread8", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside67", "bone": "tread34", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside69", "bone": "tread35", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside71", "bone": "tread36", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside41", "bone": "tread21", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside17", "bone": "tread9", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside43", "bone": "tread22", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside19", "bone": "tread10", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside45", "bone": "tread23", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside21", "bone": "tread11", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside47", "bone": "tread24", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside23", "bone": "tread12", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside49", "bone": "tread25", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside25", "bone": "tread13", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside51", "bone": "tread26", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside2", "bone": "tread", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside54", "bone": "tread27", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside28", "bone": "tread14", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside4", "bone": "tread2", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside56", "bone": "tread28", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside30", "bone": "tread15", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside6", "bone": "tread3", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside58", "bone": "tread29", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside32", "bone": "tread16", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside8", "bone": "tread4", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside60", "bone": "tread30", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside34", "bone": "tread17", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside10", "bone": "tread5", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside62", "bone": "tread31", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside36", "bone": "tread18", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside12", "bone": "tread6", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside64", "bone": "tread32", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside38", "bone": "tread19", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside14", "bone": "tread7", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside66", "bone": "tread33", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside40", "bone": "tread20", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside16", "bone": "tread8", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside68", "bone": "tread34", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside70", "bone": "tread35", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside72", "bone": "tread36", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside42", "bone": "tread21", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside18", "bone": "tread9", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside44", "bone": "tread22", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside20", "bone": "tread10", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside46", "bone": "tread23", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside22", "bone": "tread11", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside48", "bone": "tread24", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside24", "bone": "tread12", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside50", "bone": "tread25", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside26", "bone": "tread13", "attachment": "images/tread-inside" },
-	{ "name": "tread-inside52", "bone": "tread26", "attachment": "images/tread-inside" },
-	{ "name": "wheel-big", "bone": "wheel-big1", "color": "dbdbdbff", "attachment": "images/wheel-big" },
-	{ "name": "wheel-big2", "bone": "wheel-big2", "color": "dbdbdbff", "attachment": "images/wheel-big" },
-	{ "name": "wheel-mid", "bone": "wheel-mid1", "attachment": "images/wheel-mid" },
-	{ "name": "wheel-mid2", "bone": "wheel-mid2", "attachment": "images/wheel-mid" },
-	{ "name": "wheel-mid3", "bone": "wheel-mid3", "attachment": "images/wheel-mid" },
-	{ "name": "wheel-mid4", "bone": "wheel-mid4", "attachment": "images/wheel-mid" },
-	{ "name": "wheel-mid5", "bone": "wheel-mid5", "attachment": "images/wheel-mid" },
-	{ "name": "wheel-mid6", "bone": "wheel-mid6", "attachment": "images/wheel-mid" },
-	{ "name": "wheel-small", "bone": "wheel-small1", "attachment": "images/wheel-small" },
-	{ "name": "wheel-small2", "bone": "wheel-small2", "attachment": "images/wheel-small" },
-	{ "name": "wheel-small3", "bone": "wheel-small3", "attachment": "images/wheel-small" },
+	{ "name": "tankBody-shadow", "bone": "tankBody", "color": "ffffffb9", "attachment": "tankBottom-shadow" },
+	{ "name": "bottom", "bone": "tankBody", "attachment": "tankBottom" },
+	{ "name": "tread-inside1", "bone": "tread", "attachment": "tread-inside" },
+	{ "name": "tread-inside53", "bone": "tread27", "attachment": "tread-inside" },
+	{ "name": "tread-inside27", "bone": "tread14", "attachment": "tread-inside" },
+	{ "name": "tread-inside3", "bone": "tread2", "attachment": "tread-inside" },
+	{ "name": "tread-inside55", "bone": "tread28", "attachment": "tread-inside" },
+	{ "name": "tread-inside29", "bone": "tread15", "attachment": "tread-inside" },
+	{ "name": "tread-inside5", "bone": "tread3", "attachment": "tread-inside" },
+	{ "name": "tread-inside57", "bone": "tread29", "attachment": "tread-inside" },
+	{ "name": "tread-inside31", "bone": "tread16", "attachment": "tread-inside" },
+	{ "name": "tread-inside7", "bone": "tread4", "attachment": "tread-inside" },
+	{ "name": "tread-inside59", "bone": "tread30", "attachment": "tread-inside" },
+	{ "name": "tread-inside33", "bone": "tread17", "attachment": "tread-inside" },
+	{ "name": "tread-inside9", "bone": "tread5", "attachment": "tread-inside" },
+	{ "name": "tread-inside61", "bone": "tread31", "attachment": "tread-inside" },
+	{ "name": "tread-inside35", "bone": "tread18", "attachment": "tread-inside" },
+	{ "name": "tread-inside11", "bone": "tread6", "attachment": "tread-inside" },
+	{ "name": "tread-inside63", "bone": "tread32", "attachment": "tread-inside" },
+	{ "name": "tread-inside37", "bone": "tread19", "attachment": "tread-inside" },
+	{ "name": "tread-inside13", "bone": "tread7", "attachment": "tread-inside" },
+	{ "name": "tread-inside65", "bone": "tread33", "attachment": "tread-inside" },
+	{ "name": "tread-inside39", "bone": "tread20", "attachment": "tread-inside" },
+	{ "name": "tread-inside15", "bone": "tread8", "attachment": "tread-inside" },
+	{ "name": "tread-inside67", "bone": "tread34", "attachment": "tread-inside" },
+	{ "name": "tread-inside69", "bone": "tread35", "attachment": "tread-inside" },
+	{ "name": "tread-inside71", "bone": "tread36", "attachment": "tread-inside" },
+	{ "name": "tread-inside41", "bone": "tread21", "attachment": "tread-inside" },
+	{ "name": "tread-inside17", "bone": "tread9", "attachment": "tread-inside" },
+	{ "name": "tread-inside43", "bone": "tread22", "attachment": "tread-inside" },
+	{ "name": "tread-inside19", "bone": "tread10", "attachment": "tread-inside" },
+	{ "name": "tread-inside45", "bone": "tread23", "attachment": "tread-inside" },
+	{ "name": "tread-inside21", "bone": "tread11", "attachment": "tread-inside" },
+	{ "name": "tread-inside47", "bone": "tread24", "attachment": "tread-inside" },
+	{ "name": "tread-inside23", "bone": "tread12", "attachment": "tread-inside" },
+	{ "name": "tread-inside49", "bone": "tread25", "attachment": "tread-inside" },
+	{ "name": "tread-inside25", "bone": "tread13", "attachment": "tread-inside" },
+	{ "name": "tread-inside51", "bone": "tread26", "attachment": "tread-inside" },
+	{ "name": "tread-inside2", "bone": "tread", "attachment": "tread-inside" },
+	{ "name": "tread-inside54", "bone": "tread27", "attachment": "tread-inside" },
+	{ "name": "tread-inside28", "bone": "tread14", "attachment": "tread-inside" },
+	{ "name": "tread-inside4", "bone": "tread2", "attachment": "tread-inside" },
+	{ "name": "tread-inside56", "bone": "tread28", "attachment": "tread-inside" },
+	{ "name": "tread-inside30", "bone": "tread15", "attachment": "tread-inside" },
+	{ "name": "tread-inside6", "bone": "tread3", "attachment": "tread-inside" },
+	{ "name": "tread-inside58", "bone": "tread29", "attachment": "tread-inside" },
+	{ "name": "tread-inside32", "bone": "tread16", "attachment": "tread-inside" },
+	{ "name": "tread-inside8", "bone": "tread4", "attachment": "tread-inside" },
+	{ "name": "tread-inside60", "bone": "tread30", "attachment": "tread-inside" },
+	{ "name": "tread-inside34", "bone": "tread17", "attachment": "tread-inside" },
+	{ "name": "tread-inside10", "bone": "tread5", "attachment": "tread-inside" },
+	{ "name": "tread-inside62", "bone": "tread31", "attachment": "tread-inside" },
+	{ "name": "tread-inside36", "bone": "tread18", "attachment": "tread-inside" },
+	{ "name": "tread-inside12", "bone": "tread6", "attachment": "tread-inside" },
+	{ "name": "tread-inside64", "bone": "tread32", "attachment": "tread-inside" },
+	{ "name": "tread-inside38", "bone": "tread19", "attachment": "tread-inside" },
+	{ "name": "tread-inside14", "bone": "tread7", "attachment": "tread-inside" },
+	{ "name": "tread-inside66", "bone": "tread33", "attachment": "tread-inside" },
+	{ "name": "tread-inside40", "bone": "tread20", "attachment": "tread-inside" },
+	{ "name": "tread-inside16", "bone": "tread8", "attachment": "tread-inside" },
+	{ "name": "tread-inside68", "bone": "tread34", "attachment": "tread-inside" },
+	{ "name": "tread-inside70", "bone": "tread35", "attachment": "tread-inside" },
+	{ "name": "tread-inside72", "bone": "tread36", "attachment": "tread-inside" },
+	{ "name": "tread-inside42", "bone": "tread21", "attachment": "tread-inside" },
+	{ "name": "tread-inside18", "bone": "tread9", "attachment": "tread-inside" },
+	{ "name": "tread-inside44", "bone": "tread22", "attachment": "tread-inside" },
+	{ "name": "tread-inside20", "bone": "tread10", "attachment": "tread-inside" },
+	{ "name": "tread-inside46", "bone": "tread23", "attachment": "tread-inside" },
+	{ "name": "tread-inside22", "bone": "tread11", "attachment": "tread-inside" },
+	{ "name": "tread-inside48", "bone": "tread24", "attachment": "tread-inside" },
+	{ "name": "tread-inside24", "bone": "tread12", "attachment": "tread-inside" },
+	{ "name": "tread-inside50", "bone": "tread25", "attachment": "tread-inside" },
+	{ "name": "tread-inside26", "bone": "tread13", "attachment": "tread-inside" },
+	{ "name": "tread-inside52", "bone": "tread26", "attachment": "tread-inside" },
+	{ "name": "wheel-big", "bone": "wheel-big1", "color": "dbdbdbff", "attachment": "wheel-big" },
+	{ "name": "wheel-big2", "bone": "wheel-big2", "color": "dbdbdbff", "attachment": "wheel-big" },
+	{ "name": "wheel-mid", "bone": "wheel-mid1", "attachment": "wheel-mid" },
+	{ "name": "wheel-mid2", "bone": "wheel-mid2", "attachment": "wheel-mid" },
+	{ "name": "wheel-mid3", "bone": "wheel-mid3", "attachment": "wheel-mid" },
+	{ "name": "wheel-mid4", "bone": "wheel-mid4", "attachment": "wheel-mid" },
+	{ "name": "wheel-mid5", "bone": "wheel-mid5", "attachment": "wheel-mid" },
+	{ "name": "wheel-mid6", "bone": "wheel-mid6", "attachment": "wheel-mid" },
+	{ "name": "wheel-small", "bone": "wheel-small1", "attachment": "wheel-small" },
+	{ "name": "wheel-small2", "bone": "wheel-small2", "attachment": "wheel-small" },
+	{ "name": "wheel-small3", "bone": "wheel-small3", "attachment": "wheel-small" },
 	{
 		"name": "wheel-mid-overlay",
 		"bone": "wheel-midRoot1",
 		"color": "ffffffec",
-		"attachment": "images/wheel-mid-overlay",
+		"attachment": "wheel-mid-overlay",
 		"blend": "multiply"
 	},
 	{
 		"name": "wheel-mid-overlay2",
 		"bone": "wheel-midRoot2",
 		"color": "ffffffec",
-		"attachment": "images/wheel-mid-overlay",
+		"attachment": "wheel-mid-overlay",
 		"blend": "multiply"
 	},
 	{
 		"name": "wheel-mid-overlay3",
 		"bone": "wheel-midRoot3",
 		"color": "ffffffec",
-		"attachment": "images/wheel-mid-overlay",
+		"attachment": "wheel-mid-overlay",
 		"blend": "multiply"
 	},
 	{
 		"name": "wheel-mid-overlay4",
 		"bone": "wheel-midRoot4",
 		"color": "ffffffec",
-		"attachment": "images/wheel-mid-overlay",
+		"attachment": "wheel-mid-overlay",
 		"blend": "multiply"
 	},
 	{
 		"name": "wheel-mid-overlay5",
 		"bone": "wheel-midRoot5",
 		"color": "ffffffec",
-		"attachment": "images/wheel-mid-overlay",
+		"attachment": "wheel-mid-overlay",
 		"blend": "multiply"
 	},
 	{
 		"name": "wheel-mid-overlay6",
 		"bone": "wheel-midRoot6",
 		"color": "ffffffec",
-		"attachment": "images/wheel-mid-overlay",
+		"attachment": "wheel-mid-overlay",
 		"blend": "multiply"
 	},
 	{
 		"name": "wheel-big-overlay1",
 		"bone": "wheel-bigRoot1",
 		"color": "ffffffe9",
-		"attachment": "images/wheel-big-overlay",
+		"attachment": "wheel-big-overlay",
 		"blend": "multiply"
 	},
 	{
 		"name": "wheel-big-overlay2",
 		"bone": "wheel-bigRoot2",
 		"color": "ffffffe9",
-		"attachment": "images/wheel-big-overlay",
+		"attachment": "wheel-big-overlay",
 		"blend": "multiply"
 	},
 	{ "name": "treads", "bone": "tankRoot", "attachment": "treads" },
-	{ "name": "tread", "bone": "tread", "color": "c0974fff", "attachment": "images/tread" },
-	{ "name": "tread27", "bone": "tread27", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread14", "bone": "tread14", "attachment": "images/tread" },
-	{ "name": "tread2", "bone": "tread2", "attachment": "images/tread" },
-	{ "name": "tread28", "bone": "tread28", "attachment": "images/tread" },
-	{ "name": "tread15", "bone": "tread15", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread3", "bone": "tread3", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread29", "bone": "tread29", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread16", "bone": "tread16", "attachment": "images/tread" },
-	{ "name": "tread4", "bone": "tread4", "attachment": "images/tread" },
-	{ "name": "tread30", "bone": "tread30", "attachment": "images/tread" },
-	{ "name": "tread17", "bone": "tread17", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread5", "bone": "tread5", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread31", "bone": "tread31", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread18", "bone": "tread18", "attachment": "images/tread" },
-	{ "name": "tread6", "bone": "tread6", "attachment": "images/tread" },
-	{ "name": "tread32", "bone": "tread32", "attachment": "images/tread" },
-	{ "name": "tread19", "bone": "tread19", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread7", "bone": "tread7", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread33", "bone": "tread33", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread20", "bone": "tread20", "attachment": "images/tread" },
-	{ "name": "tread8", "bone": "tread8", "attachment": "images/tread" },
-	{ "name": "tread34", "bone": "tread34", "attachment": "images/tread" },
-	{ "name": "tread35", "bone": "tread35", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread36", "bone": "tread36", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread21", "bone": "tread21", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread9", "bone": "tread9", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread22", "bone": "tread22", "attachment": "images/tread" },
-	{ "name": "tread10", "bone": "tread10", "attachment": "images/tread" },
-	{ "name": "tread23", "bone": "tread23", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread11", "bone": "tread11", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread24", "bone": "tread24", "attachment": "images/tread" },
-	{ "name": "tread12", "bone": "tread12", "attachment": "images/tread" },
-	{ "name": "tread25", "bone": "tread25", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread13", "bone": "tread13", "color": "adc9b8ff", "attachment": "images/tread" },
-	{ "name": "tread26", "bone": "tread26", "attachment": "images/tread" },
-	{ "name": "rock", "bone": "rock", "attachment": "images/rock" },
-	{ "name": "machinegun", "bone": "machinegun", "attachment": "images/machinegun" },
-	{ "name": "machinegun-mount", "bone": "machinegun-mount", "attachment": "images/machinegun-mount" },
-	{ "name": "tankTop", "bone": "tankBody", "attachment": "images/tankTop" },
-	{ "name": "guntower", "bone": "guntower", "attachment": "images/guntower" },
-	{ "name": "cannon", "bone": "cannon", "attachment": "images/cannon" },
-	{ "name": "cannonConnector", "bone": "cannonConnector", "attachment": "images/cannonConnector" },
-	{ "name": "antenna", "bone": "antennaRoot", "attachment": "images/antenna" }
+	{ "name": "tread", "bone": "tread", "color": "c0974fff", "attachment": "tread" },
+	{ "name": "tread27", "bone": "tread27", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread14", "bone": "tread14", "attachment": "tread" },
+	{ "name": "tread2", "bone": "tread2", "attachment": "tread" },
+	{ "name": "tread28", "bone": "tread28", "attachment": "tread" },
+	{ "name": "tread15", "bone": "tread15", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread3", "bone": "tread3", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread29", "bone": "tread29", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread16", "bone": "tread16", "attachment": "tread" },
+	{ "name": "tread4", "bone": "tread4", "attachment": "tread" },
+	{ "name": "tread30", "bone": "tread30", "attachment": "tread" },
+	{ "name": "tread17", "bone": "tread17", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread5", "bone": "tread5", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread31", "bone": "tread31", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread18", "bone": "tread18", "attachment": "tread" },
+	{ "name": "tread6", "bone": "tread6", "attachment": "tread" },
+	{ "name": "tread32", "bone": "tread32", "attachment": "tread" },
+	{ "name": "tread19", "bone": "tread19", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread7", "bone": "tread7", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread33", "bone": "tread33", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread20", "bone": "tread20", "attachment": "tread" },
+	{ "name": "tread8", "bone": "tread8", "attachment": "tread" },
+	{ "name": "tread34", "bone": "tread34", "attachment": "tread" },
+	{ "name": "tread35", "bone": "tread35", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread36", "bone": "tread36", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread21", "bone": "tread21", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread9", "bone": "tread9", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread22", "bone": "tread22", "attachment": "tread" },
+	{ "name": "tread10", "bone": "tread10", "attachment": "tread" },
+	{ "name": "tread23", "bone": "tread23", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread11", "bone": "tread11", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread24", "bone": "tread24", "attachment": "tread" },
+	{ "name": "tread12", "bone": "tread12", "attachment": "tread" },
+	{ "name": "tread25", "bone": "tread25", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread13", "bone": "tread13", "color": "adc9b8ff", "attachment": "tread" },
+	{ "name": "tread26", "bone": "tread26", "attachment": "tread" },
+	{ "name": "rock", "bone": "rock", "attachment": "rock" },
+	{ "name": "machinegun", "bone": "machinegun", "attachment": "machinegun" },
+	{ "name": "machinegun-mount", "bone": "machinegun-mount", "attachment": "machinegun-mount" },
+	{ "name": "tankTop", "bone": "tankBody", "attachment": "tankTop" },
+	{ "name": "guntower", "bone": "guntower", "attachment": "guntower" },
+	{ "name": "cannon", "bone": "cannon", "attachment": "cannon" },
+	{ "name": "cannonConnector", "bone": "cannonConnector", "attachment": "cannonConnector" },
+	{ "name": "antenna", "bone": "antennaRoot", "attachment": "antenna" }
 ],
 "ik": [
 	{
@@ -419,10 +419,10 @@
 "skins": {
 	"default": {
 		"antenna": {
-			"images/antenna": {
+			"antenna": {
 				"type": "mesh",
 				"uvs": [ 0.64286, 0.07875, 0.65354, 0.15349, 0.66324, 0.22137, 0.67367, 0.29433, 0.68383, 0.36543, 0.69359, 0.43374, 0.7031, 0.50029, 0.71311, 0.5703, 0.72327, 0.64138, 0.73406, 0.71688, 0.7444, 0.78929, 0.75614, 0.8714, 0.76905, 0.9431, 1, 0.9431, 1, 1, 0, 1, 0, 0.9431, 0.20105, 0.9431, 0.20105, 0.87093, 0.21461, 0.78846, 0.22651, 0.71606, 0.23885, 0.64098, 0.25035, 0.57104, 0.26206, 0.49983, 0.27306, 0.4329, 0.2843, 0.36453, 0.29592, 0.29381, 0.308, 0.22037, 0.319, 0.15345, 0.33141, 0.07795, 0.34423, 0, 0.6316, 0 ],
-				"triangles": [ 29, 0, 1, 29, 30, 0, 30, 31, 0, 27, 2, 3, 27, 28, 2, 28, 1, 2, 28, 29, 1, 26, 27, 3, 25, 4, 5, 25, 26, 4, 26, 3, 4, 24, 25, 5, 7, 23, 6, 23, 24, 6, 24, 5, 6, 7, 22, 23, 21, 8, 9, 21, 22, 8, 22, 7, 8, 20, 21, 9, 19, 20, 10, 20, 9, 10, 14, 15, 12, 15, 17, 12, 12, 13, 14, 15, 16, 17, 17, 11, 12, 17, 18, 11, 18, 19, 11, 19, 10, 11 ],
+				"triangles": [ 30, 31, 0, 29, 30, 0, 29, 0, 1, 28, 29, 1, 28, 1, 2, 27, 28, 2, 27, 2, 3, 26, 3, 4, 25, 26, 4, 25, 4, 5, 26, 27, 3, 24, 5, 6, 23, 24, 6, 7, 23, 6, 24, 25, 5, 22, 7, 8, 21, 22, 8, 21, 8, 9, 7, 22, 23, 20, 9, 10, 19, 20, 10, 20, 21, 9, 19, 10, 11, 18, 19, 11, 17, 18, 11, 17, 11, 12, 15, 16, 17, 12, 13, 14, 15, 17, 12, 14, 15, 12 ],
 				"vertices": [ 2, 10, 65.37999, -3.14, 0.3125, 11, 23.38, -3.14, 0.6875, 3, 9, 84.73, -3.37, 0.0625, 10, 42.73, -3.37, 0.625, 11, 0.73, -3.37, 0.3125, 3, 9, 64.16, -3.59, 0.3125, 10, 22.16, -3.59, 0.625, 11, -19.83, -3.59, 0.0625, 3, 8, 84.06, -3.82, 0.0625, 9, 42.06, -3.82, 0.625, 10, 0.06, -3.82, 0.3125, 3, 8, 62.51, -4.04, 0.3125, 9, 20.51, -4.04, 0.625, 10, -21.48, -4.04, 0.0625, 3, 7, 83.81, -4.25, 0.0625, 8, 41.81, -4.25, 0.625, 9, -0.18, -4.25, 0.3125, 3, 7, 63.65, -4.46, 0.3125, 8, 21.65, -4.46, 0.625, 9, -20.34, -4.46, 0.0625, 3, 6, 84.43, -4.67999, 0.0625, 7, 42.43, -4.67999, 0.625, 8, 0.43, -4.67999, 0.3125, 3, 6, 62.9, -4.91, 0.3125, 7, 20.9, -4.91, 0.625, 8, -21.09, -4.91, 0.0625, 3, 5, 5.14, 80.01999, 0.0625, 6, 40.02, -5.14, 0.625, 7, -1.97, -5.14, 0.3125, 3, 5, 5.37, 58.08, 0.375, 6, 18.08, -5.37, 0.5625, 7, -23.91, -5.37, 0.0625, 1, 5, 5.63, 33.2, 1, 1, 5, 5.91, 11.48, 1, 1, 5, 11, 11.48, 1, 1, 5, 10.99, -5.75, 1, 1, 5, -11, -5.75, 1, 1, 5, -10.99, 11.48, 1, 1, 5, -6.57, 11.48, 1, 1, 5, -6.57, 33.34, 1, 3, 5, -6.27, 58.33, 0.375, 6, 18.33, 6.27, 0.5625, 7, -23.66, 6.27, 0.0625, 3, 5, -6.01, 80.26999, 0.0625, 6, 40.27, 6.01, 0.625, 7, -1.72, 6.01, 0.3125, 3, 6, 63.02, 5.74, 0.3125, 7, 21.02, 5.74, 0.625, 8, -20.96999, 5.74, 0.0625, 3, 6, 84.21, 5.49, 0.0625, 7, 42.21, 5.49, 0.625, 8, 0.21, 5.49, 0.3125, 3, 7, 63.79, 5.23, 0.3125, 8, 21.79, 5.23, 0.625, 9, -20.2, 5.23, 0.0625, 3, 7, 84.07, 4.98999, 0.0625, 8, 42.07, 4.98999, 0.625, 9, 0.07, 4.98999, 0.3125, 3, 8, 62.78, 4.73999, 0.3125, 9, 20.78, 4.73999, 0.625, 10, -21.21, 4.73999, 0.0625, 3, 8, 84.21, 4.48, 0.0625, 9, 42.21, 4.48, 0.625, 10, 0.21, 4.48, 0.3125, 3, 9, 64.46, 4.21999, 0.3125, 10, 22.46, 4.21999, 0.625, 11, -19.53, 4.21999, 0.0625, 3, 9, 84.74, 3.98, 0.0625, 10, 42.74, 3.98, 0.625, 11, 0.74, 3.98, 0.3125, 2, 10, 65.62, 3.7, 0.3125, 11, 23.62, 3.7, 0.6875, 1, 11, 47.24, 3.42, 1, 1, 11, 47.24, -2.89, 1 ],
 				"hull": 32,
 				"edges": [ 28, 30, 28, 26, 30, 32, 26, 24, 24, 22, 32, 34, 34, 24, 34, 36, 36, 22, 60, 62, 38, 36, 20, 22, 38, 20, 40, 38, 18, 20, 40, 18, 42, 40, 16, 18, 42, 16, 44, 42, 14, 16, 44, 14, 46, 44, 12, 14, 46, 12, 48, 46, 10, 12, 48, 10, 50, 48, 8, 10, 50, 8, 52, 50, 6, 8, 52, 6, 54, 52, 4, 6, 54, 4, 56, 54, 2, 4, 56, 2, 60, 58, 58, 56, 62, 0, 0, 2, 58, 0 ],
@@ -431,17 +431,17 @@
 			}
 		},
 		"bottom": {
-			"images/tankBottom": { "x": -16.66, "y": 9.89, "width": 1285, "height": 276 }
+			"tankBottom": { "x": -16.66, "y": 9.89, "width": 1285, "height": 276 }
 		},
 		"cannon": {
-			"images/cannon": { "x": 481.95, "y": -0.02, "rotation": 179.99, "width": 931, "height": 58 }
+			"cannon": { "x": 481.95, "y": -0.02, "rotation": 179.99, "width": 931, "height": 58 }
 		},
 		"cannonConnector": {
-			"images/cannonConnector": {
+			"cannonConnector": {
 				"type": "mesh",
 				"uvs": [ 1, 0.03236, 1, 0.10602, 0.90987, 0.32859, 0.81975, 0.55116, 0.72962, 0.77372, 0.6395, 0.99629, 0.42157, 0.99629, 0.20364, 0.99629, 0, 0.85433, 0, 0.69901, 0.02267, 0.52884, 0, 0.31444, 0.21601, 0.12998, 0.43367, 0, 0.63546, 0.0037, 0.48407, 0.77059, 0.31496, 0.52496, 0.64132, 0.19648, 0.21516, 0.76765, 0.58345, 0.5647, 0.68444, 0.40146, 0.46758, 0.36649, 0.28934, 0.34603 ],
-				"triangles": [ 7, 18, 6, 6, 18, 15, 7, 8, 18, 8, 9, 18, 18, 16, 15, 15, 16, 19, 9, 10, 18, 18, 10, 16, 16, 21, 19, 19, 21, 20, 10, 22, 16, 10, 11, 22, 16, 22, 21, 21, 17, 20, 21, 12, 13, 17, 13, 14, 17, 21, 13, 11, 12, 22, 21, 22, 12, 6, 15, 5, 5, 15, 4, 15, 19, 4, 4, 19, 3, 19, 20, 3, 3, 20, 2, 20, 17, 2, 2, 17, 1, 17, 14, 1, 14, 0, 1 ],
-				"vertices": [ 1, 12, 35.91, 69.08, 1, 1, 12, 35.91, 59.13, 1, 1, 12, 25.81, 29.09, 1, 1, 12, 15.72, -0.95, 1, 1, 12, 5.63, -31, 1, 1, 12, -4.46, -61.04, 1, 2, 12, -28.87, -61.04, 0.33333, 13, 28.87, 61.03, 0.66666, 1, 13, 53.27, 61.01, 1, 1, 13, 76.08, 41.83, 1, 1, 13, 71.17, 21.62, 1, 1, 13, 72.83, -1.62, 1, 1, 13, 70.37, -29.12, 1, 1, 13, 50.66, -56.13, 1, 2, 12, -28.43, 74.37, 0.41, 13, 28.43, -74.39, 0.58999, 2, 12, -4.91, 72.94999, 0.52, 13, 4.91, -72.94999, 0.48, 2, 12, -21.87, -30.57, 0.49, 13, 21.87, 30.56, 0.51, 1, 13, 40.81, -2.59999, 1, 2, 12, -4.25, 46.92, 0.49, 13, 4.25, -46.92, 0.51, 1, 13, 51.98, 30.15, 1, 2, 12, -10.74, -2.78, 0.49, 13, 10.74, 2.77, 0.51, 2, 12, 0.56, 19.25, 0.49, 13, -0.56, -19.25, 0.51, 1, 13, 23.71, -23.98, 1, 1, 13, 43.68, -26.76, 1 ],
+				"triangles": [ 21, 22, 12, 11, 12, 22, 17, 21, 13, 17, 13, 14, 21, 12, 13, 21, 17, 20, 16, 22, 21, 10, 11, 22, 10, 22, 16, 19, 21, 20, 16, 21, 19, 18, 10, 16, 9, 10, 18, 15, 16, 19, 18, 16, 15, 8, 9, 18, 7, 8, 18, 6, 18, 15, 7, 18, 6, 14, 0, 1, 17, 14, 1, 2, 17, 1, 20, 17, 2, 3, 20, 2, 19, 20, 3, 4, 19, 3, 15, 19, 4, 5, 15, 4, 6, 15, 5 ],
+				"vertices": [ 1, 12, 35.91, 69.08, 1, 1, 12, 35.91, 59.13, 1, 1, 12, 25.81, 29.09, 1, 1, 12, 15.72, -0.95, 1, 1, 12, 5.63, -31, 1, 1, 12, -4.46, -61.04, 1, 2, 12, -28.87, -61.04, 0.33333, 14, 28.87, 61.03, 0.66666, 1, 14, 53.27, 61.01, 1, 1, 14, 76.08, 41.83, 1, 1, 14, 71.17, 21.62, 1, 1, 14, 72.83, -1.62, 1, 1, 14, 70.37, -29.12, 1, 1, 14, 50.66, -56.13, 1, 2, 12, -28.43, 74.37, 0.41, 14, 28.43, -74.39, 0.58999, 2, 12, -4.91, 72.94999, 0.52, 14, 4.91, -72.94999, 0.48, 2, 12, -21.87, -30.57, 0.49, 14, 21.87, 30.56, 0.51, 1, 14, 40.81, -2.59999, 1, 2, 12, -4.25, 46.92, 0.49, 14, 4.25, -46.92, 0.51, 1, 14, 51.98, 30.15, 1, 2, 12, -10.74, -2.78, 0.49, 14, 10.74, 2.77, 0.51, 2, 12, 0.56, 19.25, 0.49, 14, -0.56, -19.25, 0.51, 1, 14, 23.71, -23.98, 1, 1, 14, 43.68, -26.76, 1 ],
 				"hull": 15,
 				"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, 0 ],
 				"width": 112,
@@ -449,346 +449,346 @@
 			}
 		},
 		"guntower": {
-			"images/guntower": { "x": 77.22, "y": 122.58, "width": 730, "height": 289 }
+			"guntower": { "x": 77.22, "y": 122.58, "width": 730, "height": 289 }
 		},
 		"machinegun": {
-			"images/machinegun": { "x": 44.85, "y": -5.72, "rotation": -180, "width": 331, "height": 57 }
+			"machinegun": { "x": 44.85, "y": -5.72, "rotation": -180, "width": 331, "height": 57 }
 		},
 		"machinegun-mount": {
-			"images/machinegun-mount": { "x": 47.42, "y": -1.53, "rotation": -90, "width": 72, "height": 96 }
+			"machinegun-mount": { "x": 47.42, "y": -1.53, "rotation": -90, "width": 72, "height": 96 }
 		},
 		"rock": {
-			"images/rock": { "color": "404040ff", "x": 25.23, "y": 27.35, "width": 252, "height": 55 }
+			"rock": { "color": "404040ff", "x": 25.23, "y": 27.35, "width": 252, "height": 55 }
 		},
 		"tankBody-shadow": {
-			"images/tankBottom-shadow": { "x": -11.43, "y": -42.88, "width": 1291, "height": 341 }
+			"tankBottom-shadow": { "x": -11.43, "y": -42.88, "width": 1291, "height": 341 }
 		},
 		"tankTop": {
-			"images/tankTop": { "x": 6.8, "y": 168.71, "width": 1407, "height": 222 }
+			"tankTop": { "x": 6.8, "y": 168.71, "width": 1407, "height": 222 }
 		},
 		"tread": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread-inside1": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside10": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside11": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside12": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside13": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside14": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside15": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside16": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside17": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside18": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside19": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside2": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside20": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside21": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside22": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside23": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside24": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside25": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside26": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside27": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside28": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside29": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside3": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside30": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside31": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside32": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside33": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside34": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside35": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside36": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside37": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside38": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside39": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside4": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside40": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside41": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside42": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside43": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside44": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside45": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside46": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside47": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside48": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside49": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside5": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside50": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside51": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside52": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside53": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside54": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside55": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside56": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside57": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside58": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside59": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside6": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside60": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside61": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside62": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside63": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside64": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside65": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside66": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside67": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside68": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside69": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside7": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside70": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside71": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside72": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside8": {
-			"images/tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 20.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread-inside9": {
-			"images/tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
+			"tread-inside": { "x": 60.1, "y": 12.56, "rotation": -180, "width": 25, "height": 28 }
 		},
 		"tread10": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread11": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread12": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread13": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread14": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread15": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread16": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread17": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread18": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread19": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread2": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread20": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread21": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread22": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread23": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread24": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread25": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread26": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread27": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread28": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread29": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread3": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread30": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread31": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread32": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread33": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread34": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread35": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread36": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread4": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread5": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread6": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread7": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread8": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"tread9": {
-			"images/tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
+			"tread": { "x": 45.47, "y": -8.28, "rotation": -179.99, "width": 96, "height": 30 }
 		},
 		"treads": {
 			"treads": {
@@ -801,61 +801,61 @@
 			}
 		},
 		"wheel-big": {
-			"images/wheel-big": { "width": 191, "height": 191 }
+			"wheel-big": { "width": 191, "height": 191 }
 		},
 		"wheel-big-overlay1": {
-			"images/wheel-big-overlay": { "width": 186, "height": 186 }
+			"wheel-big-overlay": { "width": 186, "height": 186 }
 		},
 		"wheel-big-overlay2": {
-			"images/wheel-big-overlay": { "width": 186, "height": 186 }
+			"wheel-big-overlay": { "width": 186, "height": 186 }
 		},
 		"wheel-big2": {
-			"images/wheel-big": { "width": 191, "height": 191 }
+			"wheel-big": { "width": 191, "height": 191 }
 		},
 		"wheel-mid": {
-			"images/wheel-mid": { "width": 136, "height": 136 }
+			"wheel-mid": { "width": 136, "height": 136 }
 		},
 		"wheel-mid-overlay": {
-			"images/wheel-mid-overlay": { "width": 136, "height": 136 }
+			"wheel-mid-overlay": { "width": 136, "height": 136 }
 		},
 		"wheel-mid-overlay2": {
-			"images/wheel-mid-overlay": { "width": 136, "height": 136 }
+			"wheel-mid-overlay": { "width": 136, "height": 136 }
 		},
 		"wheel-mid-overlay3": {
-			"images/wheel-mid-overlay": { "width": 136, "height": 136 }
+			"wheel-mid-overlay": { "width": 136, "height": 136 }
 		},
 		"wheel-mid-overlay4": {
-			"images/wheel-mid-overlay": { "width": 136, "height": 136 }
+			"wheel-mid-overlay": { "width": 136, "height": 136 }
 		},
 		"wheel-mid-overlay5": {
-			"images/wheel-mid-overlay": { "width": 136, "height": 136 }
+			"wheel-mid-overlay": { "width": 136, "height": 136 }
 		},
 		"wheel-mid-overlay6": {
-			"images/wheel-mid-overlay": { "width": 136, "height": 136 }
+			"wheel-mid-overlay": { "width": 136, "height": 136 }
 		},
 		"wheel-mid2": {
-			"images/wheel-mid": { "width": 136, "height": 136 }
+			"wheel-mid": { "width": 136, "height": 136 }
 		},
 		"wheel-mid3": {
-			"images/wheel-mid": { "width": 136, "height": 136 }
+			"wheel-mid": { "width": 136, "height": 136 }
 		},
 		"wheel-mid4": {
-			"images/wheel-mid": { "width": 136, "height": 136 }
+			"wheel-mid": { "width": 136, "height": 136 }
 		},
 		"wheel-mid5": {
-			"images/wheel-mid": { "width": 136, "height": 136 }
+			"wheel-mid": { "width": 136, "height": 136 }
 		},
 		"wheel-mid6": {
-			"images/wheel-mid": { "width": 136, "height": 136 }
+			"wheel-mid": { "width": 136, "height": 136 }
 		},
 		"wheel-small": {
-			"images/wheel-small": { "width": 71, "height": 71 }
+			"wheel-small": { "width": 71, "height": 71 }
 		},
 		"wheel-small2": {
-			"images/wheel-small": { "width": 71, "height": 71 }
+			"wheel-small": { "width": 71, "height": 71 }
 		},
 		"wheel-small3": {
-			"images/wheel-small": { "width": 71, "height": 71 }
+			"wheel-small": { "width": 71, "height": 71 }
 		}
 	}
 },

BIN
examples/tank/export/tank.skel


BIN
examples/tank/tank.spine


+ 9 - 9
spine-xna/example/data/star.atlas → examples/test/export/test-pma.atlas

@@ -1,20 +1,20 @@
 
-star.png
-size: 256,128
+test-pma.png
+size: 256,64
 format: RGBA8888
 filter: Linear,Linear
 repeat: none
-star
+logo
   rotate: false
-  xy: 127, 52
-  size: 76, 72
-  orig: 76, 72
+  xy: 193, 2
+  size: 60, 60
+  orig: 60, 60
   offset: 0, 0
   index: -1
-token
+spine
   rotate: false
   xy: 2, 2
-  size: 123, 122
-  orig: 123, 122
+  size: 189, 60
+  orig: 189, 60
   offset: 0, 0
   index: -1

BIN
examples/test/export/test-pma.png


+ 20 - 0
examples/test/export/test.atlas

@@ -0,0 +1,20 @@
+
+test.png
+size: 256,64
+format: RGBA8888
+filter: Linear,Linear
+repeat: none
+logo
+  rotate: false
+  xy: 193, 2
+  size: 60, 60
+  orig: 60, 60
+  offset: 0, 0
+  index: -1
+spine
+  rotate: false
+  xy: 2, 2
+  size: 189, 60
+  orig: 189, 60
+  offset: 0, 0
+  index: -1

+ 278 - 0
examples/test/export/test.json

@@ -0,0 +1,278 @@
+{
+"skeleton": { "hash": "xbu5IFg+2tCx4+2MavNPurEogzA", "spine": "3.4.02", "width": 1333.78, "height": 1112.91, "images": "./images/" },
+"bones": [
+	{ "name": "root", "x": 28.68, "y": -105.71 },
+	{ "name": "attachment", "parent": "root", "x": -267.71, "y": -366.62 },
+	{ "name": "color", "parent": "root", "x": -298.29, "y": 44.1 },
+	{ "name": "draworder", "parent": "root", "x": 283.53, "y": -356.27 },
+	{ "name": "mesh", "parent": "root", "x": -320.74, "y": 413.7 },
+	{ "name": "meshweighted", "parent": "root", "rotation": -11.22, "x": -353.28, "y": 627.53 },
+	{ "name": "pathfollower", "parent": "root", "x": 177.52, "y": 56.62 },
+	{ "name": "rotate", "parent": "root", "x": -305, "y": 201 },
+	{ "name": "scale", "parent": "root", "x": 183.99, "y": -138 },
+	{ "name": "shear", "parent": "root", "x": -304, "y": -146 },
+	{ "name": "transformconstrainttarget", "parent": "root", "x": 604.27, "y": 420.7, "color": "abe323ff" },
+	{ "name": "transformconstrained", "parent": "root", "x": 169.6, "y": 420.7 },
+	{ "name": "translate", "parent": "root", "x": 190.99, "y": 201, "color": "abe323ff" }
+],
+"slots": [
+	{ "name": "images/spine", "bone": "translate", "attachment": "images/spine" },
+	{ "name": "images/spine2", "bone": "rotate", "attachment": "images/spine" },
+	{ "name": "images/spine3", "bone": "scale", "attachment": "images/spine" },
+	{ "name": "images/spine4", "bone": "shear", "attachment": "images/spine" },
+	{ "name": "images/spine5", "bone": "color", "attachment": "images/spine" },
+	{ "name": "path2", "bone": "root", "attachment": "path" },
+	{ "name": "images/spine6", "bone": "pathfollower", "attachment": "images/spine" },
+	{ "name": "images/spine7", "bone": "transformconstrained", "attachment": "images/spine" },
+	{ "name": "images/spine8", "bone": "transformconstrainttarget", "attachment": "images/spine" },
+	{ "name": "images/spine9", "bone": "mesh", "attachment": "images/spine" },
+	{ "name": "images/spine10", "bone": "attachment", "attachment": "images/logo" },
+	{ "name": "draworder2", "bone": "draworder", "attachment": "images/logo" },
+	{ "name": "draworder1", "bone": "draworder", "attachment": "images/spine" },
+	{ "name": "images/spine12", "bone": "meshweighted", "attachment": "linkedmesh" }
+],
+"transform": [
+	{
+		"name": "transformconstraint",
+		"bones": [ "transformconstrained" ],
+		"target": "transformconstrainttarget",
+		"x": -400,
+		"rotateMix": 0.509,
+		"translateMix": 0.509,
+		"scaleMix": 0.509,
+		"shearMix": 0.509
+	}
+],
+"path": [
+	{
+		"name": "pathconstraint",
+		"bones": [ "pathfollower" ],
+		"target": "path2",
+		"rotation": 34.2
+	}
+],
+"skins": {
+	"default": {
+		"draworder1": {
+			"images/spine": { "path": "spine", "width": 377, "height": 120 }
+		},
+		"draworder2": {
+			"images/logo": { "path": "logo", "width": 120, "height": 120 }
+		},
+		"images/spine": {
+			"images/spine": { "path": "spine", "width": 377, "height": 120 }
+		},
+		"images/spine10": {
+			"images/logo": { "path": "logo", "width": 120, "height": 120 },
+			"images/spine": { "path": "spine", "width": 377, "height": 120 }
+		},
+		"images/spine12": {
+			"images/spine": {
+				"type": "mesh",
+				"path": "spine",
+				"uvs": [ 0, 0, 0.25, 0, 0.5, 0, 0.75, 0, 1, 0, 1, 0.25, 1, 0.5, 1, 0.75, 1, 1, 0.75, 1, 0.5, 1, 0.25, 1, 0, 1, 0, 0.75, 0, 0.5, 0, 0.25, 0.25, 0.25, 0.25, 0.5, 0.25, 0.75, 0.5, 0.25, 0.5, 0.5, 0.5, 0.75, 0.75, 0.25, 0.75, 0.5, 0.75, 0.75 ],
+				"triangles": [ 15, 0, 1, 16, 1, 2, 15, 1, 16, 19, 2, 3, 16, 2, 19, 22, 3, 4, 19, 3, 22, 22, 4, 5, 14, 15, 16, 17, 16, 19, 14, 16, 17, 20, 19, 22, 17, 19, 20, 23, 22, 5, 20, 22, 23, 23, 5, 6, 13, 14, 17, 18, 17, 20, 13, 17, 18, 21, 20, 23, 18, 20, 21, 24, 23, 6, 21, 23, 24, 24, 6, 7, 12, 13, 18, 11, 18, 21, 12, 18, 11, 10, 21, 24, 11, 21, 10, 9, 24, 7, 10, 24, 9, 9, 7, 8 ],
+				"vertices": [ 1, 5, -194.67, 21.29, 1, 1, 5, -102.08, 38.91, 1, 1, 5, -9.49, 56.54, 1, 1, 5, 83.08, 74.16, 1, 1, 5, 175.67, 91.79, 1, 1, 5, 181.28, 62.32, 1, 1, 5, 186.89, 32.84, 1, 1, 5, 192.5, 3.38, 1, 1, 5, 198.11, -26.09, 1, 1, 5, 105.52, -43.71, 1, 1, 5, 12.94, -61.33, 1, 1, 5, -79.64, -78.96, 1, 1, 5, -172.23, -96.58, 1, 1, 5, -177.84, -67.11, 1, 1, 5, -183.45, -37.64, 1, 1, 5, -189.06, -8.17, 1, 1, 5, -96.47, 9.45, 1, 1, 5, -90.86, -20.01, 1, 1, 5, -85.25, -49.48, 1, 1, 5, -3.88, 27.07, 1, 1, 5, 1.72, -2.39, 1, 1, 5, 7.33, -31.86, 1, 1, 5, 88.7, 44.69, 1, 1, 5, 94.31, 15.22, 1, 1, 5, 99.92, -14.24, 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": 377,
+				"height": 120
+			},
+			"linkedmesh": { "type": "linkedmesh", "path": "logo", "parent": "images/spine", "width": 120, "height": 120 }
+		},
+		"images/spine2": {
+			"images/spine": { "path": "spine", "width": 377, "height": 120 }
+		},
+		"images/spine3": {
+			"images/spine": { "path": "spine", "width": 377, "height": 120 }
+		},
+		"images/spine4": {
+			"images/spine": { "path": "spine", "rotation": 0.15, "width": 377, "height": 120 }
+		},
+		"images/spine5": {
+			"images/spine": { "path": "spine", "width": 377, "height": 120 }
+		},
+		"images/spine6": {
+			"images/spine": { "path": "spine", "width": 377, "height": 120 }
+		},
+		"images/spine7": {
+			"images/spine": { "path": "spine", "width": 377, "height": 120 }
+		},
+		"images/spine8": {
+			"images/spine": { "path": "spine", "width": 377, "height": 120 }
+		},
+		"images/spine9": {
+			"images/spine": {
+				"type": "mesh",
+				"path": "spine",
+				"uvs": [ 1, 0.50124, 1, 1, 0.72412, 1, 0.49981, 1, 0.28581, 1, 0, 1, 0, 0.50124, 0, 0, 0.49207, 0, 1, 0, 0.56941, 0.57414, 0.84014, 0.50124, 0.61841, 0.22584, 0.20589, 0.20154, 0.19558, 0.67134, 0.39152, 0.86574, 0.3941, 0.41214, 0.3941, 0.12864, 0.76021, 0.19344, 0.76537, 0.59034, 0.74474, 0.84144, 0.57716, 0.81714 ],
+				"triangles": [ 17, 7, 8, 18, 8, 9, 13, 7, 17, 12, 8, 18, 17, 8, 12, 16, 17, 12, 13, 17, 16, 6, 7, 13, 6, 13, 16, 18, 9, 0, 11, 18, 0, 10, 16, 12, 12, 18, 11, 10, 12, 11, 19, 10, 11, 14, 6, 16, 14, 16, 10, 21, 10, 19, 15, 14, 10, 20, 21, 19, 21, 15, 10, 5, 6, 14, 4, 5, 14, 15, 4, 14, 3, 15, 21, 4, 15, 3, 2, 21, 20, 3, 21, 2, 19, 11, 0, 0, 20, 19, 1, 20, 0, 2, 20, 1 ],
+				"vertices": [ 191.41, -1.12, 191.41, -60.97, 87.4, -60.97, 2.84, -60.97, -77.82, -60.97, -185.58, -60.97, -185.58, -1.12, -185.58, 59.02, -0.07, 59.02, 191.41, 59.02, 29.09, -9.85, 131.14, -1.12, 47.55, 31.92, -107.96, 34.84, -111.85, -21.53, -37.97, -44.86, -37, 9.57, -37, 43.59, 101.01, 35.81, 102.96, -11.81, 95.18, -41.93, 32, -39.02 ],
+				"hull": 10,
+				"edges": [ 10, 12, 12, 14, 14, 16, 16, 18, 2, 0, 0, 18, 6, 8, 8, 10, 2, 4, 4, 6 ],
+				"width": 377,
+				"height": 120
+			}
+		},
+		"path2": {
+			"path": {
+				"type": "path",
+				"closed": true,
+				"lengths": [ 128.85, 310.24, 465.06, 600.88, 773.97 ],
+				"vertexCount": 15,
+				"vertices": [ 258.07, -42.67, 291.94, -17.53, 326.41, 7.22, 391.41, 2.75, 398.05, 46.72, 399.83, 84.07, 274.03, 106.4, 236.7, 117.74, 199.37, 129.09, 116.55, 135.12, 84.41, 115.47, 50.34, 94.04, 56.53, 1.48, 89.01, -5.59, 122.89, -13.58 ]
+			}
+		}
+	}
+},
+"animations": {
+	"animation": {
+		"slots": {
+			"images/spine5": {
+				"color": [
+					{ "time": 0, "color": "ffffffff" },
+					{ "time": 0.4333, "color": "ff0901ff" },
+					{ "time": 0.9, "color": "2dff00ff" },
+					{ "time": 1.3333, "color": "ffffffff" }
+				]
+			},
+			"images/spine10": {
+				"attachment": [
+					{ "time": 0, "name": "images/spine" },
+					{ "time": 0.6666, "name": "images/logo" },
+					{ "time": 1.3333, "name": "images/spine" }
+				]
+			},
+			"images/spine12": {
+				"attachment": [
+					{ "time": 0, "name": "images/spine" },
+					{ "time": 0.6666, "name": "linkedmesh" }
+				]
+			}
+		},
+		"bones": {
+			"translate": {
+				"translate": [
+					{
+						"time": 0,
+						"x": 0,
+						"y": 0,
+						"curve": [ 1, 0, 0, 1 ]
+					},
+					{ "time": 0.6666, "x": 96.99, "y": -151 },
+					{ "time": 1.3333, "x": 0, "y": 0 }
+				]
+			},
+			"scale": {
+				"scale": [
+					{ "time": 0, "x": 1, "y": 1 },
+					{ "time": 0.6666, "x": 1, "y": 2.34 },
+					{ "time": 1.3333, "x": 1, "y": 1 }
+				]
+			},
+			"rotate": {
+				"rotate": [
+					{ "time": 0, "angle": 0 },
+					{ "time": 0.6666, "angle": -125.34 },
+					{ "time": 1.3333, "angle": 0 }
+				]
+			},
+			"shear": {
+				"shear": [
+					{ "time": 0, "x": 0, "y": 0 },
+					{ "time": 0.6666, "x": 29.4, "y": 0 },
+					{ "time": 1.3333, "x": 0, "y": 0 }
+				]
+			},
+			"transformconstrainttarget": {
+				"rotate": [
+					{ "time": 0, "angle": 0 },
+					{ "time": 0.6666, "angle": -74.6 },
+					{ "time": 1.3333, "angle": 0 }
+				],
+				"translate": [
+					{ "time": 0, "x": 0, "y": 0 },
+					{ "time": 0.6666, "x": 176.22, "y": -170.34 },
+					{ "time": 1.3333, "x": 0, "y": 0 }
+				],
+				"scale": [
+					{ "time": 0, "x": 1, "y": 1 },
+					{ "time": 0.6666, "x": 2, "y": 2 },
+					{ "time": 1.3333, "x": 1, "y": 1 }
+				],
+				"shear": [
+					{ "time": 0, "x": 0, "y": 0 },
+					{ "time": 0.6666, "x": 23.4, "y": 0 },
+					{ "time": 1.3333, "x": 0, "y": 0 }
+				]
+			}
+		},
+		"transform": {
+			"transformconstraint": [
+				{ "time": 0, "rotateMix": 0.509, "translateMix": 0.509, "scaleMix": 0.509, "shearMix": 0.509 },
+				{ "time": 0.6666 },
+				{ "time": 1.3333, "rotateMix": 0.5, "translateMix": 0.5, "scaleMix": 0.5, "shearMix": 0.5 }
+			]
+		},
+		"paths": {
+			"pathconstraint": {
+				"position": [
+					{ "time": 0 },
+					{ "time": 1.3333, "position": 1 }
+				],
+				"spacing": [
+					{ "time": 0, "spacing": 40.1 },
+					{ "time": 1.3333 }
+				],
+				"mix": [
+					{ "time": 0.6666, "rotateMix": 0.473, "translateMix": 0.473 },
+					{ "time": 1.3333 }
+				]
+			}
+		},
+		"deform": {
+			"default": {
+				"images/spine9": {
+					"images/spine": [
+						{ "time": 0 },
+						{
+							"time": 0.6666,
+							"vertices": [ 43.09784, 58.11693, 0, 0, 0, 0, -0.653, -57.46399, -50.93396, -47.01593, -43.098, -24.81398, -43.098, -24.81399, -1.0E-5, 1.0E-5, 0, 1.0E-5, 43.09784, 58.11695, 0, 0, 43.09784, 58.11693, 1.0E-5, -1.0E-5, 0, 0, -43.09797, -24.81399, 0, 1.0E-5, 0, 0, 0, 0, 43.09784, 58.11694, 43.09784, 58.11693 ]
+						},
+						{ "time": 1.3333 }
+					]
+				},
+				"images/spine12": {
+					"images/spine": [
+						{ "time": 0 },
+						{
+							"time": 0.3333,
+							"offset": 4,
+							"vertices": [ -9.45232, 83.5133, -3.90008, 44.76635, -3.90008, 44.76635, -3.90008, 44.76635, 0, 0, 0, 0, 0, 0, 0, 0, 5.15667, -29.57763, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.90008, 44.76635 ]
+						},
+						{ "time": 0.6666 },
+						{
+							"time": 0.6679,
+							"vertices": [ -1.21159, -14.52716, -2.76092, -7.75683, -4.30999, -0.98669, 2.38385, 9.78289, -1.56903, 5.49316, -2.93444, 6.75128, -4.30011, 8.00933, -5.66552, 9.2677, -7.031, 10.52575, -3.07855, 14.81561, 4.30986, 0.9859, 5.85907, -5.78436, 7.40826, -12.55462, 5.25317, -13.04797, 3.09832, -13.54083, 0.94323, -14.03411, -0.60595, -7.26379, 1.54907, -6.77056, 3.70422, -6.27746, -2.15495, -0.49346, 0, -3.0E-4, 2.15495, 0.49273, 1.01812, 11.04132, -0.3471, 12.29895, -1.71313, 13.557 ]
+						},
+						{
+							"time": 1.3333,
+							"vertices": [ -10.57342, 25.16797, -9.16716, 14.48486, -7.76074, 3.80212, 131.25482, 21.05285, 128.23181, -0.04534, 121.51611, 0.91668, 114.80023, 1.8789, 108.08459, 2.84124, 101.3689, 3.80316, 104.39154, 24.90191, -21.3623, 2.01171, -22.76855, 12.69433, -24.17505, 23.37719, -20.77471, 23.82476, -17.37414, 24.27276, -13.97393, 24.72009, -12.56768, 14.03753, -15.96789, 13.58978, -19.36809, 13.14215, -11.16095, 3.35455, -14.56134, 2.90704, -17.96167, 2.45922, 124.53894, 22.01538, 117.82336, 22.97705, 111.10718, 23.93933 ]
+						}
+					]
+				}
+			}
+		},
+		"drawOrder": [
+			{ "time": 0 },
+			{
+				"time": 0.6666,
+				"offsets": [
+					{ "slot": "draworder2", "offset": 1 }
+				]
+			},
+			{ "time": 1.3333 }
+		]
+	}
+}
+}

BIN
examples/test/export/test.png


BIN
examples/test/export/test.skel


BIN
examples/test/images/logo.png


BIN
examples/test/images/spine.png


BIN
examples/test/test.spine


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 15 - 15
examples/vine/export/vine.json


BIN
examples/vine/export/vine.skel


BIN
examples/vine/vine.spine


+ 15 - 16
spine-as3/LICENSE

@@ -1,17 +1,16 @@
-Spine Runtimes Software License
-Version 2.3
+Spine Runtimes Software License v2.5
 
-Copyright (c) 2013-2015, Esoteric Software
+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 (the "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 otherwise create derivative works, improvements of the
-Software or develop new applications using the Software or (b) remove,
-delete, alter or obscure any trademarks or any copyright, trademark, patent
+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.
@@ -21,8 +20,8 @@ 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; LOSS OF USE, DATA, OR PROFITS;
-OR BUSINESS INTERRUPTION) 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.
+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.

+ 1 - 1
spine-as3/README.md

@@ -10,7 +10,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f
 
 ## Spine version
 
-spine-as3 works with data exported from the latest Spine version.
+spine-as3 works with data exported from the latest, non-beta Spine version.
 
 spine-as3 supports all Spine features, including meshes. If using the `spine.flash` classes for rendering, meshes are not supported.
 

BIN
spine-as3/spine-as3-example/lib/spine-as3.swc


+ 93 - 94
spine-as3/spine-as3-example/src/spine/examples/Main.as

@@ -1,97 +1,96 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.examples {
-
-import flash.display.Sprite;
-
-import spine.*;
-import spine.animation.AnimationStateData;
-import spine.atlas.Atlas;
-import spine.attachments.AtlasAttachmentLoader;
-import spine.flash.FlashTextureLoader;
-import spine.flash.SkeletonAnimation;
-
-[SWF(width = "800", height = "600", frameRate = "60", backgroundColor = "#dddddd")]
-public class Main extends Sprite {
-	[Embed(source = "/spineboy.atlas", mimeType = "application/octet-stream")]
-	static public const SpineboyAtlas:Class;
-
-	[Embed(source = "/spineboy.png")]
-	static public const SpineboyAtlasTexture:Class;
-
-	[Embed(source = "/spineboy.json", mimeType = "application/octet-stream")]
-	static public const SpineboyJson:Class;
-
-	private var skeleton:SkeletonAnimation;
-
-	public function Main () {
-		var atlas:Atlas = new Atlas(new SpineboyAtlas(), new FlashTextureLoader(new SpineboyAtlasTexture()));
-		var json:SkeletonJson = new SkeletonJson(new AtlasAttachmentLoader(atlas));
-		json.scale = 0.6;
-		var skeletonData:SkeletonData = json.readSkeletonData(new SpineboyJson());
-
-		var stateData:AnimationStateData = new AnimationStateData(skeletonData);
-		stateData.setMixByName("walk", "jump", 0.2);
-		stateData.setMixByName("jump", "run", 0.4);
-		stateData.setMixByName("jump", "jump", 0.2);
-
-		skeleton = new SkeletonAnimation(skeletonData, stateData);
-		skeleton.x = 400;
-		skeleton.y = 560;
-		
-		skeleton.state.onStart.add(function (trackIndex:int) : void {
-			trace(trackIndex + " fuu start: " + skeleton.state.getCurrent(trackIndex));
-		});
-		skeleton.state.onEnd.add(function (trackIndex:int) : void {
-			trace(trackIndex + " end: " + skeleton.state.getCurrent(trackIndex));
-		});
-		skeleton.state.onComplete.add(function (trackIndex:int, count:int) : void {
-			trace(trackIndex + " complete: " + skeleton.state.getCurrent(trackIndex) + ", " + count);
-		});
-		skeleton.state.onEvent.add(function (trackIndex:int, event:Event) : void {
-			trace(trackIndex + " event: " + skeleton.state.getCurrent(trackIndex) + ", "
-				+ event.data.name + ": " + event.intValue + ", " + event.floatValue + ", " + event.stringValue);
-		});
-		
-		if (false) {
-			skeleton.state.setAnimationByName(0, "test", true);
-		} else {
-			skeleton.state.setAnimationByName(0, "walk", true);
-			skeleton.state.addAnimationByName(0, "jump", false, 3);
-			skeleton.state.addAnimationByName(0, "run", true, 0);
-		}
-
-		addChild(skeleton);
-	}
-}
-
+package spine.examples {
+
+import flash.display.Sprite;
+
+import spine.*;
+import spine.animation.AnimationStateData;
+import spine.atlas.Atlas;
+import spine.attachments.AtlasAttachmentLoader;
+import spine.flash.FlashTextureLoader;
+import spine.flash.SkeletonAnimation;
+
+[SWF(width = "800", height = "600", frameRate = "60", backgroundColor = "#dddddd")]
+public class Main extends Sprite {
+	[Embed(source = "/spineboy.atlas", mimeType = "application/octet-stream")]
+	static public const SpineboyAtlas:Class;
+
+	[Embed(source = "/spineboy.png")]
+	static public const SpineboyAtlasTexture:Class;
+
+	[Embed(source = "/spineboy.json", mimeType = "application/octet-stream")]
+	static public const SpineboyJson:Class;
+
+	private var skeleton:SkeletonAnimation;
+
+	public function Main () {
+		var atlas:Atlas = new Atlas(new SpineboyAtlas(), new FlashTextureLoader(new SpineboyAtlasTexture()));
+		var json:SkeletonJson = new SkeletonJson(new AtlasAttachmentLoader(atlas));
+		json.scale = 0.6;
+		var skeletonData:SkeletonData = json.readSkeletonData(new SpineboyJson());
+
+		var stateData:AnimationStateData = new AnimationStateData(skeletonData);
+		stateData.setMixByName("walk", "jump", 0.2);
+		stateData.setMixByName("jump", "run", 0.4);
+		stateData.setMixByName("jump", "jump", 0.2);
+
+		skeleton = new SkeletonAnimation(skeletonData, stateData);
+		skeleton.x = 400;
+		skeleton.y = 560;
+		
+		skeleton.state.onStart.add(function (trackIndex:int) : void {
+			trace(trackIndex + " fuu start: " + skeleton.state.getCurrent(trackIndex));
+		});
+		skeleton.state.onEnd.add(function (trackIndex:int) : void {
+			trace(trackIndex + " end: " + skeleton.state.getCurrent(trackIndex));
+		});
+		skeleton.state.onComplete.add(function (trackIndex:int, count:int) : void {
+			trace(trackIndex + " complete: " + skeleton.state.getCurrent(trackIndex) + ", " + count);
+		});
+		skeleton.state.onEvent.add(function (trackIndex:int, event:Event) : void {
+			trace(trackIndex + " event: " + skeleton.state.getCurrent(trackIndex) + ", "
+				+ event.data.name + ": " + event.intValue + ", " + event.floatValue + ", " + event.stringValue);
+		});
+		
+		if (false) {
+			skeleton.state.setAnimationByName(0, "test", true);
+		} else {
+			skeleton.state.setAnimationByName(0, "walk", true);
+			skeleton.state.addAnimationByName(0, "jump", false, 3);
+			skeleton.state.addAnimationByName(0, "run", true, 0);
+		}
+
+		addChild(skeleton);
+	}
+}
+
 }

+ 1 - 1
spine-as3/spine-as3-example/src/spineboy.json

@@ -1,5 +1,5 @@
 {
-"skeleton": { "hash": "rPoYyBLFG6F0CGZ5wsUEBKDJU9U", "spine": "3.4.00", "width": 0, "height": 0, "images": "./images/" },
+"skeleton": { "hash": "rPoYyBLFG6F0CGZ5wsUEBKDJU9U", "spine": "3.4.02", "width": 470.9, "height": 731.49, "images": "./images/" },
 "bones": [
 	{ "name": "hip", "y": 247.47 },
 	{ "name": "torso", "parent": "hip", "length": 127.55, "rotation": 103.82, "x": -1.61, "y": 4.9, "color": "e0da19ff" },

+ 43 - 44
spine-as3/spine-as3/src/spine/BlendMode.as

@@ -1,47 +1,46 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public class BlendMode {
-	public static const normal:BlendMode = new BlendMode(0);
-	public static const additive:BlendMode = new BlendMode(1);
-	public static const multiply:BlendMode = new BlendMode(2);
-	public static const screen:BlendMode = new BlendMode(3);
-
-	public var ordinal:int;
-
-	public function BlendMode (ordinal:int) {
-		this.ordinal = ordinal;
-	}
-}
-
+package spine {
+
+public class BlendMode {
+	public static const normal:BlendMode = new BlendMode(0);
+	public static const additive:BlendMode = new BlendMode(1);
+	public static const multiply:BlendMode = new BlendMode(2);
+	public static const screen:BlendMode = new BlendMode(3);
+
+	public var ordinal:int;
+
+	public function BlendMode (ordinal:int) {
+		this.ordinal = ordinal;
+	}
+}
+
 }

+ 353 - 354
spine-as3/spine-as3/src/spine/Bone.as

@@ -1,357 +1,356 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public class Bone implements Updatable {
-	static public var yDown:Boolean;
-
-	internal var _data:BoneData;
-	internal var _skeleton:Skeleton;
-	internal var _parent:Bone;
-	internal var _children:Vector.<Bone> = new Vector.<Bone>();
-	public var x:Number;
-	public var y:Number;
-	public var rotation:Number;
-	public var scaleX:Number;
-	public var scaleY:Number;
-	public var shearX:Number;
-	public var shearY:Number;
-	public var appliedRotation:Number;	
-
-	internal var _a:Number;
-	internal var _b:Number;
-	internal var _c:Number;
-	internal var _d:Number;
-	internal var _worldX:Number;
-	internal var _worldY:Number;
-	internal var _worldSignX:Number;
-	internal var _worldSignY:Number;
-	
-	internal var _sorted:Boolean;
-
-	/** @param parent May be null. */
-	public function Bone (data:BoneData, skeleton:Skeleton, parent:Bone) {
-		if (data == null) throw new ArgumentError("data cannot be null.");
-		if (skeleton == null) throw new ArgumentError("skeleton cannot be null.");
-		_data = data;
-		_skeleton = skeleton;
-		_parent = parent;
-		setToSetupPose();
-	}
-	
-	/** Same as updateWorldTransform(). This method exists for Bone to implement Updatable. */
-	public function update () : void {
-		updateWorldTransformWith(x, y, rotation, scaleX, scaleY, shearX, shearY);
-	}
-
-	/** Computes the world SRT using the parent bone and this bone's local SRT. */
-	public function updateWorldTransform () : void {
-		updateWorldTransformWith(x, y, rotation, scaleX, scaleY, shearX, shearY);
-	}
-
-	/** Computes the world SRT using the parent bone and the specified local SRT. */
-	public function updateWorldTransformWith (x:Number, y:Number, rotation:Number, scaleX:Number, scaleY:Number, shearX:Number, shearY:Number) : void {
-		appliedRotation = rotation;
-
-		var rotationY:Number = rotation + 90 + shearY;
-		var la:Number = MathUtils.cosDeg(rotation + shearX) * scaleX, lb:Number = MathUtils.cosDeg(rotationY) * scaleY;
-		var lc:Number = MathUtils.sinDeg(rotation + shearX) * scaleX, ld:Number = MathUtils.sinDeg(rotationY) * scaleY;
-		
-		var parent:Bone = _parent;
-		if (!parent) { // Root bone.
-			var skeleton:Skeleton = _skeleton;
-			if (skeleton.flipX) {
-				x = -x;
-				la = -la;
-				lb = -lb;
-			}
-			if (skeleton.flipY != yDown) {
-				y = -y;
-				lc = -lc;
-				ld = -ld;
-			}
-			_a = la;
-			_b = lb;
-			_c = lc;
-			_d = ld;
-			_worldX = x;
-			_worldY = y;
-			_worldSignX = scaleX < 0 ? -1 : 1;
-			_worldSignY = scaleY < 0 ? -1 : 1;
-			return;
-		}
-
-		var pa:Number = parent._a, pb:Number = parent._b, pc:Number = parent._c, pd:Number = parent._d;
-		_worldX = pa * x + pb * y + parent._worldX;
-		_worldY = pc * x + pd * y + parent._worldY;
-		_worldSignX = parent._worldSignX * (scaleX < 0 ? -1 : 1);
-		_worldSignY = parent._worldSignY * (scaleY < 0 ? -1 : 1);
-
-		if (data.inheritRotation && data.inheritScale) {
-			_a = pa * la + pb * lc;
-			_b = pa * lb + pb * ld;
-			_c = pc * la + pd * lc;
-			_d = pc * lb + pd * ld;
-		} else {
-			if (data.inheritRotation) { // No scale inheritance.
-				pa = 1;
-				pb = 0;
-				pc = 0;
-				pd = 1;
-				do {
-					var cos:Number = MathUtils.cosDeg(parent.appliedRotation), sin:Number = MathUtils.sinDeg(parent.appliedRotation);
-					var temp:Number = pa * cos + pb * sin;
-					pb = pb * cos - pa * sin;
-					pa = temp;
-					temp = pc * cos + pd * sin;
-					pd = pd * cos - pc * sin;
-					pc = temp;
-	
-					if (!parent.data.inheritRotation) break;
-					parent = parent.parent;
-				} while (parent != null);
-				_a = pa * la + pb * lc;
-				_b = pa * lb + pb * ld;
-				_c = pc * la + pd * lc;
-				_d = pc * lb + pd * ld;
-			} else if (data.inheritScale) { // No rotation inheritance.
-				pa = 1;
-				pb = 0;
-				pc = 0;
-				pd = 1;
-				do {
-					cos = MathUtils.cosDeg(parent.appliedRotation), sin = MathUtils.sinDeg(parent.appliedRotation);
-					var psx:Number = parent.scaleX, psy:Number = parent.scaleY;
-					var za:Number = cos * psx, zb:Number = sin * psy, zc:Number = sin * psx, zd:Number = cos * psy;
-					temp = pa * za + pb * zc;
-					pb = pb * zd - pa * zb;
-					pa = temp;
-					temp = pc * za + pd * zc;
-					pd = pd * zd - pc * zb;
-					pc = temp;
-
-					if (psx >= 0) sin = -sin;
-					temp = pa * cos + pb * sin;
-					pb = pb * cos - pa * sin;
-					pa = temp;
-					temp = pc * cos + pd * sin;
-					pd = pd * cos - pc * sin;
-					pc = temp;
-	
-					if (!parent.data.inheritScale) break;
-					parent = parent.parent;
-				} while (parent != null);
-				_a = pa * la + pb * lc;
-				_b = pa * lb + pb * ld;
-				_c = pc * la + pd * lc;
-				_d = pc * lb + pd * ld;
-			} else {
-				_a = la;
-				_b = lb;
-				_c = lc;
-				_d = ld;
-			}
-			if (_skeleton.flipX) {
-				_a = -_a;
-				_b = -_b;
-			}
-			if (_skeleton.flipY != yDown) {
-				_c = -_c;
-				_d = -_d;
-			}
-		}
-	}
-
-	public function setToSetupPose () : void {
-		x = _data.x;
-		y = _data.y;
-		rotation = _data.rotation;
-		scaleX = _data.scaleX;
-		scaleY = _data.scaleY;
-		shearX = _data.shearX;
-		shearY = _data.shearY;
-	}
-
-	public function get data () : BoneData {
-		return _data;
-	}
-	
-	public function get skeleton () : Skeleton {
-		return _skeleton;
-	}
-	
-	public function get parent () : Bone {
-		return _parent;
-	}
-	
-	public function get children () : Vector.<Bone> {;
-		return _children;
-	}
-
-	public function get a () : Number {
-		return _a;
-	}
-
-	public function get b () : Number {
-		return _b;
-	}
-
-	public function get c () : Number {
-		return _c;
-	}
-
-	public function get d () : Number {
-		return _d;
-	}
-
-	public function get worldX () : Number {
-		return _worldX;
-	}
-
-	public function get worldY () : Number {
-		return _worldY;
-	}
-
-	public function get worldSignX () : Number {
-		return _worldSignX;
-	}
-
-	public function get worldSignY () : Number {
-		return _worldSignY;
-	}
-
-	public function get worldRotationX () : Number {
-		return Math.atan2(_c, _a) * MathUtils.radDeg;
-	}
-
-	public function get worldRotationY () : Number {
-		return Math.atan2(_d, _b) * MathUtils.radDeg;
-	}
-
-	public function get worldScaleX () : Number {
-		return Math.sqrt(_a * _a + _b * _b) * _worldSignX;
-	}
-
-	public function get worldScaleY () : Number {
-		return Math.sqrt(_c * _c + _d * _d) * _worldSignY;
-	}
-	
-	public function worldToLocalRotationX () : Number {
-		var parent:Bone = _parent;
-		if (parent == null) return rotation;
-		var pa:Number = parent.a, pb:Number = parent.b, pc:Number = parent.c, pd:Number = parent.d, a:Number = this.a, c:Number = this.c;
-		return Math.atan2(pa * c - pc * a, pd * a - pb * c) * MathUtils.radDeg;
-	}
-
-	public function worldToLocalRotationY () : Number {
-		var parent:Bone = _parent;
-		if (parent == null) return rotation;
-		var pa:Number = parent.a, pb:Number = parent.b, pc:Number = parent.c, pd:Number = parent.d, b:Number = this.b, d:Number = this.d;
-		return Math.atan2(pa * d - pc * b, pd * b - pb * d) * MathUtils.radDeg;
-	}
-
-	public function rotateWorld (degrees:Number) : void {
-		var a:Number = this.a, b:Number = this.b, c:Number = this.c, d:Number = this.d;
-		var cos:Number = MathUtils.cosDeg(degrees), sin:Number = MathUtils.sinDeg(degrees);
-		this._a = cos * a - sin * c;
-		this._b = cos * b - sin * d;
-		this._c = sin * a + cos * c;
-		this._d = sin * b + cos * d;
-	}
-
-	/** Computes the local transform from the world transform. This can be useful to perform processing on the local transform
-	 * after the world transform has been modified directly (eg, by a constraint).
-	 * <p>
-	 * Some redundant information is lost by the world transform, such as -1,-1 scale versus 180 rotation. The computed local
-	 * transform values may differ from the original values but are functionally the same. */
-	public function updateLocalTransform () : void {
-		var parent:Bone = this.parent;
-		if (parent == null) {
-			x = worldX;
-			y = worldY;
-			rotation = Math.atan2(c, a) * MathUtils.radDeg;
-			scaleX = Math.sqrt(a * a + c * c);
-			scaleY = Math.sqrt(b * b + d * d);
-			var det:Number = a * d - b * c;
-			shearX = 0;
-			shearY = Math.atan2(a * b + c * d, det) * MathUtils.radDeg;
-			return;
-		}
-		var pa:Number = parent.a, pb:Number = parent.b, pc:Number = parent.c, pd:Number = parent.d;
-		var pid:Number = 1 / (pa * pd - pb * pc);
-		var dx:Number = worldX - parent.worldX, dy:Number = worldY - parent.worldY;
-		x = (dx * pd * pid - dy * pb * pid);
-		y = (dy * pa * pid - dx * pc * pid);
-		var ia:Number = pid * pd;
-		var id:Number = pid * pa;
-		var ib:Number = pid * pb;
-		var ic:Number = pid * pc;
-		var ra:Number = ia * a - ib * c;
-		var rb:Number = ia * b - ib * d;
-		var rc:Number = id * c - ic * a;
-		var rd:Number = id * d - ic * b;
-		shearX = 0;
-		scaleX = Math.sqrt(ra * ra + rc * rc);
-		if (scaleX > 0.0001) {
-			det = ra * rd - rb * rc;
-			scaleY = det / scaleX;
-			shearY = Math.atan2(ra * rb + rc * rd, det) * MathUtils.radDeg;
-			rotation = Math.atan2(rc, ra) * MathUtils.radDeg;
-		} else {
-			scaleX = 0;
-			scaleY = Math.sqrt(rb * rb + rd * rd);
-			shearY = 0;
-			rotation = 90 - Math.atan2(rd, rb) * MathUtils.radDeg;
-		}
-		appliedRotation = rotation;
-	}
-
-	public function worldToLocal (world:Vector.<Number>) : void {
-		var a:Number = _a, b:Number = _b, c:Number = _c, d:Number = _d;
-		var invDet:Number = 1 / (a * d - b * c);
-		var x:Number = world[0] - _worldX, y:Number = world[1] - _worldY;				
-		world[0] = (x * d * invDet - y * b * invDet);
-		world[1] = (y * a * invDet - x * c * invDet);
-	}
-
-	public function localToWorld (local:Vector.<Number>) : void {
-		var localX:Number = local[0], localY:Number = local[1];
-		local[0] = localX * _a + localY * _b + _worldX;
-		local[1] = localX * _c + localY * _d + _worldY;
-	}
-
-	public function toString () : String {
-		return _data._name;
-	}
-}
-
+package spine {
+
+public class Bone implements Updatable {
+	static public var yDown:Boolean;
+
+	internal var _data:BoneData;
+	internal var _skeleton:Skeleton;
+	internal var _parent:Bone;
+	internal var _children:Vector.<Bone> = new Vector.<Bone>();
+	public var x:Number;
+	public var y:Number;
+	public var rotation:Number;
+	public var scaleX:Number;
+	public var scaleY:Number;
+	public var shearX:Number;
+	public var shearY:Number;
+	public var appliedRotation:Number;	
+
+	internal var _a:Number;
+	internal var _b:Number;
+	internal var _c:Number;
+	internal var _d:Number;
+	internal var _worldX:Number;
+	internal var _worldY:Number;
+	internal var _worldSignX:Number;
+	internal var _worldSignY:Number;
+	
+	internal var _sorted:Boolean;
+
+	/** @param parent May be null. */
+	public function Bone (data:BoneData, skeleton:Skeleton, parent:Bone) {
+		if (data == null) throw new ArgumentError("data cannot be null.");
+		if (skeleton == null) throw new ArgumentError("skeleton cannot be null.");
+		_data = data;
+		_skeleton = skeleton;
+		_parent = parent;
+		setToSetupPose();
+	}
+	
+	/** Same as updateWorldTransform(). This method exists for Bone to implement Updatable. */
+	public function update () : void {
+		updateWorldTransformWith(x, y, rotation, scaleX, scaleY, shearX, shearY);
+	}
+
+	/** Computes the world SRT using the parent bone and this bone's local SRT. */
+	public function updateWorldTransform () : void {
+		updateWorldTransformWith(x, y, rotation, scaleX, scaleY, shearX, shearY);
+	}
+
+	/** Computes the world SRT using the parent bone and the specified local SRT. */
+	public function updateWorldTransformWith (x:Number, y:Number, rotation:Number, scaleX:Number, scaleY:Number, shearX:Number, shearY:Number) : void {
+		appliedRotation = rotation;
+
+		var rotationY:Number = rotation + 90 + shearY;
+		var la:Number = MathUtils.cosDeg(rotation + shearX) * scaleX, lb:Number = MathUtils.cosDeg(rotationY) * scaleY;
+		var lc:Number = MathUtils.sinDeg(rotation + shearX) * scaleX, ld:Number = MathUtils.sinDeg(rotationY) * scaleY;
+		
+		var parent:Bone = _parent;
+		if (!parent) { // Root bone.
+			var skeleton:Skeleton = _skeleton;
+			if (skeleton.flipX) {
+				x = -x;
+				la = -la;
+				lb = -lb;
+			}
+			if (skeleton.flipY != yDown) {
+				y = -y;
+				lc = -lc;
+				ld = -ld;
+			}
+			_a = la;
+			_b = lb;
+			_c = lc;
+			_d = ld;
+			_worldX = x;
+			_worldY = y;
+			_worldSignX = scaleX < 0 ? -1 : 1;
+			_worldSignY = scaleY < 0 ? -1 : 1;
+			return;
+		}
+
+		var pa:Number = parent._a, pb:Number = parent._b, pc:Number = parent._c, pd:Number = parent._d;
+		_worldX = pa * x + pb * y + parent._worldX;
+		_worldY = pc * x + pd * y + parent._worldY;
+		_worldSignX = parent._worldSignX * (scaleX < 0 ? -1 : 1);
+		_worldSignY = parent._worldSignY * (scaleY < 0 ? -1 : 1);
+
+		if (data.inheritRotation && data.inheritScale) {
+			_a = pa * la + pb * lc;
+			_b = pa * lb + pb * ld;
+			_c = pc * la + pd * lc;
+			_d = pc * lb + pd * ld;
+		} else {
+			if (data.inheritRotation) { // No scale inheritance.
+				pa = 1;
+				pb = 0;
+				pc = 0;
+				pd = 1;
+				do {
+					var cos:Number = MathUtils.cosDeg(parent.appliedRotation), sin:Number = MathUtils.sinDeg(parent.appliedRotation);
+					var temp:Number = pa * cos + pb * sin;
+					pb = pb * cos - pa * sin;
+					pa = temp;
+					temp = pc * cos + pd * sin;
+					pd = pd * cos - pc * sin;
+					pc = temp;
+	
+					if (!parent.data.inheritRotation) break;
+					parent = parent.parent;
+				} while (parent != null);
+				_a = pa * la + pb * lc;
+				_b = pa * lb + pb * ld;
+				_c = pc * la + pd * lc;
+				_d = pc * lb + pd * ld;
+			} else if (data.inheritScale) { // No rotation inheritance.
+				pa = 1;
+				pb = 0;
+				pc = 0;
+				pd = 1;
+				do {
+					cos = MathUtils.cosDeg(parent.appliedRotation), sin = MathUtils.sinDeg(parent.appliedRotation);
+					var psx:Number = parent.scaleX, psy:Number = parent.scaleY;
+					var za:Number = cos * psx, zb:Number = sin * psy, zc:Number = sin * psx, zd:Number = cos * psy;
+					temp = pa * za + pb * zc;
+					pb = pb * zd - pa * zb;
+					pa = temp;
+					temp = pc * za + pd * zc;
+					pd = pd * zd - pc * zb;
+					pc = temp;
+
+					if (psx >= 0) sin = -sin;
+					temp = pa * cos + pb * sin;
+					pb = pb * cos - pa * sin;
+					pa = temp;
+					temp = pc * cos + pd * sin;
+					pd = pd * cos - pc * sin;
+					pc = temp;
+	
+					if (!parent.data.inheritScale) break;
+					parent = parent.parent;
+				} while (parent != null);
+				_a = pa * la + pb * lc;
+				_b = pa * lb + pb * ld;
+				_c = pc * la + pd * lc;
+				_d = pc * lb + pd * ld;
+			} else {
+				_a = la;
+				_b = lb;
+				_c = lc;
+				_d = ld;
+			}
+			if (_skeleton.flipX) {
+				_a = -_a;
+				_b = -_b;
+			}
+			if (_skeleton.flipY != yDown) {
+				_c = -_c;
+				_d = -_d;
+			}
+		}
+	}
+
+	public function setToSetupPose () : void {
+		x = _data.x;
+		y = _data.y;
+		rotation = _data.rotation;
+		scaleX = _data.scaleX;
+		scaleY = _data.scaleY;
+		shearX = _data.shearX;
+		shearY = _data.shearY;
+	}
+
+	public function get data () : BoneData {
+		return _data;
+	}
+	
+	public function get skeleton () : Skeleton {
+		return _skeleton;
+	}
+	
+	public function get parent () : Bone {
+		return _parent;
+	}
+	
+	public function get children () : Vector.<Bone> {;
+		return _children;
+	}
+
+	public function get a () : Number {
+		return _a;
+	}
+
+	public function get b () : Number {
+		return _b;
+	}
+
+	public function get c () : Number {
+		return _c;
+	}
+
+	public function get d () : Number {
+		return _d;
+	}
+
+	public function get worldX () : Number {
+		return _worldX;
+	}
+
+	public function get worldY () : Number {
+		return _worldY;
+	}
+
+	public function get worldSignX () : Number {
+		return _worldSignX;
+	}
+
+	public function get worldSignY () : Number {
+		return _worldSignY;
+	}
+
+	public function get worldRotationX () : Number {
+		return Math.atan2(_c, _a) * MathUtils.radDeg;
+	}
+
+	public function get worldRotationY () : Number {
+		return Math.atan2(_d, _b) * MathUtils.radDeg;
+	}
+
+	public function get worldScaleX () : Number {
+		return Math.sqrt(_a * _a + _b * _b) * _worldSignX;
+	}
+
+	public function get worldScaleY () : Number {
+		return Math.sqrt(_c * _c + _d * _d) * _worldSignY;
+	}
+	
+	public function worldToLocalRotationX () : Number {
+		var parent:Bone = _parent;
+		if (parent == null) return rotation;
+		var pa:Number = parent.a, pb:Number = parent.b, pc:Number = parent.c, pd:Number = parent.d, a:Number = this.a, c:Number = this.c;
+		return Math.atan2(pa * c - pc * a, pd * a - pb * c) * MathUtils.radDeg;
+	}
+
+	public function worldToLocalRotationY () : Number {
+		var parent:Bone = _parent;
+		if (parent == null) return rotation;
+		var pa:Number = parent.a, pb:Number = parent.b, pc:Number = parent.c, pd:Number = parent.d, b:Number = this.b, d:Number = this.d;
+		return Math.atan2(pa * d - pc * b, pd * b - pb * d) * MathUtils.radDeg;
+	}
+
+	public function rotateWorld (degrees:Number) : void {
+		var a:Number = this.a, b:Number = this.b, c:Number = this.c, d:Number = this.d;
+		var cos:Number = MathUtils.cosDeg(degrees), sin:Number = MathUtils.sinDeg(degrees);
+		this._a = cos * a - sin * c;
+		this._b = cos * b - sin * d;
+		this._c = sin * a + cos * c;
+		this._d = sin * b + cos * d;
+	}
+
+	/** Computes the local transform from the world transform. This can be useful to perform processing on the local transform
+	 * after the world transform has been modified directly (eg, by a constraint).
+	 * <p>
+	 * Some redundant information is lost by the world transform, such as -1,-1 scale versus 180 rotation. The computed local
+	 * transform values may differ from the original values but are functionally the same. */
+	public function updateLocalTransform () : void {
+		var parent:Bone = this.parent;
+		if (parent == null) {
+			x = worldX;
+			y = worldY;
+			rotation = Math.atan2(c, a) * MathUtils.radDeg;
+			scaleX = Math.sqrt(a * a + c * c);
+			scaleY = Math.sqrt(b * b + d * d);
+			var det:Number = a * d - b * c;
+			shearX = 0;
+			shearY = Math.atan2(a * b + c * d, det) * MathUtils.radDeg;
+			return;
+		}
+		var pa:Number = parent.a, pb:Number = parent.b, pc:Number = parent.c, pd:Number = parent.d;
+		var pid:Number = 1 / (pa * pd - pb * pc);
+		var dx:Number = worldX - parent.worldX, dy:Number = worldY - parent.worldY;
+		x = (dx * pd * pid - dy * pb * pid);
+		y = (dy * pa * pid - dx * pc * pid);
+		var ia:Number = pid * pd;
+		var id:Number = pid * pa;
+		var ib:Number = pid * pb;
+		var ic:Number = pid * pc;
+		var ra:Number = ia * a - ib * c;
+		var rb:Number = ia * b - ib * d;
+		var rc:Number = id * c - ic * a;
+		var rd:Number = id * d - ic * b;
+		shearX = 0;
+		scaleX = Math.sqrt(ra * ra + rc * rc);
+		if (scaleX > 0.0001) {
+			det = ra * rd - rb * rc;
+			scaleY = det / scaleX;
+			shearY = Math.atan2(ra * rb + rc * rd, det) * MathUtils.radDeg;
+			rotation = Math.atan2(rc, ra) * MathUtils.radDeg;
+		} else {
+			scaleX = 0;
+			scaleY = Math.sqrt(rb * rb + rd * rd);
+			shearY = 0;
+			rotation = 90 - Math.atan2(rd, rb) * MathUtils.radDeg;
+		}
+		appliedRotation = rotation;
+	}
+
+	public function worldToLocal (world:Vector.<Number>) : void {
+		var a:Number = _a, b:Number = _b, c:Number = _c, d:Number = _d;
+		var invDet:Number = 1 / (a * d - b * c);
+		var x:Number = world[0] - _worldX, y:Number = world[1] - _worldY;				
+		world[0] = (x * d * invDet - y * b * invDet);
+		world[1] = (y * a * invDet - x * c * invDet);
+	}
+
+	public function localToWorld (local:Vector.<Number>) : void {
+		var localX:Number = local[0], localY:Number = local[1];
+		local[0] = localX * _a + localY * _b + _worldX;
+		local[1] = localX * _c + localY * _d + _worldY;
+	}
+
+	public function toString () : String {
+		return _data._name;
+	}
+}
+
 }

+ 72 - 73
spine-as3/spine-as3/src/spine/BoneData.as

@@ -1,76 +1,75 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public class BoneData {
-	internal var _index:int;
-	internal var _name:String;
-	internal var _parent:BoneData;
-	public var length:Number;
-	public var x:Number;
-	public var y:Number;
-	public var rotation:Number;
-	public var scaleX:Number = 1;
-	public var scaleY:Number = 1;
-	public var shearX:Number;
-	public var shearY:Number;	
-	public var inheritRotation:Boolean = true;
-	public var inheritScale:Boolean = true;
-
-	/** @param parent May be null. */
-	public function BoneData (index:int, name:String, parent:BoneData) {
-		if (index < 0) throw new ArgumentError("index must be >= 0");
-		if (name == null) throw new ArgumentError("name cannot be null.");
-		_index = index;
-		_name = name;
-		_parent = parent;
-	}
-	
-	public function get index () : int {
-		return _index;
-	}
-
-	public function get name () : String {
-		return _name;
-	}
-
-	/** @return May be null. */
-	public function get parent () : BoneData {
-		return _parent;
-	}
-
-	public function toString () : String {
-		return _name;
-	}
-}
-
+package spine {
+
+public class BoneData {
+	internal var _index:int;
+	internal var _name:String;
+	internal var _parent:BoneData;
+	public var length:Number;
+	public var x:Number;
+	public var y:Number;
+	public var rotation:Number;
+	public var scaleX:Number = 1;
+	public var scaleY:Number = 1;
+	public var shearX:Number;
+	public var shearY:Number;	
+	public var inheritRotation:Boolean = true;
+	public var inheritScale:Boolean = true;
+
+	/** @param parent May be null. */
+	public function BoneData (index:int, name:String, parent:BoneData) {
+		if (index < 0) throw new ArgumentError("index must be >= 0");
+		if (name == null) throw new ArgumentError("name cannot be null.");
+		_index = index;
+		_name = name;
+		_parent = parent;
+	}
+	
+	public function get index () : int {
+		return _index;
+	}
+
+	public function get name () : String {
+		return _name;
+	}
+
+	/** @return May be null. */
+	public function get parent () : BoneData {
+		return _parent;
+	}
+
+	public function toString () : String {
+		return _name;
+	}
+}
+
 }

+ 52 - 53
spine-as3/spine-as3/src/spine/Event.as

@@ -1,56 +1,55 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public class Event {
-	internal var _data:EventData;
-	public var time:Number;
-	public var intValue:int;
-	public var floatValue:Number;
-	public var stringValue:String;
-
-	public function Event (time:Number, data:EventData) {
-		if (data == null) throw new ArgumentError("data cannot be null.");
-		this.time = time;
-		_data = data;
-	}
-
-	public function get data () : EventData {
-		return _data;
-	}
-
-	public function toString () : String {
-		return _data._name;
-	}
-}
-
+package spine {
+
+public class Event {
+	internal var _data:EventData;
+	public var time:Number;
+	public var intValue:int;
+	public var floatValue:Number;
+	public var stringValue:String;
+
+	public function Event (time:Number, data:EventData) {
+		if (data == null) throw new ArgumentError("data cannot be null.");
+		this.time = time;
+		_data = data;
+	}
+
+	public function get data () : EventData {
+		return _data;
+	}
+
+	public function toString () : String {
+		return _data._name;
+	}
+}
+
 }

+ 50 - 51
spine-as3/spine-as3/src/spine/EventData.as

@@ -1,54 +1,53 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public class EventData {
-	internal var _name:String;
-	public var intValue:int;;
-	public var floatValue:Number;
-	public var stringValue:String;
-	
-	public function EventData (name:String) {
-		if (name == null) throw new ArgumentError("name cannot be null.");
-		_name = name;
-	}
-
-	public function get name () : String {
-		return _name;
-	}
-
-	public function toString () : String {
-		return _name;
-	}
-}
-
+package spine {
+
+public class EventData {
+	internal var _name:String;
+	public var intValue:int;;
+	public var floatValue:Number;
+	public var stringValue:String;
+	
+	public function EventData (name:String) {
+		if (name == null) throw new ArgumentError("name cannot be null.");
+		_name = name;
+	}
+
+	public function get name () : String {
+		return _name;
+	}
+
+	public function toString () : String {
+		return _name;
+	}
+}
+
 }

+ 227 - 228
spine-as3/spine-as3/src/spine/IkConstraint.as

@@ -1,231 +1,230 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public class IkConstraint implements Updatable {
-	internal var _data:IkConstraintData;
-	public var bones:Vector.<Bone>;
-	public var target:Bone;
-	public var mix:Number;
-	public var bendDirection:int;
-	
-	public var level:int;	
-
-	public function IkConstraint (data:IkConstraintData, skeleton:Skeleton) {
-		if (data == null) throw new ArgumentError("data cannot be null.");
-		if (skeleton == null) throw new ArgumentError("skeleton cannot be null.");
-		_data = data;
-		mix = data.mix;
-		bendDirection = data.bendDirection;
-
-		bones = new Vector.<Bone>();
-		for each (var boneData:BoneData in data.bones)
-			bones[bones.length] = skeleton.findBone(boneData.name);
-		target = skeleton.findBone(data.target._name);
-	}
-
-	public function apply () : void {
-		update();
-	}
-
-	public function update () : void {
-		switch (bones.length) {
-		case 1:
-			apply1(bones[0], target._worldX, target._worldY, mix);
-			break;
-		case 2:
-			apply2(bones[0], bones[1], target._worldX, target._worldY, bendDirection, mix);
-			break;
-		}
-	}
-
-	public function get data () : IkConstraintData {
-		return _data;
-	}
-
-	public function toString () : String {
-		return _data._name;
-	}
-	
-	/** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world
-	 * coordinate system. */
-	static public function apply1 (bone:Bone, targetX:Number, targetY:Number, alpha:Number) : void {
-		var pp:Bone = bone.parent;
-		var id:Number = 1 / (pp.a * pp.d - pp.b * pp.c);
-		var x:Number = targetX - pp.worldX, y:Number = targetY - pp.worldY;
-		var tx:Number = (x * pp.d - y * pp.b) * id - bone.x, ty:Number = (y * pp.a - x * pp.c) * id - bone.y;
-		var rotationIK:Number = Math.atan2(ty, tx) * MathUtils.radDeg - bone.shearX - bone.rotation;
-		if (bone.scaleX < 0) rotationIK += 180;
-		if (rotationIK > 180)
-			rotationIK -= 360;
-		else if (rotationIK < -180) rotationIK += 360;
-		bone.updateWorldTransformWith(bone.x, bone.y, bone.rotation + rotationIK * alpha, bone.scaleX, bone.scaleY, bone.shearX,
-			bone.shearY);
-	}
-
-	/** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The
-	 * target is specified in the world coordinate system.
-	 * @param child Any descendant bone of the parent. */
-	static public function apply2 (parent:Bone, child:Bone, targetX:Number, targetY:Number, bendDir:int, alpha:Number) : void {
-		if (alpha == 0) {
-			child.updateWorldTransform();
-			return;
-		}
-		var px:Number = parent.x, py:Number = parent.y, psx:Number = parent.scaleX, psy:Number = parent.scaleY, csx:Number = child.scaleX;;
-		var os1:int, os2:int, s2:int;
-		if (psx < 0) {
-			psx = -psx;
-			os1 = 180;
-			s2 = -1;
-		} else {
-			os1 = 0;
-			s2 = 1;
-		}
-		if (psy < 0) {
-			psy = -psy;
-			s2 = -s2;
-		}
-		if (csx < 0) {
-			csx = -csx;
-			os2 = 180;
-		} else
-			os2 = 0;
-		var cx:Number = child.x, cy:Number, cwx:Number, cwy:Number, a:Number = parent.a, b:Number = parent.b, c:Number = parent.c, d:Number = parent.d;
-		var u:Boolean = Math.abs(psx - psy) <= 0.0001;
-		if (!u) {
-			cy = 0;
-			cwx = a * cx + parent.worldX;
-			cwy = c * cx + parent.worldY;
-		} else {
-			cy = child.y;
-			cwx = a * cx + b * cy + parent.worldX;
-			cwy = c * cx + d * cy + parent.worldY;
-		}
-		var pp:Bone = parent.parent;
-		a = pp.a;
-		b = pp.b;
-		c = pp.c;
-		d = pp.d;
-		var id:Number = 1 / (a * d - b * c), x:Number = targetX - pp.worldX, y:Number = targetY - pp.worldY;
-		var tx:Number = (x * d - y * b) * id - px, ty:Number = (y * a - x * c) * id - py;
-		x = cwx - pp.worldX;
-		y = cwy - pp.worldY;
-		var dx:Number = (x * d - y * b) * id - px, dy:Number = (y * a - x * c) * id - py;
-		var l1:Number = Math.sqrt(dx * dx + dy * dy), l2:Number = child.data.length * csx, a1:Number, a2:Number;
-		outer:
-		if (u) {
-			l2 *= psx;
-			var cos:Number = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2);
-			if (cos < -1) 
-				cos = -1;
-			else if (cos > 1) cos = 1;
-			a2 = Math.acos(cos) * bendDir;
-			a = l1 + l2 * cos;
-			b = l2 * Math.sin(a2);
-			a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b);
-		} else {
-			a = psx * l2;
-			b = psy * l2;
-			var aa:Number = a * a, bb:Number = b * b, dd:Number = tx * tx + ty * ty, ta:Number = Math.atan2(ty, tx);
-			c = bb * l1 * l1 + aa * dd - aa * bb;
-			var c1:Number = -2 * bb * l1, c2:Number = bb - aa;
-			d = c1 * c1 - 4 * c2 * c;
-			if (d >= 0) {
-				var q:Number = Math.sqrt(d);
-				if (c1 < 0) q = -q;
-				q = -(c1 + q) / 2;
-				var r0:Number = q / c2, r1:Number = c / q;
-				var r:Number = Math.abs(r0) < Math.abs(r1) ? r0 : r1;
-				if (r * r <= dd) {
-					y = Math.sqrt(dd - r * r) * bendDir;
-					a1 = ta - Math.atan2(y, r);
-					a2 = Math.atan2(y / psy, (r - l1) / psx);
-					break outer;
-				}
-			}
-			var minAngle:Number = 0, minDist:Number = Number.MAX_VALUE, minX:Number = 0, minY:Number = 0;
-			var maxAngle:Number = 0, maxDist:Number = 0, maxX:Number = 0, maxY:Number = 0;
-			x = l1 + a;
-			d = x * x;
-			if (d > maxDist) {
-				maxAngle = 0;
-				maxDist = d;
-				maxX = x;
-			}
-			x = l1 - a;
-			d = x * x;
-			if (d < minDist) {
-				minAngle = Math.PI;
-				minDist = d;
-				minX = x;
-			}
-			var angle:Number = Math.acos(-a * l1 / (aa - bb));
-			x = a * Math.cos(angle) + l1;
-			y = b * Math.sin(angle);
-			d = x * x + y * y;
-			if (d < minDist) {
-				minAngle = angle;
-				minDist = d;
-				minX = x;
-				minY = y;
-			}
-			if (d > maxDist) {
-				maxAngle = angle;
-				maxDist = d;
-				maxX = x;
-				maxY = y;
-			}
-			if (dd <= (minDist + maxDist) / 2) {
-				a1 = ta - Math.atan2(minY * bendDir, minX);
-				a2 = minAngle * bendDir;
-			} else {
-				a1 = ta - Math.atan2(maxY * bendDir, maxX);
-				a2 = maxAngle * bendDir;
-			}
-		}
-		var os:Number = Math.atan2(cy, cx) * s2;
-		var rotation:Number = parent.rotation;
-		a1 = (a1 - os) * MathUtils.radDeg + os1 - rotation;
-		if (a1 > 180)
-			a1 -= 360;
-		else if (a1 < -180) a1 += 360;
-		parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, parent.scaleX, parent.scaleY, 0, 0);
-		rotation = child.rotation;
-		a2 = ((a2 + os) * MathUtils.radDeg - child.shearX) * s2 + os2 - rotation;
-		if (a2 > 180)
-			a2 -= 360;
-		else if (a2 < -180) a2 += 360;
-		child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.scaleX, child.scaleY, child.shearX, child.shearY);
-	}
-}
-
+package spine {
+
+public class IkConstraint implements Updatable {
+	internal var _data:IkConstraintData;
+	public var bones:Vector.<Bone>;
+	public var target:Bone;
+	public var mix:Number;
+	public var bendDirection:int;
+	
+	public var level:int;	
+
+	public function IkConstraint (data:IkConstraintData, skeleton:Skeleton) {
+		if (data == null) throw new ArgumentError("data cannot be null.");
+		if (skeleton == null) throw new ArgumentError("skeleton cannot be null.");
+		_data = data;
+		mix = data.mix;
+		bendDirection = data.bendDirection;
+
+		bones = new Vector.<Bone>();
+		for each (var boneData:BoneData in data.bones)
+			bones[bones.length] = skeleton.findBone(boneData.name);
+		target = skeleton.findBone(data.target._name);
+	}
+
+	public function apply () : void {
+		update();
+	}
+
+	public function update () : void {
+		switch (bones.length) {
+		case 1:
+			apply1(bones[0], target._worldX, target._worldY, mix);
+			break;
+		case 2:
+			apply2(bones[0], bones[1], target._worldX, target._worldY, bendDirection, mix);
+			break;
+		}
+	}
+
+	public function get data () : IkConstraintData {
+		return _data;
+	}
+
+	public function toString () : String {
+		return _data._name;
+	}
+	
+	/** Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified in the world
+	 * coordinate system. */
+	static public function apply1 (bone:Bone, targetX:Number, targetY:Number, alpha:Number) : void {
+		var pp:Bone = bone.parent;
+		var id:Number = 1 / (pp.a * pp.d - pp.b * pp.c);
+		var x:Number = targetX - pp.worldX, y:Number = targetY - pp.worldY;
+		var tx:Number = (x * pp.d - y * pp.b) * id - bone.x, ty:Number = (y * pp.a - x * pp.c) * id - bone.y;
+		var rotationIK:Number = Math.atan2(ty, tx) * MathUtils.radDeg - bone.shearX - bone.rotation;
+		if (bone.scaleX < 0) rotationIK += 180;
+		if (rotationIK > 180)
+			rotationIK -= 360;
+		else if (rotationIK < -180) rotationIK += 360;
+		bone.updateWorldTransformWith(bone.x, bone.y, bone.rotation + rotationIK * alpha, bone.scaleX, bone.scaleY, bone.shearX,
+			bone.shearY);
+	}
+
+	/** Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as possible. The
+	 * target is specified in the world coordinate system.
+	 * @param child Any descendant bone of the parent. */
+	static public function apply2 (parent:Bone, child:Bone, targetX:Number, targetY:Number, bendDir:int, alpha:Number) : void {
+		if (alpha == 0) {
+			child.updateWorldTransform();
+			return;
+		}
+		var px:Number = parent.x, py:Number = parent.y, psx:Number = parent.scaleX, psy:Number = parent.scaleY, csx:Number = child.scaleX;;
+		var os1:int, os2:int, s2:int;
+		if (psx < 0) {
+			psx = -psx;
+			os1 = 180;
+			s2 = -1;
+		} else {
+			os1 = 0;
+			s2 = 1;
+		}
+		if (psy < 0) {
+			psy = -psy;
+			s2 = -s2;
+		}
+		if (csx < 0) {
+			csx = -csx;
+			os2 = 180;
+		} else
+			os2 = 0;
+		var cx:Number = child.x, cy:Number, cwx:Number, cwy:Number, a:Number = parent.a, b:Number = parent.b, c:Number = parent.c, d:Number = parent.d;
+		var u:Boolean = Math.abs(psx - psy) <= 0.0001;
+		if (!u) {
+			cy = 0;
+			cwx = a * cx + parent.worldX;
+			cwy = c * cx + parent.worldY;
+		} else {
+			cy = child.y;
+			cwx = a * cx + b * cy + parent.worldX;
+			cwy = c * cx + d * cy + parent.worldY;
+		}
+		var pp:Bone = parent.parent;
+		a = pp.a;
+		b = pp.b;
+		c = pp.c;
+		d = pp.d;
+		var id:Number = 1 / (a * d - b * c), x:Number = targetX - pp.worldX, y:Number = targetY - pp.worldY;
+		var tx:Number = (x * d - y * b) * id - px, ty:Number = (y * a - x * c) * id - py;
+		x = cwx - pp.worldX;
+		y = cwy - pp.worldY;
+		var dx:Number = (x * d - y * b) * id - px, dy:Number = (y * a - x * c) * id - py;
+		var l1:Number = Math.sqrt(dx * dx + dy * dy), l2:Number = child.data.length * csx, a1:Number, a2:Number;
+		outer:
+		if (u) {
+			l2 *= psx;
+			var cos:Number = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2);
+			if (cos < -1) 
+				cos = -1;
+			else if (cos > 1) cos = 1;
+			a2 = Math.acos(cos) * bendDir;
+			a = l1 + l2 * cos;
+			b = l2 * Math.sin(a2);
+			a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b);
+		} else {
+			a = psx * l2;
+			b = psy * l2;
+			var aa:Number = a * a, bb:Number = b * b, dd:Number = tx * tx + ty * ty, ta:Number = Math.atan2(ty, tx);
+			c = bb * l1 * l1 + aa * dd - aa * bb;
+			var c1:Number = -2 * bb * l1, c2:Number = bb - aa;
+			d = c1 * c1 - 4 * c2 * c;
+			if (d >= 0) {
+				var q:Number = Math.sqrt(d);
+				if (c1 < 0) q = -q;
+				q = -(c1 + q) / 2;
+				var r0:Number = q / c2, r1:Number = c / q;
+				var r:Number = Math.abs(r0) < Math.abs(r1) ? r0 : r1;
+				if (r * r <= dd) {
+					y = Math.sqrt(dd - r * r) * bendDir;
+					a1 = ta - Math.atan2(y, r);
+					a2 = Math.atan2(y / psy, (r - l1) / psx);
+					break outer;
+				}
+			}
+			var minAngle:Number = 0, minDist:Number = Number.MAX_VALUE, minX:Number = 0, minY:Number = 0;
+			var maxAngle:Number = 0, maxDist:Number = 0, maxX:Number = 0, maxY:Number = 0;
+			x = l1 + a;
+			d = x * x;
+			if (d > maxDist) {
+				maxAngle = 0;
+				maxDist = d;
+				maxX = x;
+			}
+			x = l1 - a;
+			d = x * x;
+			if (d < minDist) {
+				minAngle = Math.PI;
+				minDist = d;
+				minX = x;
+			}
+			var angle:Number = Math.acos(-a * l1 / (aa - bb));
+			x = a * Math.cos(angle) + l1;
+			y = b * Math.sin(angle);
+			d = x * x + y * y;
+			if (d < minDist) {
+				minAngle = angle;
+				minDist = d;
+				minX = x;
+				minY = y;
+			}
+			if (d > maxDist) {
+				maxAngle = angle;
+				maxDist = d;
+				maxX = x;
+				maxY = y;
+			}
+			if (dd <= (minDist + maxDist) / 2) {
+				a1 = ta - Math.atan2(minY * bendDir, minX);
+				a2 = minAngle * bendDir;
+			} else {
+				a1 = ta - Math.atan2(maxY * bendDir, maxX);
+				a2 = maxAngle * bendDir;
+			}
+		}
+		var os:Number = Math.atan2(cy, cx) * s2;
+		var rotation:Number = parent.rotation;
+		a1 = (a1 - os) * MathUtils.radDeg + os1 - rotation;
+		if (a1 > 180)
+			a1 -= 360;
+		else if (a1 < -180) a1 += 360;
+		parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, parent.scaleX, parent.scaleY, 0, 0);
+		rotation = child.rotation;
+		a2 = ((a2 + os) * MathUtils.radDeg - child.shearX) * s2 + os2 - rotation;
+		if (a2 > 180)
+			a2 -= 360;
+		else if (a2 < -180) a2 += 360;
+		child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.scaleX, child.scaleY, child.shearX, child.shearY);
+	}
+}
+
 }

+ 51 - 52
spine-as3/spine-as3/src/spine/IkConstraintData.as

@@ -1,55 +1,54 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public class IkConstraintData {
-	internal var _name:String;
-	public var bones:Vector.<BoneData> = new Vector.<BoneData>();
-	public var target:BoneData;
-	public var bendDirection:int = 1;
-	public var mix:Number = 1;
-
-	public function IkConstraintData (name:String) {
-		if (name == null) throw new ArgumentError("name cannot be null.");
-		_name = name;
-	}
-
-	public function get name () : String {
-		return _name;
-	}
-
-	public function toString () : String {
-		return _name;
-	}
-}
-
+package spine {
+
+public class IkConstraintData {
+	internal var _name:String;
+	public var bones:Vector.<BoneData> = new Vector.<BoneData>();
+	public var target:BoneData;
+	public var bendDirection:int = 1;
+	public var mix:Number = 1;
+
+	public function IkConstraintData (name:String) {
+		if (name == null) throw new ArgumentError("name cannot be null.");
+		_name = name;
+	}
+
+	public function get name () : String {
+		return _name;
+	}
+
+	public function toString () : String {
+		return _name;
+	}
+}
+
 }

+ 49 - 50
spine-as3/spine-as3/src/spine/MathUtils.as

@@ -1,53 +1,52 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public class MathUtils {
-	static public var radDeg:Number = 180 / Math.PI;
-	static public var degRad:Number = Math.PI / 180;
-	
-	static public function cosDeg(degrees:Number): Number {
-		return Math.cos(degrees * degRad);
-	}
-	
-	static public function sinDeg(degrees:Number): Number {
-		return Math.sin(degrees * degRad);
-	}
-	
-	static public function clamp (value:Number, min:Number, max:Number) : Number {
-		if (value < min) return min;
-		if (value > max) return max;
-		return value;
-	}
-}
-
+package spine {
+
+public class MathUtils {
+	static public var radDeg:Number = 180 / Math.PI;
+	static public var degRad:Number = Math.PI / 180;
+	
+	static public function cosDeg(degrees:Number): Number {
+		return Math.cos(degrees * degRad);
+	}
+	
+	static public function sinDeg(degrees:Number): Number {
+		return Math.sin(degrees * degRad);
+	}
+	
+	static public function clamp (value:Number, min:Number, max:Number) : Number {
+		if (value < min) return min;
+		if (value > max) return max;
+		return value;
+	}
+}
+
 }

+ 416 - 417
spine-as3/spine-as3/src/spine/PathConstraint.as

@@ -1,420 +1,419 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-import spine.attachments.PathAttachment;
-
-public class PathConstraint implements Updatable {
-	private static const NONE:int = -1, BEFORE:int = -2, AFTER:int = -3;
-
-	internal var _data:PathConstraintData;
-	internal var _bones:Vector.<Bone>;
-	public var target:Slot;
-	public var position:Number, spacing:Number, rotateMix:Number, translateMix:Number;
-
-	internal const _spaces:Vector.<Number> = new Vector.<Number>();
-	internal const _positions:Vector.<Number> = new Vector.<Number>();
-	internal const _world:Vector.<Number> = new Vector.<Number>();
-	internal const _curves:Vector.<Number> = new Vector.<Number>();
-	internal const _lengths:Vector.<Number> = new Vector.<Number>();
-	internal const _segments:Vector.<Number> = new Vector.<Number>(10);	
-
-	public function PathConstraint (data:PathConstraintData, skeleton:Skeleton) {
-		if (data == null) throw new ArgumentError("data cannot be null.");
-		if (skeleton == null) throw new ArgumentError("skeleton cannot be null.");
-		_data = data;
-		_bones = new Vector.<Bone>();		
-		for each (var boneData:BoneData in data.bones)
-			_bones.push(skeleton.findBone(boneData.name));
-		target = skeleton.findSlot(data.target.name);
-		position = data.position;
-		spacing = data.spacing;
-		rotateMix = data.rotateMix;
-		translateMix = data.translateMix;
-	}
-
-	public function apply () : void {
-		update();
-	}
-	
-	public function update () : void {
-		var attachment:PathAttachment = target.attachment as PathAttachment;
-		if (attachment == null) return;		
-
-		var rotateMix:Number = this.rotateMix, translateMix:Number = this.translateMix;
-		var translate:Boolean = translateMix > 0, rotate:Boolean = rotateMix > 0;
-		if (!translate && !rotate) return;
-
-		var data:PathConstraintData = this._data;
-		var spacingMode:SpacingMode = data.spacingMode;
-		var lengthSpacing:Boolean = spacingMode == SpacingMode.length;
-		var rotateMode:RotateMode = data.rotateMode;
-		var tangents:Boolean = rotateMode == RotateMode.tangent, scale:Boolean = rotateMode == RotateMode.chainScale;
-		var boneCount:int = this._bones.length, spacesCount:int = tangents ? boneCount : boneCount + 1;
-		var bones:Vector.<Bone> = this._bones;
-		this._spaces.length = spacesCount;
-		var spaces:Vector.<Number> = this._spaces, lengths:Vector.<Number> = null;
-		var spacing:Number = this.spacing;
-		if (scale || lengthSpacing) {
-			if (scale) {
-				this._lengths.length = boneCount;
-				lengths = this._lengths;
-			}
-			for (var i:int = 0, n:int = spacesCount - 1; i < n;) {
-				var bone:Bone = bones[i];
-				var length:Number = bone.data.length, x:Number = length * bone.a, y:Number = length * bone.c;
-				length = Math.sqrt(x * x + y * y);
-				if (scale) lengths[i] = length;
-				spaces[++i] = lengthSpacing ? Math.max(0, length + spacing) : spacing;
-			}
-		} else {
-			for (i = 1; i < spacesCount; i++)
-				spaces[i] = spacing;
-		}
-
-		var positions:Vector.<Number> = computeWorldPositions(attachment, spacesCount, tangents,
-			data.positionMode == PositionMode.percent, spacingMode == SpacingMode.percent);
-		var skeleton:Skeleton = target.skeleton;
-		var skeletonX:Number = skeleton.x, skeletonY:Number = skeleton.y;
-		var boneX:Number = positions[0], boneY:Number = positions[1], offsetRotation:Number = data.offsetRotation;
-		var tip:Boolean = rotateMode == RotateMode.chain && offsetRotation == 0;
-		var p:Number;
-		for (i = 0, p = 3; i < boneCount; i++, p += 3) {
-			bone = bones[i];
-			bone._worldX += (boneX - skeletonX - bone.worldX) * translateMix;
-			bone._worldY += (boneY - skeletonY - bone.worldY) * translateMix;
-			x = positions[p]; y = positions[p + 1]; var dx:Number = x - boneX, dy:Number = y - boneY;
-			if (scale) {
-				length = lengths[i];
-				if (length != 0) {
-					var s:Number = (Math.sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1;
-					bone._a *= s;
-					bone._c *= s;
-				}
-			}
-			boneX = x;
-			boneY = y;
-			if (rotate) {
-				var a:Number = bone.a, b:Number = bone.b, c:Number = bone.c, d:Number = bone.d, r:Number, cos:Number, sin:Number;
-				if (tangents)
-					r = positions[p - 1];
-				else if (spaces[i + 1] == 0)
-					r = positions[p + 2];
-				else
-					r = Math.atan2(dy, dx);
-				r -= Math.atan2(c, a) - offsetRotation * MathUtils.degRad;
-				if (tip) {
-					cos = Math.cos(r);
-					sin = Math.sin(r);
-					length = bone.data.length;
-					boneX += (length * (cos * a - sin * c) - dx) * rotateMix;
-					boneY += (length * (sin * a + cos * c) - dy) * rotateMix;
-				}
-				if (r > Math.PI)
-					r -= (Math.PI * 2);
-				else if (r < -Math.PI) //
-					r += (Math.PI * 2);
-				r *= rotateMix;
-				cos = Math.cos(r);
-				sin = Math.sin(r);
-				bone._a = cos * a - sin * c;
-				bone._b = cos * b - sin * d;
-				bone._c = sin * a + cos * c;
-				bone._d = sin * b + cos * d;
-			}
-		}
-	}
-
-	protected function computeWorldPositions (path:PathAttachment, spacesCount:int, tangents:Boolean, percentPosition:Boolean,
-		percentSpacing:Boolean) : Vector.<Number> {
-		var target:Slot = this.target;
-		var position:Number = this.position;
-		var spaces:Vector.<Number> = this._spaces;
-		this._positions.length = spacesCount * 3 + 2;
-		var out:Vector.<Number> = this._positions, world:Vector.<Number>;
-		var closed:Boolean = path.closed;
-		var verticesLength:int = path.worldVerticesLength, curveCount:int = verticesLength / 6, prevCurve:int = NONE;
-
-		if (!path.constantSpeed) {
-			var lengths:Vector.<Number> = path.lengths;
-			curveCount -= closed ? 1 : 2;
-			var pathLength:Number = lengths[curveCount];
-			if (percentPosition) position *= pathLength;
-			if (percentSpacing) {
-				for (var i:int = 0; i < spacesCount; i++)
-					spaces[i] *= pathLength;
-			}
-			this._world.length = 8;
-			world = this._world;
-			var o:int, curve:int; 
-			for (i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) {
-				var space:Number = spaces[i];
-				position += space;
-				var p:Number = position;
-
-				if (closed) {
-					p %= pathLength;
-					if (p < 0) p += pathLength;
-					curve = 0;
-				} else if (p < 0) {
-					if (prevCurve != BEFORE) {
-						prevCurve = BEFORE;
-						path.computeWorldVertices2(target, 2, 4, world, 0);
-					}
-					addBeforePosition(p, world, 0, out, o);
-					continue;
-				} else if (p > pathLength) {
-					if (prevCurve != AFTER) {
-						prevCurve = AFTER;
-						path.computeWorldVertices2(target, verticesLength - 6, 4, world, 0);
-					}
-					addAfterPosition(p - pathLength, world, 0, out, o);
-					continue;
-				}
-
-				// Determine curve containing position.
-				for (;; curve++) {
-					var length:Number = lengths[curve];
-					if (p > length) continue;
-					if (curve == 0)
-						p /= length;
-					else {
-						var prev:Number = lengths[curve - 1];
-						p = (p - prev) / (length - prev);
-					}
-					break;
-				}
-				if (curve != prevCurve) {
-					prevCurve = curve;
-					if (closed && curve == curveCount) {
-						path.computeWorldVertices2(target, verticesLength - 4, 4, world, 0);
-						path.computeWorldVertices2(target, 0, 4, world, 4);
-					} else
-						path.computeWorldVertices2(target, curve * 6 + 2, 8, world, 0);
-				}
-				addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o,
-					tangents || (i > 0 && space == 0));
-			}
-			return out;
-		}
-
-		// World vertices.
-		if (closed) {
-			verticesLength += 2;
-			this._world.length = verticesLength;
-			world = this._world;
-			path.computeWorldVertices2(target, 2, verticesLength - 4, world, 0);
-			path.computeWorldVertices2(target, 0, 2, world, verticesLength - 4);
-			world[verticesLength - 2] = world[0];
-			world[verticesLength - 1] = world[1];
-		} else {
-			curveCount--;
-			verticesLength -= 4;
-			this._world.length = verticesLength;
-			world = this._world;
-			path.computeWorldVertices2(target, 2, verticesLength, world, 0);
-		}
-
-		// Curve lengths.
-		this._curves.length = curveCount;
-		var curves:Vector.<Number> = this._curves;
-		pathLength = 0;
-		var x1:Number = world[0], y1:Number = world[1], cx1:Number = 0, cy1:Number = 0, cx2:Number = 0, cy2:Number = 0, x2:Number = 0, y2:Number = 0;
-		var tmpx:Number, tmpy:Number, dddfx:Number, dddfy:Number, ddfx:Number, ddfy:Number, dfx:Number, dfy:Number;
-		var w:int;
-		for (i = 0, w = 2; i < curveCount; i++, w += 6) {
-			cx1 = world[w];
-			cy1 = world[w + 1];
-			cx2 = world[w + 2];
-			cy2 = world[w + 3];
-			x2 = world[w + 4];
-			y2 = world[w + 5];
-			tmpx = (x1 - cx1 * 2 + cx2) * 0.1875;
-			tmpy = (y1 - cy1 * 2 + cy2) * 0.1875;
-			dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375;
-			dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375;
-			ddfx = tmpx * 2 + dddfx;
-			ddfy = tmpy * 2 + dddfy;
-			dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667;
-			dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667;
-			pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
-			dfx += ddfx;
-			dfy += ddfy;
-			ddfx += dddfx;
-			ddfy += dddfy;
-			pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
-			dfx += ddfx;
-			dfy += ddfy;
-			pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
-			dfx += ddfx + dddfx;
-			dfy += ddfy + dddfy;
-			pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
-			curves[i] = pathLength;
-			x1 = x2;
-			y1 = y2;
-		}
-		if (percentPosition) position *= pathLength;
-		if (percentSpacing) {
-			for (i = 0; i < spacesCount; i++)
-				spaces[i] *= pathLength;
-		}
-
-		var segments:Vector.<Number> = this._segments;
-		var curveLength:Number = 0;
-		var segment:int;
-		for (i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) {
-			space = spaces[i];
-			position += space;
-			p = position;
-
-			if (closed) {
-				p %= pathLength;
-				if (p < 0) p += pathLength;
-				curve = 0;
-			} else if (p < 0) {
-				addBeforePosition(p, world, 0, out, o);
-				continue;
-			} else if (p > pathLength) {
-				addAfterPosition(p - pathLength, world, verticesLength - 4, out, o);
-				continue;
-			}
-
-			// Determine curve containing position.
-			for (;; curve++) {
-				length = curves[curve];
-				if (p > length) continue;
-				if (curve == 0)
-					p /= length;
-				else {
-					prev = curves[curve - 1];
-					p = (p - prev) / (length - prev);
-				}
-				break;
-			}
-
-			// Curve segment lengths.
-			if (curve != prevCurve) {
-				prevCurve = curve;
-				var ii:int = curve * 6;
-				x1 = world[ii];
-				y1 = world[ii + 1];
-				cx1 = world[ii + 2];
-				cy1 = world[ii + 3];
-				cx2 = world[ii + 4];
-				cy2 = world[ii + 5];
-				x2 = world[ii + 6];
-				y2 = world[ii + 7];
-				tmpx = (x1 - cx1 * 2 + cx2) * 0.03;
-				tmpy = (y1 - cy1 * 2 + cy2) * 0.03;
-				dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006;
-				dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006;
-				ddfx = tmpx * 2 + dddfx;
-				ddfy = tmpy * 2 + dddfy;
-				dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667;
-				dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667;
-				curveLength = Math.sqrt(dfx * dfx + dfy * dfy);
-				segments[0] = curveLength;
-				for (ii = 1; ii < 8; ii++) {
-					dfx += ddfx;
-					dfy += ddfy;
-					ddfx += dddfx;
-					ddfy += dddfy;
-					curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
-					segments[ii] = curveLength;
-				}
-				dfx += ddfx;
-				dfy += ddfy;
-				curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
-				segments[8] = curveLength;
-				dfx += ddfx + dddfx;
-				dfy += ddfy + dddfy;
-				curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
-				segments[9] = curveLength;
-				segment = 0;
-			}
-
-			// Weight by segment length.
-			p *= curveLength;
-			for (;; segment++) {
-				length = segments[segment];
-				if (p > length) continue;
-				if (segment == 0)
-					p /= length;
-				else {
-					prev = segments[segment - 1];
-					p = segment + (p - prev) / (length - prev);
-				}
-				break;
-			}
-			addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space == 0));
-		}
-		return out;
-	}
-
-	private function addBeforePosition (p:Number, temp:Vector.<Number>, i:int, out:Vector.<Number>, o:int) : void {
-		var x1:Number = temp[i], y1:Number = temp[i + 1], dx:Number = temp[i + 2] - x1, dy:Number = temp[i + 3] - y1, r:Number = Math.atan2(dy, dx);
-		out[o] = x1 + p * Math.cos(r);
-		out[o + 1] = y1 + p * Math.sin(r);
-		out[o + 2] = r;
-	}
-
-	private function addAfterPosition (p:Number, temp:Vector.<Number>, i:int, out:Vector.<Number>, o:int) : void {
-		var x1:Number = temp[i + 2], y1:Number = temp[i + 3], dx:Number = x1 - temp[i], dy:Number = y1 - temp[i + 1], r:Number = Math.atan2(dy, dx);
-		out[o] = x1 + p * Math.cos(r);
-		out[o + 1] = y1 + p * Math.sin(r);
-		out[o + 2] = r;
-	}
-
-	private function addCurvePosition (p:Number, x1:Number, y1:Number, cx1:Number, cy1:Number, cx2:Number, cy2:Number, x2:Number, y2:Number,
-		out:Vector.<Number>, o:int, tangents:Boolean) : void {
-		if (p == 0) p = 0.0001;
-		var tt:Number = p * p, ttt:Number = tt * p, u:Number = 1 - p, uu:Number = u * u, uuu:Number = uu * u;
-		var ut:Number = u * p, ut3:Number = ut * 3, uut3:Number = u * ut3, utt3:Number = ut3 * p;
-		var x:Number = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y:Number = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt;
-		out[o] = x;
-		out[o + 1] = y;
-		if (tangents) out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt));
-	}
-
-	public function get bones () : Vector.<Bone> {
-		return _bones;
-	}
-	
-	public function get data () : PathConstraintData {
-		return _data;
-	}
-
-	public function toString () : String {
-		return _data.name;
-	}
-}
-
+package spine {
+import spine.attachments.PathAttachment;
+
+public class PathConstraint implements Updatable {
+	private static const NONE:int = -1, BEFORE:int = -2, AFTER:int = -3;
+
+	internal var _data:PathConstraintData;
+	internal var _bones:Vector.<Bone>;
+	public var target:Slot;
+	public var position:Number, spacing:Number, rotateMix:Number, translateMix:Number;
+
+	internal const _spaces:Vector.<Number> = new Vector.<Number>();
+	internal const _positions:Vector.<Number> = new Vector.<Number>();
+	internal const _world:Vector.<Number> = new Vector.<Number>();
+	internal const _curves:Vector.<Number> = new Vector.<Number>();
+	internal const _lengths:Vector.<Number> = new Vector.<Number>();
+	internal const _segments:Vector.<Number> = new Vector.<Number>(10);	
+
+	public function PathConstraint (data:PathConstraintData, skeleton:Skeleton) {
+		if (data == null) throw new ArgumentError("data cannot be null.");
+		if (skeleton == null) throw new ArgumentError("skeleton cannot be null.");
+		_data = data;
+		_bones = new Vector.<Bone>();		
+		for each (var boneData:BoneData in data.bones)
+			_bones.push(skeleton.findBone(boneData.name));
+		target = skeleton.findSlot(data.target.name);
+		position = data.position;
+		spacing = data.spacing;
+		rotateMix = data.rotateMix;
+		translateMix = data.translateMix;
+	}
+
+	public function apply () : void {
+		update();
+	}
+	
+	public function update () : void {
+		var attachment:PathAttachment = target.attachment as PathAttachment;
+		if (attachment == null) return;		
+
+		var rotateMix:Number = this.rotateMix, translateMix:Number = this.translateMix;
+		var translate:Boolean = translateMix > 0, rotate:Boolean = rotateMix > 0;
+		if (!translate && !rotate) return;
+
+		var data:PathConstraintData = this._data;
+		var spacingMode:SpacingMode = data.spacingMode;
+		var lengthSpacing:Boolean = spacingMode == SpacingMode.length;
+		var rotateMode:RotateMode = data.rotateMode;
+		var tangents:Boolean = rotateMode == RotateMode.tangent, scale:Boolean = rotateMode == RotateMode.chainScale;
+		var boneCount:int = this._bones.length, spacesCount:int = tangents ? boneCount : boneCount + 1;
+		var bones:Vector.<Bone> = this._bones;
+		this._spaces.length = spacesCount;
+		var spaces:Vector.<Number> = this._spaces, lengths:Vector.<Number> = null;
+		var spacing:Number = this.spacing;
+		if (scale || lengthSpacing) {
+			if (scale) {
+				this._lengths.length = boneCount;
+				lengths = this._lengths;
+			}
+			for (var i:int = 0, n:int = spacesCount - 1; i < n;) {
+				var bone:Bone = bones[i];
+				var length:Number = bone.data.length, x:Number = length * bone.a, y:Number = length * bone.c;
+				length = Math.sqrt(x * x + y * y);
+				if (scale) lengths[i] = length;
+				spaces[++i] = lengthSpacing ? Math.max(0, length + spacing) : spacing;
+			}
+		} else {
+			for (i = 1; i < spacesCount; i++)
+				spaces[i] = spacing;
+		}
+
+		var positions:Vector.<Number> = computeWorldPositions(attachment, spacesCount, tangents,
+			data.positionMode == PositionMode.percent, spacingMode == SpacingMode.percent);
+		var skeleton:Skeleton = target.skeleton;
+		var skeletonX:Number = skeleton.x, skeletonY:Number = skeleton.y;
+		var boneX:Number = positions[0], boneY:Number = positions[1], offsetRotation:Number = data.offsetRotation;
+		var tip:Boolean = rotateMode == RotateMode.chain && offsetRotation == 0;
+		var p:Number;
+		for (i = 0, p = 3; i < boneCount; i++, p += 3) {
+			bone = bones[i];
+			bone._worldX += (boneX - skeletonX - bone.worldX) * translateMix;
+			bone._worldY += (boneY - skeletonY - bone.worldY) * translateMix;
+			x = positions[p]; y = positions[p + 1]; var dx:Number = x - boneX, dy:Number = y - boneY;
+			if (scale) {
+				length = lengths[i];
+				if (length != 0) {
+					var s:Number = (Math.sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1;
+					bone._a *= s;
+					bone._c *= s;
+				}
+			}
+			boneX = x;
+			boneY = y;
+			if (rotate) {
+				var a:Number = bone.a, b:Number = bone.b, c:Number = bone.c, d:Number = bone.d, r:Number, cos:Number, sin:Number;
+				if (tangents)
+					r = positions[p - 1];
+				else if (spaces[i + 1] == 0)
+					r = positions[p + 2];
+				else
+					r = Math.atan2(dy, dx);
+				r -= Math.atan2(c, a) - offsetRotation * MathUtils.degRad;
+				if (tip) {
+					cos = Math.cos(r);
+					sin = Math.sin(r);
+					length = bone.data.length;
+					boneX += (length * (cos * a - sin * c) - dx) * rotateMix;
+					boneY += (length * (sin * a + cos * c) - dy) * rotateMix;
+				}
+				if (r > Math.PI)
+					r -= (Math.PI * 2);
+				else if (r < -Math.PI) //
+					r += (Math.PI * 2);
+				r *= rotateMix;
+				cos = Math.cos(r);
+				sin = Math.sin(r);
+				bone._a = cos * a - sin * c;
+				bone._b = cos * b - sin * d;
+				bone._c = sin * a + cos * c;
+				bone._d = sin * b + cos * d;
+			}
+		}
+	}
+
+	protected function computeWorldPositions (path:PathAttachment, spacesCount:int, tangents:Boolean, percentPosition:Boolean,
+		percentSpacing:Boolean) : Vector.<Number> {
+		var target:Slot = this.target;
+		var position:Number = this.position;
+		var spaces:Vector.<Number> = this._spaces;
+		this._positions.length = spacesCount * 3 + 2;
+		var out:Vector.<Number> = this._positions, world:Vector.<Number>;
+		var closed:Boolean = path.closed;
+		var verticesLength:int = path.worldVerticesLength, curveCount:int = verticesLength / 6, prevCurve:int = NONE;
+
+		if (!path.constantSpeed) {
+			var lengths:Vector.<Number> = path.lengths;
+			curveCount -= closed ? 1 : 2;
+			var pathLength:Number = lengths[curveCount];
+			if (percentPosition) position *= pathLength;
+			if (percentSpacing) {
+				for (var i:int = 0; i < spacesCount; i++)
+					spaces[i] *= pathLength;
+			}
+			this._world.length = 8;
+			world = this._world;
+			var o:int, curve:int; 
+			for (i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) {
+				var space:Number = spaces[i];
+				position += space;
+				var p:Number = position;
+
+				if (closed) {
+					p %= pathLength;
+					if (p < 0) p += pathLength;
+					curve = 0;
+				} else if (p < 0) {
+					if (prevCurve != BEFORE) {
+						prevCurve = BEFORE;
+						path.computeWorldVertices2(target, 2, 4, world, 0);
+					}
+					addBeforePosition(p, world, 0, out, o);
+					continue;
+				} else if (p > pathLength) {
+					if (prevCurve != AFTER) {
+						prevCurve = AFTER;
+						path.computeWorldVertices2(target, verticesLength - 6, 4, world, 0);
+					}
+					addAfterPosition(p - pathLength, world, 0, out, o);
+					continue;
+				}
+
+				// Determine curve containing position.
+				for (;; curve++) {
+					var length:Number = lengths[curve];
+					if (p > length) continue;
+					if (curve == 0)
+						p /= length;
+					else {
+						var prev:Number = lengths[curve - 1];
+						p = (p - prev) / (length - prev);
+					}
+					break;
+				}
+				if (curve != prevCurve) {
+					prevCurve = curve;
+					if (closed && curve == curveCount) {
+						path.computeWorldVertices2(target, verticesLength - 4, 4, world, 0);
+						path.computeWorldVertices2(target, 0, 4, world, 4);
+					} else
+						path.computeWorldVertices2(target, curve * 6 + 2, 8, world, 0);
+				}
+				addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o,
+					tangents || (i > 0 && space == 0));
+			}
+			return out;
+		}
+
+		// World vertices.
+		if (closed) {
+			verticesLength += 2;
+			this._world.length = verticesLength;
+			world = this._world;
+			path.computeWorldVertices2(target, 2, verticesLength - 4, world, 0);
+			path.computeWorldVertices2(target, 0, 2, world, verticesLength - 4);
+			world[verticesLength - 2] = world[0];
+			world[verticesLength - 1] = world[1];
+		} else {
+			curveCount--;
+			verticesLength -= 4;
+			this._world.length = verticesLength;
+			world = this._world;
+			path.computeWorldVertices2(target, 2, verticesLength, world, 0);
+		}
+
+		// Curve lengths.
+		this._curves.length = curveCount;
+		var curves:Vector.<Number> = this._curves;
+		pathLength = 0;
+		var x1:Number = world[0], y1:Number = world[1], cx1:Number = 0, cy1:Number = 0, cx2:Number = 0, cy2:Number = 0, x2:Number = 0, y2:Number = 0;
+		var tmpx:Number, tmpy:Number, dddfx:Number, dddfy:Number, ddfx:Number, ddfy:Number, dfx:Number, dfy:Number;
+		var w:int;
+		for (i = 0, w = 2; i < curveCount; i++, w += 6) {
+			cx1 = world[w];
+			cy1 = world[w + 1];
+			cx2 = world[w + 2];
+			cy2 = world[w + 3];
+			x2 = world[w + 4];
+			y2 = world[w + 5];
+			tmpx = (x1 - cx1 * 2 + cx2) * 0.1875;
+			tmpy = (y1 - cy1 * 2 + cy2) * 0.1875;
+			dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375;
+			dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375;
+			ddfx = tmpx * 2 + dddfx;
+			ddfy = tmpy * 2 + dddfy;
+			dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667;
+			dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667;
+			pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
+			dfx += ddfx;
+			dfy += ddfy;
+			ddfx += dddfx;
+			ddfy += dddfy;
+			pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
+			dfx += ddfx;
+			dfy += ddfy;
+			pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
+			dfx += ddfx + dddfx;
+			dfy += ddfy + dddfy;
+			pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
+			curves[i] = pathLength;
+			x1 = x2;
+			y1 = y2;
+		}
+		if (percentPosition) position *= pathLength;
+		if (percentSpacing) {
+			for (i = 0; i < spacesCount; i++)
+				spaces[i] *= pathLength;
+		}
+
+		var segments:Vector.<Number> = this._segments;
+		var curveLength:Number = 0;
+		var segment:int;
+		for (i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) {
+			space = spaces[i];
+			position += space;
+			p = position;
+
+			if (closed) {
+				p %= pathLength;
+				if (p < 0) p += pathLength;
+				curve = 0;
+			} else if (p < 0) {
+				addBeforePosition(p, world, 0, out, o);
+				continue;
+			} else if (p > pathLength) {
+				addAfterPosition(p - pathLength, world, verticesLength - 4, out, o);
+				continue;
+			}
+
+			// Determine curve containing position.
+			for (;; curve++) {
+				length = curves[curve];
+				if (p > length) continue;
+				if (curve == 0)
+					p /= length;
+				else {
+					prev = curves[curve - 1];
+					p = (p - prev) / (length - prev);
+				}
+				break;
+			}
+
+			// Curve segment lengths.
+			if (curve != prevCurve) {
+				prevCurve = curve;
+				var ii:int = curve * 6;
+				x1 = world[ii];
+				y1 = world[ii + 1];
+				cx1 = world[ii + 2];
+				cy1 = world[ii + 3];
+				cx2 = world[ii + 4];
+				cy2 = world[ii + 5];
+				x2 = world[ii + 6];
+				y2 = world[ii + 7];
+				tmpx = (x1 - cx1 * 2 + cx2) * 0.03;
+				tmpy = (y1 - cy1 * 2 + cy2) * 0.03;
+				dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006;
+				dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006;
+				ddfx = tmpx * 2 + dddfx;
+				ddfy = tmpy * 2 + dddfy;
+				dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667;
+				dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667;
+				curveLength = Math.sqrt(dfx * dfx + dfy * dfy);
+				segments[0] = curveLength;
+				for (ii = 1; ii < 8; ii++) {
+					dfx += ddfx;
+					dfy += ddfy;
+					ddfx += dddfx;
+					ddfy += dddfy;
+					curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
+					segments[ii] = curveLength;
+				}
+				dfx += ddfx;
+				dfy += ddfy;
+				curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
+				segments[8] = curveLength;
+				dfx += ddfx + dddfx;
+				dfy += ddfy + dddfy;
+				curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
+				segments[9] = curveLength;
+				segment = 0;
+			}
+
+			// Weight by segment length.
+			p *= curveLength;
+			for (;; segment++) {
+				length = segments[segment];
+				if (p > length) continue;
+				if (segment == 0)
+					p /= length;
+				else {
+					prev = segments[segment - 1];
+					p = segment + (p - prev) / (length - prev);
+				}
+				break;
+			}
+			addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space == 0));
+		}
+		return out;
+	}
+
+	private function addBeforePosition (p:Number, temp:Vector.<Number>, i:int, out:Vector.<Number>, o:int) : void {
+		var x1:Number = temp[i], y1:Number = temp[i + 1], dx:Number = temp[i + 2] - x1, dy:Number = temp[i + 3] - y1, r:Number = Math.atan2(dy, dx);
+		out[o] = x1 + p * Math.cos(r);
+		out[o + 1] = y1 + p * Math.sin(r);
+		out[o + 2] = r;
+	}
+
+	private function addAfterPosition (p:Number, temp:Vector.<Number>, i:int, out:Vector.<Number>, o:int) : void {
+		var x1:Number = temp[i + 2], y1:Number = temp[i + 3], dx:Number = x1 - temp[i], dy:Number = y1 - temp[i + 1], r:Number = Math.atan2(dy, dx);
+		out[o] = x1 + p * Math.cos(r);
+		out[o + 1] = y1 + p * Math.sin(r);
+		out[o + 2] = r;
+	}
+
+	private function addCurvePosition (p:Number, x1:Number, y1:Number, cx1:Number, cy1:Number, cx2:Number, cy2:Number, x2:Number, y2:Number,
+		out:Vector.<Number>, o:int, tangents:Boolean) : void {
+		if (p == 0) p = 0.0001;
+		var tt:Number = p * p, ttt:Number = tt * p, u:Number = 1 - p, uu:Number = u * u, uuu:Number = uu * u;
+		var ut:Number = u * p, ut3:Number = ut * 3, uut3:Number = u * ut3, utt3:Number = ut3 * p;
+		var x:Number = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y:Number = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt;
+		out[o] = x;
+		out[o + 1] = y;
+		if (tangents) out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt));
+	}
+
+	public function get bones () : Vector.<Bone> {
+		return _bones;
+	}
+	
+	public function get data () : PathConstraintData {
+		return _data;
+	}
+
+	public function toString () : String {
+		return _data.name;
+	}
+}
+
 }

+ 58 - 59
spine-as3/spine-as3/src/spine/PathConstraintData.as

@@ -1,62 +1,61 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public dynamic class PathConstraintData {
-	internal var _name:String;
-	internal var _bones:Vector.<BoneData> = new Vector.<BoneData>();
-	public var target:SlotData;
-	public var positionMode:PositionMode;
-	public var spacingMode:SpacingMode;
-	public var rotateMode:RotateMode;
-	public var offsetRotation:Number;
-	public var position:Number, spacing:Number, rotateMix:Number, translateMix:Number;
-
-	public function PathConstraintData (name:String) {
-		if (name == null) throw new ArgumentError("name cannot be null.");
-		_name = name;
-	}
-
-	public function get bones () : Vector.<BoneData> {
-		return _bones;
-	}
-	
-	public function get name () : String {
-		return _name;
-	}
-
-	public function toString () : String {
-		return name;
-	}
+package spine {
+
+public dynamic class PathConstraintData {
+	internal var _name:String;
+	internal var _bones:Vector.<BoneData> = new Vector.<BoneData>();
+	public var target:SlotData;
+	public var positionMode:PositionMode;
+	public var spacingMode:SpacingMode;
+	public var rotateMode:RotateMode;
+	public var offsetRotation:Number;
+	public var position:Number, spacing:Number, rotateMix:Number, translateMix:Number;
+
+	public function PathConstraintData (name:String) {
+		if (name == null) throw new ArgumentError("name cannot be null.");
+		_name = name;
+	}
+
+	public function get bones () : Vector.<BoneData> {
+		return _bones;
+	}
+	
+	public function get name () : String {
+		return _name;
+	}
+
+	public function toString () : String {
+		return name;
+	}
+}
+
 }
-
-}

+ 79 - 80
spine-as3/spine-as3/src/spine/Polygon.as

@@ -1,83 +1,82 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public class Polygon {
-	public var vertices:Vector.<Number> = new Vector.<Number>();
-	
-	public function Polygon () {		
-	}
-	
-	/** Returns true if the polygon contains the point. */
-	public function containsPoint (x:Number, y:Number) : Boolean {
-		var nn:int = vertices.length;
-		
-		var prevIndex:int = nn - 2;
-		var inside:Boolean = false;
-		for (var ii:int = 0; ii < nn; ii += 2) {
-			var vertexY:Number = vertices[ii + 1];
-			var prevY:Number = vertices[prevIndex + 1];
-			if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) {
-				var vertexX:Number = vertices[ii];
-				if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) inside = !inside;
-			}
-			prevIndex = ii;
-		}
-		
-		return inside;
-	}
-
-	/** Returns true if the polygon contains the line segment. */
-	public function intersectsSegment (x1:Number, y1:Number, x2:Number, y2:Number) : Boolean {
-		var nn:int = vertices.length;
-		
-		var width12:Number = x1 - x2, height12:Number = y1 - y2;
-		var det1:Number = x1 * y2 - y1 * x2;
-		var x3:Number = vertices[nn - 2], y3:Number = vertices[nn - 1];
-		for (var ii:int = 0; ii < nn; ii += 2) {
-			var x4:Number = vertices[ii], y4:Number = vertices[ii + 1];
-			var det2:Number = x3 * y4 - y3 * x4;
-			var width34:Number = x3 - x4, height34:Number = y3 - y4;
-			var det3:Number = width12 * height34 - height12 * width34;
-			var x:Number = (det1 * width34 - width12 * det2) / det3;
-			if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) {
-				var y:Number = (det1 * height34 - height12 * det2) / det3;
-				if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) return true;
-			}
-			x3 = x4;
-			y3 = y4;
-		}
-		return false;
-	}
-}
-
+package spine {
+
+public class Polygon {
+	public var vertices:Vector.<Number> = new Vector.<Number>();
+	
+	public function Polygon () {		
+	}
+	
+	/** Returns true if the polygon contains the point. */
+	public function containsPoint (x:Number, y:Number) : Boolean {
+		var nn:int = vertices.length;
+		
+		var prevIndex:int = nn - 2;
+		var inside:Boolean = false;
+		for (var ii:int = 0; ii < nn; ii += 2) {
+			var vertexY:Number = vertices[ii + 1];
+			var prevY:Number = vertices[prevIndex + 1];
+			if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) {
+				var vertexX:Number = vertices[ii];
+				if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) inside = !inside;
+			}
+			prevIndex = ii;
+		}
+		
+		return inside;
+	}
+
+	/** Returns true if the polygon contains the line segment. */
+	public function intersectsSegment (x1:Number, y1:Number, x2:Number, y2:Number) : Boolean {
+		var nn:int = vertices.length;
+		
+		var width12:Number = x1 - x2, height12:Number = y1 - y2;
+		var det1:Number = x1 * y2 - y1 * x2;
+		var x3:Number = vertices[nn - 2], y3:Number = vertices[nn - 1];
+		for (var ii:int = 0; ii < nn; ii += 2) {
+			var x4:Number = vertices[ii], y4:Number = vertices[ii + 1];
+			var det2:Number = x3 * y4 - y3 * x4;
+			var width34:Number = x3 - x4, height34:Number = y3 - y4;
+			var det3:Number = width12 * height34 - height12 * width34;
+			var x:Number = (det1 * width34 - width12 * det2) / det3;
+			if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) {
+				var y:Number = (det1 * height34 - height12 * det2) / det3;
+				if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) return true;
+			}
+			x3 = x4;
+			y3 = y4;
+		}
+		return false;
+	}
+}
+
 }

+ 35 - 36
spine-as3/spine-as3/src/spine/PositionMode.as

@@ -1,39 +1,38 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-	
-public class PositionMode {
-	public static const fixed:PositionMode = new PositionMode();
-	public static const percent:PositionMode = new PositionMode();
+package spine {
+	
+public class PositionMode {
+	public static const fixed:PositionMode = new PositionMode();
+	public static const percent:PositionMode = new PositionMode();
+}
+
 }
-
-}

+ 36 - 37
spine-as3/spine-as3/src/spine/RotateMode.as

@@ -1,40 +1,39 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public class RotateMode {
-	public static const tangent:RotateMode = new RotateMode();
-	public static const chain:RotateMode = new RotateMode();
-	public static const chainScale:RotateMode = new RotateMode();
+package spine {
+
+public class RotateMode {
+	public static const tangent:RotateMode = new RotateMode();
+	public static const chain:RotateMode = new RotateMode();
+	public static const chainScale:RotateMode = new RotateMode();
+}
+
 }
-
-}

+ 445 - 441
spine-as3/spine-as3/src/spine/Skeleton.as

@@ -1,444 +1,448 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-import flash.utils.Dictionary;
-import spine.attachments.PathAttachment;
-import spine.attachments.Attachment;
-
-public class Skeleton {
-	internal var _data:SkeletonData;
-	public var bones:Vector.<Bone>;
-	public var slots:Vector.<Slot>;
-	public var drawOrder:Vector.<Slot>;
-	public var ikConstraints:Vector.<IkConstraint>, ikConstraintsSorted:Vector.<IkConstraint>;
-	public var transformConstraints:Vector.<TransformConstraint>;
-	public var pathConstraints:Vector.<PathConstraint>;
-	private var _updateCache:Vector.<Updatable> = new Vector.<Updatable>();
-	private var _skin:Skin;
-	public var r:Number = 1, g:Number = 1, b:Number = 1, a:Number = 1;
-	public var time:Number = 0;
-	public var flipX:Boolean, flipY:Boolean;
-	public var x:Number = 0, y:Number = 0;
-
-	public function Skeleton (data:SkeletonData) {
-		if (data == null)
-			throw new ArgumentError("data cannot be null.");
-		_data = data;
-
-		bones = new Vector.<Bone>();
-		for each (var boneData:BoneData in data.bones) {
-			var bone:Bone;
-			if (boneData.parent == null)
-				bone = new Bone(boneData, this, null);
-			else {
-				var parent:Bone = bones[boneData.parent.index];
-				bone = new Bone(boneData, this, parent);
-				parent.children.push(bone);
-			}
-			bones.push(bone);
-		}
-
-		slots = new Vector.<Slot>();
-		drawOrder = new Vector.<Slot>();
-		for each (var slotData:SlotData in data.slots) {
-			bone = bones[slotData.boneData.index];
-			var slot:Slot = new Slot(slotData, bone);
-			slots.push(slot);
-			drawOrder[drawOrder.length] = slot;
-		}
-		
-		ikConstraints = new Vector.<IkConstraint>();
-		ikConstraintsSorted = new Vector.<IkConstraint>();
-		for each (var ikConstraintData:IkConstraintData in data.ikConstraints)
-			ikConstraints.push(new IkConstraint(ikConstraintData, this));
-		
-		transformConstraints = new Vector.<TransformConstraint>();
-		for each (var transformConstraintData:TransformConstraintData in data.transformConstraints)
-			transformConstraints.push(new TransformConstraint(transformConstraintData, this));
-
-		pathConstraints = new Vector.<PathConstraint>();
-		for each (var pathConstraintData:PathConstraintData in data.pathConstraints)
-			pathConstraints.push(new PathConstraint(pathConstraintData, this));
-
-		updateCache();
-	}
-
-	/** Caches information about bones and constraints. Must be called if bones, constraints, or weighted path attachments are
-	 * added or removed. */
-	public function updateCache () : void {
-		var updateCache:Vector.<Updatable> = this._updateCache;
-		updateCache.length = 0;
-
-		var bones:Vector.<Bone> = this.bones;
-		for (var i:int = 0, n:int = bones.length; i < n; i++)
-			bones[i]._sorted = false;
-
-		// IK first, lowest hierarchy depth first.
-		var ikConstraints:Vector.<IkConstraint> = this.ikConstraintsSorted;
-		ikConstraints.length = 0;
-		for each (var c:IkConstraint in this.ikConstraints)
-			ikConstraints.push(c);
-		var ikCount:int = ikConstraints.length;
-		var level:int;
-		for (i = 0, n = ikCount; i < n; i++) {
-			var ik:IkConstraint = ikConstraints[i];
-			var bone:Bone = ik.bones[0].parent;
-			for (level = 0; bone != null; level++)
-				bone = bone.parent;
-			ik.level = level;
-		}
-		var ii:int;
-		for (i = 1; i < ikCount; i++) {
-			ik = ikConstraints[i];
-			level = ik.level;
-			for (ii = i - 1; ii >= 0; ii--) {
-				var other:IkConstraint = ikConstraints[ii];
-				if (other.level < level) break;
-				ikConstraints[ii + 1] = other;
-			}
-			ikConstraints[ii + 1] = ik;
-		}
-		for (i = 0, n = ikConstraints.length; i < n; i++) {
-			var ikConstraint:IkConstraint = ikConstraints[i];
-			var target:Bone = ikConstraint.target;
-			sortBone(target);
-
-			var constrained:Vector.<Bone> = ikConstraint.bones;
-			var parent:Bone = constrained[0];
-			sortBone(parent);
-
-			updateCache.push(ikConstraint);
-
-			sortReset(parent.children);
-			constrained[constrained.length - 1]._sorted = true;
-		}
-
-		var pathConstraints:Vector.<PathConstraint> = this.pathConstraints;
-		for (i = 0, n = pathConstraints.length; i < n; i++) {
-			var pathConstraint:PathConstraint = pathConstraints[i];
-
-			var slot:Slot = pathConstraint.target;
-			var slotIndex:int = slot.data.index;
-			var slotBone:Bone = slot.bone;
-			if (skin != null) sortPathConstraintAttachment(skin, slotIndex, slotBone);
-			if (_data.defaultSkin != null && _data.defaultSkin != skin)
-				sortPathConstraintAttachment(_data.defaultSkin, slotIndex, slotBone);
-				
-			var nn:int;
-			for (ii = 0, nn = _data.skins.length; ii < nn; ii++)
-				sortPathConstraintAttachment(_data.skins[ii], slotIndex, slotBone);
-
-			var attachment:PathAttachment = slot.attachment as PathAttachment;
-			if (attachment != null) sortPathConstraintAttachment2(attachment, slotBone);
-
-			constrained = pathConstraint.bones;
-			var boneCount:int = constrained.length;
-			for (ii = 0; ii < boneCount; ii++)
-				sortBone(constrained[ii]);
-
-			updateCache.push(pathConstraint);
-
-			for (ii = 0; ii < boneCount; ii++)
-				sortReset(constrained[ii].children);
-			for (ii = 0; ii < boneCount; ii++)
-				constrained[ii]._sorted = true;
-		}
-
-		var transformConstraints:Vector.<TransformConstraint> = this.transformConstraints;
-		for (i = 0, n = transformConstraints.length; i < n; i++) {
-			var transformConstraint:TransformConstraint = transformConstraints[i];
-
-			sortBone(transformConstraint.target);
-
-			constrained = transformConstraint.bones;
-			boneCount = constrained.length;
-			for (ii = 0; ii < boneCount; ii++)
-				sortBone(constrained[ii]);
-
-			updateCache.push(transformConstraint);
-
-			for (ii = 0; ii < boneCount; ii++)
-				sortReset(constrained[ii].children);
-			for (ii = 0; ii < boneCount; ii++)
-				constrained[ii]._sorted = true;
-		}
-
-		for (i = 0, n = bones.length; i < n; i++)
-			sortBone(bones[i]);
-	}
-	
-	private function sortPathConstraintAttachment (skin:Skin, slotIndex:int, slotBone:Bone) : void {
-		var dict:Dictionary = skin.attachments[slotIndex];
-		if (!dict) return;
-		
-		for each (var value:Attachment in dict) {
-			sortPathConstraintAttachment2(value, slotBone);
-		}
-	}
-
-	private function sortPathConstraintAttachment2 (attachment:Attachment, slotBone:Bone) : void {
-		var pathAttachment:PathAttachment = attachment as PathAttachment;
-		if (!pathAttachment) return;
-		var pathBones:Vector.<int> = pathAttachment.bones;
-		if (pathBones == null)
-			sortBone(slotBone);
-		else {
-			var bones:Vector.<Bone> = this.bones;
-			for each (var boneIndex:int in pathBones)
-				sortBone(bones[boneIndex]);
-		}
-	}
-
-	private function sortBone (bone:Bone) : void {
-		if (bone._sorted) return;
-		var parent:Bone = bone.parent;
-		if (parent != null) sortBone(parent);
-		bone._sorted = true;
-		_updateCache.push(bone);
-	}
-
-	private function sortReset (bones:Vector.<Bone>) : void {
-		for (var i:int = 0, n:int = bones.length; i < n; i++) {
-			var bone:Bone = bones[i];
-			if (bone._sorted) sortReset(bone.children);
-			bone._sorted = false;
-		}
-	}
-
-	/** Updates the world transform for each bone and applies constraints. */
-	public function updateWorldTransform () : void {
-		for each (var updatable:Updatable in _updateCache)
-			updatable.update();
-	}
-
-	/** Sets the bones, constraints, and slots to their setup pose values. */
-	public function setToSetupPose () : void {
-		setBonesToSetupPose();
-		setSlotsToSetupPose();
-	}
-
-	/** Sets the bones and constraints to their setup pose values. */
-	public function setBonesToSetupPose () : void {
-		for each (var bone:Bone in bones)
-			bone.setToSetupPose();
-
-		for each (var ikConstraint:IkConstraint in ikConstraints) {
-			ikConstraint.bendDirection = ikConstraint._data.bendDirection;
-			ikConstraint.mix = ikConstraint._data.mix;
-		}
-
-		for each (var transformConstraint:TransformConstraint in transformConstraints) {
-			transformConstraint.rotateMix = transformConstraint._data.rotateMix;
-			transformConstraint.translateMix = transformConstraint._data.translateMix;
-			transformConstraint.scaleMix = transformConstraint._data.scaleMix;
-			transformConstraint.shearMix = transformConstraint._data.shearMix;
-		}
-		
-		for each (var pathConstraint:PathConstraint in pathConstraints) {
-			pathConstraint.position = pathConstraint._data.position;
-			pathConstraint.spacing = pathConstraint._data.spacing;
-			pathConstraint.rotateMix = pathConstraint._data.rotateMix;
-			pathConstraint.translateMix = pathConstraint._data.translateMix;
-		}
-	}
-
-	public function setSlotsToSetupPose () : void {
-		var i:int = 0;
-		for each (var slot:Slot in slots) { 
-			drawOrder[i++] = slot;
-			slot.setToSetupPose();
-		}
-	}
-
-	public function get data () : SkeletonData {
-		return _data;
-	}
-	
-	public function get getUpdateCache () : Vector.<Updatable> {
-		return _updateCache;
-	}
-
-	public function get rootBone () : Bone {
-		if (bones.length == 0) return null;
-		return bones[0];
-	}
-
-	/** @return May be null. */
-	public function findBone (boneName:String) : Bone {
-		if (boneName == null)
-			throw new ArgumentError("boneName cannot be null.");
-		for each (var bone:Bone in bones)
-			if (bone._data._name == boneName) return bone;
-		return null;
-	}
-
-	/** @return -1 if the bone was not found. */
-	public function findBoneIndex (boneName:String) : int {
-		if (boneName == null)
-			throw new ArgumentError("boneName cannot be null.");
-		var i:int = 0;
-		for each (var bone:Bone in bones) {
-			if (bone._data._name == boneName) return i;
-			i++;
-		}
-		return -1;
-	}
-
-	/** @return May be null. */
-	public function findSlot (slotName:String) : Slot {
-		if (slotName == null)
-			throw new ArgumentError("slotName cannot be null.");
-		for each (var slot:Slot in slots)
-			if (slot._data._name == slotName) return slot;
-		return null;
-	}
-
-	/** @return -1 if the bone was not found. */
-	public function findSlotIndex (slotName:String) : int {
-		if (slotName == null)
-			throw new ArgumentError("slotName cannot be null.");
-		var i:int = 0;
-		for each (var slot:Slot in slots) {
-			if (slot._data._name == slotName) return i;
-			i++;
-		}
-		return -1;
-	}
-
-	public function get skin () : Skin {
-		return _skin;
-	}
-
-	public function set skinName (skinName:String) : void {
-		var skin:Skin = data.findSkin(skinName);
-		if (skin == null) throw new ArgumentError("Skin not found: " + skinName);
-		this.skin = skin;
-	}
-
-	/** @return May be null. */
-	public function get skinName () : String {
-		return _skin == null ? null : _skin._name;
-	}
-
-	/** Sets the skin used to look up attachments before looking in the {@link SkeletonData#getDefaultSkin() default skin}. 
-	 * Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was 
-	 * no old skin, each slot's setup mode attachment is attached from the new skin.
-	 * @param newSkin May be null. */
-	public function set skin (newSkin:Skin) : void {
-		if (newSkin) {
-			if (skin)
-				newSkin.attachAll(this, skin);
-			else {
-				var i:int = 0;
-				for each (var slot:Slot in slots) {
-					var name:String = slot._data.attachmentName;
-					if (name) {
-						var attachment:Attachment = newSkin.getAttachment(i, name);
-						if (attachment) slot.attachment = attachment;
-					}
-					i++;
-				}
-			}
-		}
-		_skin = newSkin;
-	}
-
-	/** @return May be null. */
-	public function getAttachmentForSlotName (slotName:String, attachmentName:String) : Attachment {
-		return getAttachmentForSlotIndex(data.findSlotIndex(slotName), attachmentName);
-	}
-
-	/** @return May be null. */
-	public function getAttachmentForSlotIndex (slotIndex:int, attachmentName:String) : Attachment {
-		if (attachmentName == null) throw new ArgumentError("attachmentName cannot be null.");
-		if (skin != null) {
-			var attachment:Attachment = skin.getAttachment(slotIndex, attachmentName);
-			if (attachment != null) return attachment;
-		}
-		if (data.defaultSkin != null) return data.defaultSkin.getAttachment(slotIndex, attachmentName);
-		return null;
-	}
-
-	/** @param attachmentName May be null. */
-	public function setAttachment (slotName:String, attachmentName:String) : void {
-		if (slotName == null) throw new ArgumentError("slotName cannot be null.");
-		var i:int = 0;
-		for each (var slot:Slot in slots) {
-			if (slot._data._name == slotName) {
-				var attachment:Attachment = null;
-				if (attachmentName != null) {
-					attachment = getAttachmentForSlotIndex(i, attachmentName);
-					if (attachment == null)
-						throw new ArgumentError("Attachment not found: " + attachmentName + ", for slot: " + slotName);
-				}
-				slot.attachment = attachment;
-				return;
-			}
-			i++;
-		}
-		throw new ArgumentError("Slot not found: " + slotName);
-	}
-
-	/** @return May be null. */
-	public function findIkConstraint (constraintName:String) : IkConstraint {
-		if (constraintName == null) throw new ArgumentError("constraintName cannot be null.");
-		for each (var ikConstraint:IkConstraint in ikConstraints)
-			if (ikConstraint._data._name == constraintName) return ikConstraint;
-		return null;
-	}
-
-	/** @return May be null. */
-	public function findTransformConstraint (constraintName:String) : TransformConstraint {
-		if (constraintName == null) throw new ArgumentError("constraintName cannot be null.");
-		for each (var transformConstraint:TransformConstraint in transformConstraints)
-			if (transformConstraint._data._name == constraintName) return transformConstraint;
-		return null;
-	}
-	
-	/** @return May be null. */
-	public function findPathConstraint (constraintName:String) : PathConstraint {
-		if (constraintName == null) throw new ArgumentError("constraintName cannot be null.");
-		for each (var pathConstraint:PathConstraint in pathConstraints)
-			if (pathConstraint._data._name == constraintName) return pathConstraint;
-		return null;
-	}
-
-	public function update (delta:Number) : void {
-		time += delta;
-	}
-
-	public function toString () : String {
-		return _data.name != null ? _data.name : super.toString();
-	}
-}
-
+package spine {
+import flash.utils.Dictionary;
+import spine.attachments.PathAttachment;
+import spine.attachments.Attachment;
+
+public class Skeleton {
+	internal var _data:SkeletonData;
+	public var bones:Vector.<Bone>;
+	public var slots:Vector.<Slot>;
+	public var drawOrder:Vector.<Slot>;
+	public var ikConstraints:Vector.<IkConstraint>, ikConstraintsSorted:Vector.<IkConstraint>;
+	public var transformConstraints:Vector.<TransformConstraint>;
+	public var pathConstraints:Vector.<PathConstraint>;
+	private var _updateCache:Vector.<Updatable> = new Vector.<Updatable>();
+	private var _skin:Skin;
+	public var r:Number = 1, g:Number = 1, b:Number = 1, a:Number = 1;
+	public var time:Number = 0;
+	public var flipX:Boolean, flipY:Boolean;
+	public var x:Number = 0, y:Number = 0;
+
+	public function Skeleton (data:SkeletonData) {
+		if (data == null)
+			throw new ArgumentError("data cannot be null.");
+		_data = data;
+
+		bones = new Vector.<Bone>();
+		for each (var boneData:BoneData in data.bones) {
+			var bone:Bone;
+			if (boneData.parent == null)
+				bone = new Bone(boneData, this, null);
+			else {
+				var parent:Bone = bones[boneData.parent.index];
+				bone = new Bone(boneData, this, parent);
+				parent.children.push(bone);
+			}
+			bones.push(bone);
+		}
+
+		slots = new Vector.<Slot>();
+		drawOrder = new Vector.<Slot>();
+		for each (var slotData:SlotData in data.slots) {
+			bone = bones[slotData.boneData.index];
+			var slot:Slot = new Slot(slotData, bone);
+			slots.push(slot);
+			drawOrder[drawOrder.length] = slot;
+		}
+		
+		ikConstraints = new Vector.<IkConstraint>();
+		ikConstraintsSorted = new Vector.<IkConstraint>();
+		for each (var ikConstraintData:IkConstraintData in data.ikConstraints)
+			ikConstraints.push(new IkConstraint(ikConstraintData, this));
+		
+		transformConstraints = new Vector.<TransformConstraint>();
+		for each (var transformConstraintData:TransformConstraintData in data.transformConstraints)
+			transformConstraints.push(new TransformConstraint(transformConstraintData, this));
+
+		pathConstraints = new Vector.<PathConstraint>();
+		for each (var pathConstraintData:PathConstraintData in data.pathConstraints)
+			pathConstraints.push(new PathConstraint(pathConstraintData, this));
+
+		updateCache();
+	}
+
+	/** Caches information about bones and constraints. Must be called if bones, constraints, or weighted path attachments are
+	 * added or removed. */
+	public function updateCache () : void {
+		var updateCache:Vector.<Updatable> = this._updateCache;
+		updateCache.length = 0;
+
+		var bones:Vector.<Bone> = this.bones;
+		for (var i:int = 0, n:int = bones.length; i < n; i++)
+			bones[i]._sorted = false;
+
+		// IK first, lowest hierarchy depth first.
+		var ikConstraints:Vector.<IkConstraint> = this.ikConstraintsSorted;
+		ikConstraints.length = 0;
+		for each (var c:IkConstraint in this.ikConstraints)
+			ikConstraints.push(c);
+		var ikCount:int = ikConstraints.length;
+		var level:int;
+		for (i = 0, n = ikCount; i < n; i++) {
+			var ik:IkConstraint = ikConstraints[i];
+			var bone:Bone = ik.bones[0].parent;
+			for (level = 0; bone != null; level++)
+				bone = bone.parent;
+			ik.level = level;
+		}
+		var ii:int;
+		for (i = 1; i < ikCount; i++) {
+			ik = ikConstraints[i];
+			level = ik.level;
+			for (ii = i - 1; ii >= 0; ii--) {
+				var other:IkConstraint = ikConstraints[ii];
+				if (other.level < level) break;
+				ikConstraints[ii + 1] = other;
+			}
+			ikConstraints[ii + 1] = ik;
+		}
+		for (i = 0, n = ikConstraints.length; i < n; i++) {
+			var ikConstraint:IkConstraint = ikConstraints[i];
+			var target:Bone = ikConstraint.target;
+			sortBone(target);
+
+			var constrained:Vector.<Bone> = ikConstraint.bones;
+			var parent:Bone = constrained[0];
+			sortBone(parent);
+
+			updateCache.push(ikConstraint);
+
+			sortReset(parent.children);
+			constrained[constrained.length - 1]._sorted = true;
+		}
+
+		var pathConstraints:Vector.<PathConstraint> = this.pathConstraints;
+		for (i = 0, n = pathConstraints.length; i < n; i++) {
+			var pathConstraint:PathConstraint = pathConstraints[i];
+
+			var slot:Slot = pathConstraint.target;
+			var slotIndex:int = slot.data.index;
+			var slotBone:Bone = slot.bone;
+			if (skin != null) sortPathConstraintAttachment(skin, slotIndex, slotBone);
+			if (_data.defaultSkin != null && _data.defaultSkin != skin)
+				sortPathConstraintAttachment(_data.defaultSkin, slotIndex, slotBone);
+				
+			var nn:int;
+			for (ii = 0, nn = _data.skins.length; ii < nn; ii++)
+				sortPathConstraintAttachment(_data.skins[ii], slotIndex, slotBone);
+
+			var attachment:PathAttachment = slot.attachment as PathAttachment;
+			if (attachment != null) sortPathConstraintAttachment2(attachment, slotBone);
+
+			constrained = pathConstraint.bones;
+			var boneCount:int = constrained.length;
+			for (ii = 0; ii < boneCount; ii++)
+				sortBone(constrained[ii]);
+
+			updateCache.push(pathConstraint);
+
+			for (ii = 0; ii < boneCount; ii++)
+				sortReset(constrained[ii].children);
+			for (ii = 0; ii < boneCount; ii++)
+				constrained[ii]._sorted = true;
+		}
+
+		var transformConstraints:Vector.<TransformConstraint> = this.transformConstraints;
+		for (i = 0, n = transformConstraints.length; i < n; i++) {
+			var transformConstraint:TransformConstraint = transformConstraints[i];
+
+			sortBone(transformConstraint.target);
+
+			constrained = transformConstraint.bones;
+			boneCount = constrained.length;
+			for (ii = 0; ii < boneCount; ii++)
+				sortBone(constrained[ii]);
+
+			updateCache.push(transformConstraint);
+
+			for (ii = 0; ii < boneCount; ii++)
+				sortReset(constrained[ii].children);
+			for (ii = 0; ii < boneCount; ii++)
+				constrained[ii]._sorted = true;
+		}
+
+		for (i = 0, n = bones.length; i < n; i++)
+			sortBone(bones[i]);
+	}
+	
+	private function sortPathConstraintAttachment (skin:Skin, slotIndex:int, slotBone:Bone) : void {
+		var dict:Dictionary = skin.attachments[slotIndex];
+		if (!dict) return;
+		
+		for each (var value:Attachment in dict) {
+			sortPathConstraintAttachment2(value, slotBone);
+		}
+	}
+
+	private function sortPathConstraintAttachment2 (attachment:Attachment, slotBone:Bone) : void {
+		var pathAttachment:PathAttachment = attachment as PathAttachment;
+		if (!pathAttachment) return;
+		var pathBones:Vector.<int> = pathAttachment.bones;
+		if (pathBones == null)
+			sortBone(slotBone);
+		else {
+			var bones:Vector.<Bone> = this.bones;
+			var i:int = 0;
+			while (i < pathBones.length) {
+				var boneCount:int = pathBones[i++];
+				for (var n:int = i + boneCount; i < n; i++) {				
+					sortBone(bones[pathBones[i]]);
+				}
+			}
+		}
+	}
+
+	private function sortBone (bone:Bone) : void {
+		if (bone._sorted) return;
+		var parent:Bone = bone.parent;
+		if (parent != null) sortBone(parent);
+		bone._sorted = true;
+		_updateCache.push(bone);
+	}
+
+	private function sortReset (bones:Vector.<Bone>) : void {
+		for (var i:int = 0, n:int = bones.length; i < n; i++) {
+			var bone:Bone = bones[i];
+			if (bone._sorted) sortReset(bone.children);
+			bone._sorted = false;
+		}
+	}
+
+	/** Updates the world transform for each bone and applies constraints. */
+	public function updateWorldTransform () : void {
+		for each (var updatable:Updatable in _updateCache)
+			updatable.update();
+	}
+
+	/** Sets the bones, constraints, and slots to their setup pose values. */
+	public function setToSetupPose () : void {
+		setBonesToSetupPose();
+		setSlotsToSetupPose();
+	}
+
+	/** Sets the bones and constraints to their setup pose values. */
+	public function setBonesToSetupPose () : void {
+		for each (var bone:Bone in bones)
+			bone.setToSetupPose();
+
+		for each (var ikConstraint:IkConstraint in ikConstraints) {
+			ikConstraint.bendDirection = ikConstraint._data.bendDirection;
+			ikConstraint.mix = ikConstraint._data.mix;
+		}
+
+		for each (var transformConstraint:TransformConstraint in transformConstraints) {
+			transformConstraint.rotateMix = transformConstraint._data.rotateMix;
+			transformConstraint.translateMix = transformConstraint._data.translateMix;
+			transformConstraint.scaleMix = transformConstraint._data.scaleMix;
+			transformConstraint.shearMix = transformConstraint._data.shearMix;
+		}
+		
+		for each (var pathConstraint:PathConstraint in pathConstraints) {
+			pathConstraint.position = pathConstraint._data.position;
+			pathConstraint.spacing = pathConstraint._data.spacing;
+			pathConstraint.rotateMix = pathConstraint._data.rotateMix;
+			pathConstraint.translateMix = pathConstraint._data.translateMix;
+		}
+	}
+
+	public function setSlotsToSetupPose () : void {
+		var i:int = 0;
+		for each (var slot:Slot in slots) { 
+			drawOrder[i++] = slot;
+			slot.setToSetupPose();
+		}
+	}
+
+	public function get data () : SkeletonData {
+		return _data;
+	}
+	
+	public function get getUpdateCache () : Vector.<Updatable> {
+		return _updateCache;
+	}
+
+	public function get rootBone () : Bone {
+		if (bones.length == 0) return null;
+		return bones[0];
+	}
+
+	/** @return May be null. */
+	public function findBone (boneName:String) : Bone {
+		if (boneName == null)
+			throw new ArgumentError("boneName cannot be null.");
+		for each (var bone:Bone in bones)
+			if (bone._data._name == boneName) return bone;
+		return null;
+	}
+
+	/** @return -1 if the bone was not found. */
+	public function findBoneIndex (boneName:String) : int {
+		if (boneName == null)
+			throw new ArgumentError("boneName cannot be null.");
+		var i:int = 0;
+		for each (var bone:Bone in bones) {
+			if (bone._data._name == boneName) return i;
+			i++;
+		}
+		return -1;
+	}
+
+	/** @return May be null. */
+	public function findSlot (slotName:String) : Slot {
+		if (slotName == null)
+			throw new ArgumentError("slotName cannot be null.");
+		for each (var slot:Slot in slots)
+			if (slot._data._name == slotName) return slot;
+		return null;
+	}
+
+	/** @return -1 if the bone was not found. */
+	public function findSlotIndex (slotName:String) : int {
+		if (slotName == null)
+			throw new ArgumentError("slotName cannot be null.");
+		var i:int = 0;
+		for each (var slot:Slot in slots) {
+			if (slot._data._name == slotName) return i;
+			i++;
+		}
+		return -1;
+	}
+
+	public function get skin () : Skin {
+		return _skin;
+	}
+
+	public function set skinName (skinName:String) : void {
+		var skin:Skin = data.findSkin(skinName);
+		if (skin == null) throw new ArgumentError("Skin not found: " + skinName);
+		this.skin = skin;
+	}
+
+	/** @return May be null. */
+	public function get skinName () : String {
+		return _skin == null ? null : _skin._name;
+	}
+
+	/** Sets the skin used to look up attachments before looking in the {@link SkeletonData#getDefaultSkin() default skin}. 
+	 * Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was 
+	 * no old skin, each slot's setup mode attachment is attached from the new skin.
+	 * @param newSkin May be null. */
+	public function set skin (newSkin:Skin) : void {
+		if (newSkin) {
+			if (skin)
+				newSkin.attachAll(this, skin);
+			else {
+				var i:int = 0;
+				for each (var slot:Slot in slots) {
+					var name:String = slot._data.attachmentName;
+					if (name) {
+						var attachment:Attachment = newSkin.getAttachment(i, name);
+						if (attachment) slot.attachment = attachment;
+					}
+					i++;
+				}
+			}
+		}
+		_skin = newSkin;
+	}
+
+	/** @return May be null. */
+	public function getAttachmentForSlotName (slotName:String, attachmentName:String) : Attachment {
+		return getAttachmentForSlotIndex(data.findSlotIndex(slotName), attachmentName);
+	}
+
+	/** @return May be null. */
+	public function getAttachmentForSlotIndex (slotIndex:int, attachmentName:String) : Attachment {
+		if (attachmentName == null) throw new ArgumentError("attachmentName cannot be null.");
+		if (skin != null) {
+			var attachment:Attachment = skin.getAttachment(slotIndex, attachmentName);
+			if (attachment != null) return attachment;
+		}
+		if (data.defaultSkin != null) return data.defaultSkin.getAttachment(slotIndex, attachmentName);
+		return null;
+	}
+
+	/** @param attachmentName May be null. */
+	public function setAttachment (slotName:String, attachmentName:String) : void {
+		if (slotName == null) throw new ArgumentError("slotName cannot be null.");
+		var i:int = 0;
+		for each (var slot:Slot in slots) {
+			if (slot._data._name == slotName) {
+				var attachment:Attachment = null;
+				if (attachmentName != null) {
+					attachment = getAttachmentForSlotIndex(i, attachmentName);
+					if (attachment == null)
+						throw new ArgumentError("Attachment not found: " + attachmentName + ", for slot: " + slotName);
+				}
+				slot.attachment = attachment;
+				return;
+			}
+			i++;
+		}
+		throw new ArgumentError("Slot not found: " + slotName);
+	}
+
+	/** @return May be null. */
+	public function findIkConstraint (constraintName:String) : IkConstraint {
+		if (constraintName == null) throw new ArgumentError("constraintName cannot be null.");
+		for each (var ikConstraint:IkConstraint in ikConstraints)
+			if (ikConstraint._data._name == constraintName) return ikConstraint;
+		return null;
+	}
+
+	/** @return May be null. */
+	public function findTransformConstraint (constraintName:String) : TransformConstraint {
+		if (constraintName == null) throw new ArgumentError("constraintName cannot be null.");
+		for each (var transformConstraint:TransformConstraint in transformConstraints)
+			if (transformConstraint._data._name == constraintName) return transformConstraint;
+		return null;
+	}
+	
+	/** @return May be null. */
+	public function findPathConstraint (constraintName:String) : PathConstraint {
+		if (constraintName == null) throw new ArgumentError("constraintName cannot be null.");
+		for each (var pathConstraint:PathConstraint in pathConstraints)
+			if (pathConstraint._data._name == constraintName) return pathConstraint;
+		return null;
+	}
+
+	public function update (delta:Number) : void {
+		time += delta;
+	}
+
+	public function toString () : String {
+		return _data.name != null ? _data.name : super.toString();
+	}
+}
+
 }

+ 149 - 150
spine-as3/spine-as3/src/spine/SkeletonBounds.as

@@ -1,153 +1,152 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-import spine.attachments.BoundingBoxAttachment;
-
-public class SkeletonBounds {
-	private var polygonPool:Vector.<Polygon> = new Vector.<Polygon>();
-
-	public var boundingBoxes:Vector.<BoundingBoxAttachment> = new Vector.<BoundingBoxAttachment>();
-	public var polygons:Vector.<Polygon> = new Vector.<Polygon>();
-	public var minX:Number, minY:Number, maxX:Number, maxY:Number;
-	
-	public function SkeletonBounds () {		
-	}
-
-	public function update (skeleton:Skeleton, updateAabb:Boolean) : void {
-		var slots:Vector.<Slot> = skeleton.slots;
-		var slotCount:int = slots.length;		
-
-		boundingBoxes.length = 0;
-		for each (var polygon:Polygon in polygons)
-			polygonPool[polygonPool.length] = polygon;
-		polygons.length = 0;
-
-		for (var i:int = 0; i < slotCount; i++) {
-			var slot:Slot = slots[i];
-			var boundingBox:BoundingBoxAttachment = slot.attachment as BoundingBoxAttachment;
-			if (boundingBox == null) continue;
-			boundingBoxes[boundingBoxes.length] = boundingBox;
-
-			var poolCount:int = polygonPool.length;
-			if (poolCount > 0) {
-				polygon = polygonPool[poolCount - 1];
-				polygonPool.splice(poolCount - 1, 1);
-			} else
-				polygon = new Polygon();
-			polygons[polygons.length] = polygon;
-
-			polygon.vertices.length = boundingBox.worldVerticesLength;
-			boundingBox.computeWorldVertices(slot, polygon.vertices);
-		}
-
-		if (updateAabb) aabbCompute();
-	}
-
-	private function aabbCompute () : void {
-		var minX:Number = Number.MAX_VALUE, minY:Number = Number.MAX_VALUE;
-		var maxX:Number = -Number.MAX_VALUE, maxY:Number = -Number.MAX_VALUE;
-		for (var i:int = 0, n:int = polygons.length; i < n; i++) {
-			var polygon:Polygon = polygons[i];
-			var vertices:Vector.<Number> = polygon.vertices;
-			for (var ii:int = 0, nn:int = vertices.length; ii < nn; ii += 2) {
-				var x:Number = vertices[ii];
-				var y:Number = vertices[ii + 1];
-				minX = Math.min(minX, x);
-				minY = Math.min(minY, y);
-				maxX = Math.max(maxX, x);
-				maxY = Math.max(maxY, y);
-			}
-		}
-		this.minX = minX;
-		this.minY = minY;
-		this.maxX = maxX;
-		this.maxY = maxY;
-	}
-	
-	
-	/** Returns true if the axis aligned bounding box contains the point. */
-	public function aabbContainsPoint (x:Number, y:Number) : Boolean {
-		return x >= minX && x <= maxX && y >= minY && y <= maxY;
-	}
-	
-	/** Returns true if the axis aligned bounding box intersects the line segment. */
-	public function aabbIntersectsSegment (x1:Number, y1:Number, x2:Number, y2:Number) : Boolean {
-		if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY))
-			return false;
-		var m:Number = (y2 - y1) / (x2 - x1);
-		var y:Number = m * (minX - x1) + y1;
-		if (y > minY && y < maxY) return true;
-		y = m * (maxX - x1) + y1;
-		if (y > minY && y < maxY) return true;
-		var x:Number = (minY - y1) / m + x1;
-		if (x > minX && x < maxX) return true;
-		x = (maxY - y1) / m + x1;
-		if (x > minX && x < maxX) return true;
-		return false;
-	}
-	
-	/** Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. */
-	public function aabbIntersectsSkeleton (bounds:SkeletonBounds) : Boolean {
-		return minX < bounds.maxX && maxX > bounds.minX && minY < bounds.maxY && maxY > bounds.minY;
-	}
-	
-	/** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more
-	 * efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. */
-	public function containsPoint (x:Number, y:Number) : BoundingBoxAttachment {
-		for (var i:int = 0, n:int = polygons.length; i < n; i++)
-			if (polygons[i].containsPoint(x, y)) return boundingBoxes[i];
-		return null;
-	}
-	
-	/** Returns the first bounding box attachment that contains the line segment, or null. When doing many checks, it is usually
-	 * more efficient to only call this method if {@link #aabbIntersectsSegment(float, float, float, float)} returns true. */
-	public function intersectsSegment (x1:Number, y1:Number, x2:Number, y2:Number) : BoundingBoxAttachment {
-		for (var i:int = 0, n:int = polygons.length; i < n; i++)
-			if (polygons[i].intersectsSegment(x1, y1, x2, y2)) return boundingBoxes[i];
-		return null;
-	}
-
-	public function getPolygon (attachment:BoundingBoxAttachment) : Polygon {
-		var index:int = boundingBoxes.indexOf(attachment);
-		return index == -1 ? null : polygons[index];
-	}
-
-	public function get width () : Number {
-		return maxX - minX;
-	}
-	
-	public function get height () : Number {
-		return maxY - minY;
-	}
-}
-
+package spine {
+import spine.attachments.BoundingBoxAttachment;
+
+public class SkeletonBounds {
+	private var polygonPool:Vector.<Polygon> = new Vector.<Polygon>();
+
+	public var boundingBoxes:Vector.<BoundingBoxAttachment> = new Vector.<BoundingBoxAttachment>();
+	public var polygons:Vector.<Polygon> = new Vector.<Polygon>();
+	public var minX:Number, minY:Number, maxX:Number, maxY:Number;
+	
+	public function SkeletonBounds () {		
+	}
+
+	public function update (skeleton:Skeleton, updateAabb:Boolean) : void {
+		var slots:Vector.<Slot> = skeleton.slots;
+		var slotCount:int = slots.length;		
+
+		boundingBoxes.length = 0;
+		for each (var polygon:Polygon in polygons)
+			polygonPool[polygonPool.length] = polygon;
+		polygons.length = 0;
+
+		for (var i:int = 0; i < slotCount; i++) {
+			var slot:Slot = slots[i];
+			var boundingBox:BoundingBoxAttachment = slot.attachment as BoundingBoxAttachment;
+			if (boundingBox == null) continue;
+			boundingBoxes[boundingBoxes.length] = boundingBox;
+
+			var poolCount:int = polygonPool.length;
+			if (poolCount > 0) {
+				polygon = polygonPool[poolCount - 1];
+				polygonPool.splice(poolCount - 1, 1);
+			} else
+				polygon = new Polygon();
+			polygons[polygons.length] = polygon;
+
+			polygon.vertices.length = boundingBox.worldVerticesLength;
+			boundingBox.computeWorldVertices(slot, polygon.vertices);
+		}
+
+		if (updateAabb) aabbCompute();
+	}
+
+	private function aabbCompute () : void {
+		var minX:Number = Number.MAX_VALUE, minY:Number = Number.MAX_VALUE;
+		var maxX:Number = -Number.MAX_VALUE, maxY:Number = -Number.MAX_VALUE;
+		for (var i:int = 0, n:int = polygons.length; i < n; i++) {
+			var polygon:Polygon = polygons[i];
+			var vertices:Vector.<Number> = polygon.vertices;
+			for (var ii:int = 0, nn:int = vertices.length; ii < nn; ii += 2) {
+				var x:Number = vertices[ii];
+				var y:Number = vertices[ii + 1];
+				minX = Math.min(minX, x);
+				minY = Math.min(minY, y);
+				maxX = Math.max(maxX, x);
+				maxY = Math.max(maxY, y);
+			}
+		}
+		this.minX = minX;
+		this.minY = minY;
+		this.maxX = maxX;
+		this.maxY = maxY;
+	}
+	
+	
+	/** Returns true if the axis aligned bounding box contains the point. */
+	public function aabbContainsPoint (x:Number, y:Number) : Boolean {
+		return x >= minX && x <= maxX && y >= minY && y <= maxY;
+	}
+	
+	/** Returns true if the axis aligned bounding box intersects the line segment. */
+	public function aabbIntersectsSegment (x1:Number, y1:Number, x2:Number, y2:Number) : Boolean {
+		if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY))
+			return false;
+		var m:Number = (y2 - y1) / (x2 - x1);
+		var y:Number = m * (minX - x1) + y1;
+		if (y > minY && y < maxY) return true;
+		y = m * (maxX - x1) + y1;
+		if (y > minY && y < maxY) return true;
+		var x:Number = (minY - y1) / m + x1;
+		if (x > minX && x < maxX) return true;
+		x = (maxY - y1) / m + x1;
+		if (x > minX && x < maxX) return true;
+		return false;
+	}
+	
+	/** Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. */
+	public function aabbIntersectsSkeleton (bounds:SkeletonBounds) : Boolean {
+		return minX < bounds.maxX && maxX > bounds.minX && minY < bounds.maxY && maxY > bounds.minY;
+	}
+	
+	/** Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more
+	 * efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true. */
+	public function containsPoint (x:Number, y:Number) : BoundingBoxAttachment {
+		for (var i:int = 0, n:int = polygons.length; i < n; i++)
+			if (polygons[i].containsPoint(x, y)) return boundingBoxes[i];
+		return null;
+	}
+	
+	/** Returns the first bounding box attachment that contains the line segment, or null. When doing many checks, it is usually
+	 * more efficient to only call this method if {@link #aabbIntersectsSegment(float, float, float, float)} returns true. */
+	public function intersectsSegment (x1:Number, y1:Number, x2:Number, y2:Number) : BoundingBoxAttachment {
+		for (var i:int = 0, n:int = polygons.length; i < n; i++)
+			if (polygons[i].intersectsSegment(x1, y1, x2, y2)) return boundingBoxes[i];
+		return null;
+	}
+
+	public function getPolygon (attachment:BoundingBoxAttachment) : Polygon {
+		var index:int = boundingBoxes.indexOf(attachment);
+		return index == -1 ? null : polygons[index];
+	}
+
+	public function get width () : Number {
+		return maxX - minX;
+	}
+	
+	public function get height () : Number {
+		return maxY - minY;
+	}
+}
+
 }

+ 177 - 178
spine-as3/spine-as3/src/spine/SkeletonData.as

@@ -1,181 +1,180 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-import spine.animation.Animation;
-
-public class SkeletonData {
-	/** May be null. */
-	public var name:String;
-	public var bones:Vector.<BoneData> = new Vector.<BoneData>(); // Ordered parents first.
-	public var slots:Vector.<SlotData> = new Vector.<SlotData>(); // Setup pose draw order.
-	public var skins:Vector.<Skin> = new Vector.<Skin>();
-	public var defaultSkin:Skin;
-	public var events:Vector.<EventData> = new Vector.<EventData>();
-	public var animations:Vector.<Animation> = new Vector.<Animation>();
-	public var ikConstraints:Vector.<IkConstraintData> = new Vector.<IkConstraintData>();
-	public var transformConstraints:Vector.<TransformConstraintData> = new Vector.<TransformConstraintData>();
-	public var pathConstraints:Vector.<PathConstraintData> = new Vector.<PathConstraintData>();
-	public var width:Number, height:Number;
-	public var version:String, hash:String;
-	
-	public function SkeletonData () {		
-	}
-
-	// --- Bones.
-
-	/** @return May be null. */
-	public function findBone (boneName:String) : BoneData {
-		if (boneName == null) throw new ArgumentError("boneName cannot be null.");
-		for (var i:int = 0, n:int = bones.length; i < n; i++) {
-			var bone:BoneData = bones[i];
-			if (bone._name == boneName) return bone;
-		}
-		return null;
-	}
-
-	/** @return -1 if the bone was not found. */
-	public function findBoneIndex (boneName:String) : int {
-		if (boneName == null) throw new ArgumentError("boneName cannot be null.");
-		for (var i:int = 0, n:int = bones.length; i < n; i++)
-			if (bones[i]._name == boneName) return i;
-		return -1;
-	}
-
-	// --- Slots.
-
-	/** @return May be null. */
-	public function findSlot (slotName:String) : SlotData {
-		if (slotName == null) throw new ArgumentError("slotName cannot be null.");
-		for (var i:int = 0, n:int = slots.length; i < n; i++) {
-			var slot:SlotData = slots[i];
-			if (slot._name == slotName) return slot;
-		}
-		return null;
-	}
-
-	/** @return -1 if the bone was not found. */
-	public function findSlotIndex (slotName:String) : int {
-		if (slotName == null) throw new ArgumentError("slotName cannot be null.");
-		for (var i:int = 0, n:int = slots.length; i < n; i++)
-			if (slots[i]._name == slotName) return i;
-		return -1;
-	}
-
-	// --- Skins.
-
-	/** @return May be null. */
-	public function findSkin (skinName:String) : Skin {
-		if (skinName == null) throw new ArgumentError("skinName cannot be null.");
-		for each (var skin:Skin in skins)
-			if (skin._name == skinName) return skin;
-		return null;
-	}
-	
-	// --- Events.
-	
-	/** @return May be null. */
-	public function findEvent (eventName:String) : EventData {
-		if (eventName == null) throw new ArgumentError("eventName cannot be null.");
-		for each (var eventData:EventData in events)
-			if (eventData._name == eventName) return eventData;
-		return null;
-	}
-	
-	// --- Animations.
-	
-	/** @return May be null. */
-	public function findAnimation (animationName:String) : Animation {
-		if (animationName == null) throw new ArgumentError("animationName cannot be null.");
-		for each (var animation:Animation in animations)
-			if (animation.name == animationName) return animation;
-		return null;
-	}
-	
-	// --- IK constraints.
-
-	/** @return May be null. */
-	public function findIkConstraint (constraintName:String) : IkConstraintData {
-		if (constraintName == null) throw new ArgumentError("constraintName cannot be null.");
-		for each (var ikConstraintData:IkConstraintData in ikConstraints)
-			if (ikConstraintData._name == constraintName) return ikConstraintData;
-		return null;
-	}
-	
-	// --- Transform constraints.
-
-	/** @return May be null. */
-	public function findTransformConstraint (constraintName:String) : TransformConstraintData {
-		if (constraintName == null) throw new ArgumentError("constraintName cannot be null.");
-		for each (var transformConstraintData:TransformConstraintData in transformConstraints)
-			if (transformConstraintData._name == constraintName) return transformConstraintData;
-		return null;
-	}
-	
-	/** @return -1 if the transform constraint was not found. */
-	public function findTransformConstraintIndex (transformConstraintName:String) : int {
-		if (transformConstraintName == null) throw new ArgumentError("transformConstraintName cannot be null.");
-		var transformConstraints:Vector.<TransformConstraintData> = this.transformConstraints;
-		for (var i:int = 0, n:int = transformConstraints.length; i < n; i++)
-			if (transformConstraints[i].name == transformConstraintName) return i;
-		return -1;
-	}
-	
-	// --- Path constraints.
-	
-		/** @return May be null. */
-	public function findPathConstraint (constraintName:String) : PathConstraintData {
-		if (constraintName == null) throw new ArgumentError("constraintName cannot be null.");
-		var pathConstraints:Vector.<PathConstraintData> = this.pathConstraints;
-		for (var i:int = 0, n:int = pathConstraints.length; i < n; i++) {
-			var constraint:PathConstraintData = pathConstraints[i];
-			if (constraint.name == constraintName) return constraint;
-		}
-		return null;
-	}
-
-	/** @return -1 if the path constraint was not found. */
-	public function findPathConstraintIndex (pathConstraintName:String) : int {
-		if (pathConstraintName == null) throw new ArgumentError("pathConstraintName cannot be null.");
-		var pathConstraints:Vector.<PathConstraintData> = this.pathConstraints;
-		for (var i:int = 0, n:int = pathConstraints.length; i < n; i++)
-			if (pathConstraints[i].name == pathConstraintName) return i;
-		return -1;
-	}
-
-	// ---
-
-	public function toString () : String {
-		return name != null ? name : super.toString();
-	}
-}
-
+package spine {
+import spine.animation.Animation;
+
+public class SkeletonData {
+	/** May be null. */
+	public var name:String;
+	public var bones:Vector.<BoneData> = new Vector.<BoneData>(); // Ordered parents first.
+	public var slots:Vector.<SlotData> = new Vector.<SlotData>(); // Setup pose draw order.
+	public var skins:Vector.<Skin> = new Vector.<Skin>();
+	public var defaultSkin:Skin;
+	public var events:Vector.<EventData> = new Vector.<EventData>();
+	public var animations:Vector.<Animation> = new Vector.<Animation>();
+	public var ikConstraints:Vector.<IkConstraintData> = new Vector.<IkConstraintData>();
+	public var transformConstraints:Vector.<TransformConstraintData> = new Vector.<TransformConstraintData>();
+	public var pathConstraints:Vector.<PathConstraintData> = new Vector.<PathConstraintData>();
+	public var width:Number, height:Number;
+	public var version:String, hash:String;
+	
+	public function SkeletonData () {		
+	}
+
+	// --- Bones.
+
+	/** @return May be null. */
+	public function findBone (boneName:String) : BoneData {
+		if (boneName == null) throw new ArgumentError("boneName cannot be null.");
+		for (var i:int = 0, n:int = bones.length; i < n; i++) {
+			var bone:BoneData = bones[i];
+			if (bone._name == boneName) return bone;
+		}
+		return null;
+	}
+
+	/** @return -1 if the bone was not found. */
+	public function findBoneIndex (boneName:String) : int {
+		if (boneName == null) throw new ArgumentError("boneName cannot be null.");
+		for (var i:int = 0, n:int = bones.length; i < n; i++)
+			if (bones[i]._name == boneName) return i;
+		return -1;
+	}
+
+	// --- Slots.
+
+	/** @return May be null. */
+	public function findSlot (slotName:String) : SlotData {
+		if (slotName == null) throw new ArgumentError("slotName cannot be null.");
+		for (var i:int = 0, n:int = slots.length; i < n; i++) {
+			var slot:SlotData = slots[i];
+			if (slot._name == slotName) return slot;
+		}
+		return null;
+	}
+
+	/** @return -1 if the bone was not found. */
+	public function findSlotIndex (slotName:String) : int {
+		if (slotName == null) throw new ArgumentError("slotName cannot be null.");
+		for (var i:int = 0, n:int = slots.length; i < n; i++)
+			if (slots[i]._name == slotName) return i;
+		return -1;
+	}
+
+	// --- Skins.
+
+	/** @return May be null. */
+	public function findSkin (skinName:String) : Skin {
+		if (skinName == null) throw new ArgumentError("skinName cannot be null.");
+		for each (var skin:Skin in skins)
+			if (skin._name == skinName) return skin;
+		return null;
+	}
+	
+	// --- Events.
+	
+	/** @return May be null. */
+	public function findEvent (eventName:String) : EventData {
+		if (eventName == null) throw new ArgumentError("eventName cannot be null.");
+		for each (var eventData:EventData in events)
+			if (eventData._name == eventName) return eventData;
+		return null;
+	}
+	
+	// --- Animations.
+	
+	/** @return May be null. */
+	public function findAnimation (animationName:String) : Animation {
+		if (animationName == null) throw new ArgumentError("animationName cannot be null.");
+		for each (var animation:Animation in animations)
+			if (animation.name == animationName) return animation;
+		return null;
+	}
+	
+	// --- IK constraints.
+
+	/** @return May be null. */
+	public function findIkConstraint (constraintName:String) : IkConstraintData {
+		if (constraintName == null) throw new ArgumentError("constraintName cannot be null.");
+		for each (var ikConstraintData:IkConstraintData in ikConstraints)
+			if (ikConstraintData._name == constraintName) return ikConstraintData;
+		return null;
+	}
+	
+	// --- Transform constraints.
+
+	/** @return May be null. */
+	public function findTransformConstraint (constraintName:String) : TransformConstraintData {
+		if (constraintName == null) throw new ArgumentError("constraintName cannot be null.");
+		for each (var transformConstraintData:TransformConstraintData in transformConstraints)
+			if (transformConstraintData._name == constraintName) return transformConstraintData;
+		return null;
+	}
+	
+	/** @return -1 if the transform constraint was not found. */
+	public function findTransformConstraintIndex (transformConstraintName:String) : int {
+		if (transformConstraintName == null) throw new ArgumentError("transformConstraintName cannot be null.");
+		var transformConstraints:Vector.<TransformConstraintData> = this.transformConstraints;
+		for (var i:int = 0, n:int = transformConstraints.length; i < n; i++)
+			if (transformConstraints[i].name == transformConstraintName) return i;
+		return -1;
+	}
+	
+	// --- Path constraints.
+	
+		/** @return May be null. */
+	public function findPathConstraint (constraintName:String) : PathConstraintData {
+		if (constraintName == null) throw new ArgumentError("constraintName cannot be null.");
+		var pathConstraints:Vector.<PathConstraintData> = this.pathConstraints;
+		for (var i:int = 0, n:int = pathConstraints.length; i < n; i++) {
+			var constraint:PathConstraintData = pathConstraints[i];
+			if (constraint.name == constraintName) return constraint;
+		}
+		return null;
+	}
+
+	/** @return -1 if the path constraint was not found. */
+	public function findPathConstraintIndex (pathConstraintName:String) : int {
+		if (pathConstraintName == null) throw new ArgumentError("pathConstraintName cannot be null.");
+		var pathConstraints:Vector.<PathConstraintData> = this.pathConstraints;
+		for (var i:int = 0, n:int = pathConstraints.length; i < n; i++)
+			if (pathConstraints[i].name == pathConstraintName) return i;
+		return -1;
+	}
+
+	// ---
+
+	public function toString () : String {
+		return name != null ? name : super.toString();
+	}
+}
+
 }

+ 734 - 734
spine-as3/spine-as3/src/spine/SkeletonJson.as

@@ -1,737 +1,737 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
-package spine {
-import spine.animation.PathConstraintMixTimeline;
-import spine.animation.PathConstraintSpacingTimeline;
-import spine.animation.PathConstraintPositionTimeline;
-import spine.animation.TransformConstraintTimeline;
-import spine.animation.ShearTimeline;
-import spine.attachments.PathAttachment;
-import spine.attachments.VertexAttachment;
-import flash.utils.ByteArray;
 
-import spine.animation.Animation;
-import spine.animation.AttachmentTimeline;
-import spine.animation.ColorTimeline;
-import spine.animation.CurveTimeline;
-import spine.animation.DrawOrderTimeline;
-import spine.animation.EventTimeline;
-import spine.animation.DeformTimeline;
-import spine.animation.IkConstraintTimeline;
-import spine.animation.RotateTimeline;
-import spine.animation.ScaleTimeline;
-import spine.animation.Timeline;
-import spine.animation.TranslateTimeline;
-import spine.attachments.Attachment;
-import spine.attachments.AttachmentLoader;
-import spine.attachments.AttachmentType;
-import spine.attachments.BoundingBoxAttachment;
-import spine.attachments.MeshAttachment;
-import spine.attachments.RegionAttachment;
-
-public class SkeletonJson {
-	public var attachmentLoader:AttachmentLoader;
-	public var scale:Number = 1;
-	private var linkedMeshes:Vector.<LinkedMesh> = new Vector.<LinkedMesh>();
-
-	public function SkeletonJson (attachmentLoader:AttachmentLoader = null) {
-		this.attachmentLoader = attachmentLoader;
-	}
-
-	/** @param object A String or ByteArray. */
-	public function readSkeletonData (object:*, name:String = null) : SkeletonData {
-		if (object == null) throw new ArgumentError("object cannot be null.");
-
-		var root:Object;
-		if (object is String)
-			root = JSON.parse(String(object));
-		else if (object is ByteArray)
-			root = JSON.parse(ByteArray(object).readUTFBytes(ByteArray(object).length));
-		else if (object is Object)
-			root = object;
-		else
-			throw new ArgumentError("object must be a String, ByteArray or Object.");
-
-		var skeletonData:SkeletonData = new SkeletonData();
-		skeletonData.name = name;
-
-		// Skeleton.
-		var skeletonMap:Object = root["skeleton"];
-		if (skeletonMap) {
-			skeletonData.hash = skeletonMap["hash"];
-			skeletonData.version = skeletonMap["spine"];
-			skeletonData.width = skeletonMap["width"] || 0;
-			skeletonData.height = skeletonMap["height"] || 0;			
-		}			
-
-		// Bones.
-		var boneData:BoneData;
-		for each (var boneMap:Object in root["bones"]) {
-			var parent:BoneData = null;
-			var parentName:String = boneMap["parent"];
-			if (parentName) {
-				parent = skeletonData.findBone(parentName);
-				if (!parent) throw new Error("Parent bone not found: " + parentName);
-			}
-			boneData = new BoneData(skeletonData.bones.length, boneMap["name"], parent);
-			boneData.length = Number(boneMap["length"] || 0) * scale;
-			boneData.x = Number(boneMap["x"] || 0) * scale;
-			boneData.y = Number(boneMap["y"] || 0) * scale;
-			boneData.rotation = (boneMap["rotation"] || 0);
-			boneData.scaleX = boneMap.hasOwnProperty("scaleX") ? boneMap["scaleX"] : 1;
-			boneData.scaleY = boneMap.hasOwnProperty("scaleY") ? boneMap["scaleY"] : 1;
-			boneData.shearX = Number(boneMap["shearX"] || 0);
-			boneData.shearY = Number(boneMap["shearY"] || 0);
-			boneData.inheritRotation = boneMap.hasOwnProperty("inheritRotation") ? Boolean(boneMap["inheritRotation"]) : true;
-			boneData.inheritScale = boneMap.hasOwnProperty("inheritScale") ? Boolean(boneMap["inheritScale"]) : true;			
-			skeletonData.bones.push(boneData);
-		}
-		
-		// Slots.
-		for each (var slotMap:Object in root["slots"]) {
-			var slotName:String = slotMap["name"];
-			var boneName:String = slotMap["bone"];
-			boneData = skeletonData.findBone(boneName);
-			if (!boneData) throw new Error("Slot bone not found: " + boneName);
-			var slotData:SlotData = new SlotData(skeletonData.slots.length, slotName, boneData);
-
-			var color:String = slotMap["color"];
-			if (color) {
-				slotData.r = toColor(color, 0);
-				slotData.g = toColor(color, 1);
-				slotData.b = toColor(color, 2);
-				slotData.a = toColor(color, 3);
-			}
-
-			slotData.attachmentName = slotMap["attachment"];
-			slotData.blendMode = BlendMode[slotMap["blend"] || "normal"];
-			skeletonData.slots.push(slotData);
-		}
-
-		// IK constraints.
-		for each (var constraintMap:Object in root["ik"]) {
-			var ikConstraintData:IkConstraintData = new IkConstraintData(constraintMap["name"]);
-
-			for each (boneName in constraintMap["bones"]) {
-				var bone:BoneData = skeletonData.findBone(boneName);
-				if (!bone) throw new Error("IK constraint bone not found: " + boneName);
-				ikConstraintData.bones.push(bone);
-			}
-
-			ikConstraintData.target = skeletonData.findBone(constraintMap["target"]);
-			if (!ikConstraintData.target) throw new Error("Target bone not found: " + constraintMap["target"]);
-
-			ikConstraintData.bendDirection = (!constraintMap.hasOwnProperty("bendPositive") || constraintMap["bendPositive"]) ? 1 : -1;
-			ikConstraintData.mix = constraintMap.hasOwnProperty("mix") ? constraintMap["mix"] : 1;
-
-			skeletonData.ikConstraints.push(ikConstraintData);
-		}
-
-		// Transform constraints.
-		for each (constraintMap in root["transform"]) {
-			var transformConstraintData:TransformConstraintData = new TransformConstraintData(constraintMap["name"]);
-
-			for each (boneName in constraintMap["bones"]) {
-				bone = skeletonData.findBone(boneName);
-				if (!bone) throw new Error("Transform constraint bone not found: " + boneName);
-				transformConstraintData.bones.push(bone);
-			}
-		
-			transformConstraintData.target = skeletonData.findBone(constraintMap["target"]);
-			if (!transformConstraintData.target) throw new Error("Target bone not found: " + constraintMap["target"]);
-			
-			transformConstraintData.offsetRotation = Number(constraintMap["rotation"] || 0);
-			transformConstraintData.offsetX = Number(constraintMap["x"] || 0) * scale;
-			transformConstraintData.offsetY = Number(constraintMap["y"] || 0) * scale;
-			transformConstraintData.offsetScaleX = Number(constraintMap["scaleX"] || 0);
-			transformConstraintData.offsetScaleY = Number(constraintMap["scaleY"] || 0);
-			transformConstraintData.offsetShearY = Number(constraintMap["shearY"] || 0);
-			
-			transformConstraintData.rotateMix = constraintMap.hasOwnProperty("rotateMix") ? constraintMap["rotateMix"] : 1;
-			transformConstraintData.translateMix = constraintMap.hasOwnProperty("translateMix") ? constraintMap["translateMix"] : 1;
-			transformConstraintData.scaleMix = constraintMap.hasOwnProperty("scaleMix") ? constraintMap["scaleMix"] : 1;
-			transformConstraintData.shearMix = constraintMap.hasOwnProperty("shearMix") ? constraintMap["shearMix"] : 1;
-
-			skeletonData.transformConstraints.push(transformConstraintData);
-		}
-		
-		// Path constraints.
-		for each (constraintMap in root["path"]) {
-			var pathConstraintData:PathConstraintData = new PathConstraintData(constraintMap["name"]);
-
-			for each (boneName in constraintMap["bones"]) {
-				bone = skeletonData.findBone(boneName);
-				if (!bone) throw new Error("Path constraint bone not found: " + boneName);
-				pathConstraintData.bones.push(bone);
-			}
-		
-			pathConstraintData.target = skeletonData.findSlot(constraintMap["target"]);
-			if (!pathConstraintData.target) throw new Error("Path target slot not found: " + constraintMap["target"]);
-
-			pathConstraintData.positionMode = PositionMode[constraintMap["positionMode"] || "percent"];
-			pathConstraintData.spacingMode = SpacingMode[constraintMap["spacingMode"] || "length"];
-			pathConstraintData.rotateMode = RotateMode[constraintMap["rotateMode"] || "rotateMode"];
-			pathConstraintData.offsetRotation = Number(constraintMap["rotation"] || 0);
-			pathConstraintData.position = Number(constraintMap["position"] || 0);
-			if (pathConstraintData.positionMode == PositionMode.fixed) pathConstraintData.position *= scale;
-			pathConstraintData.spacing = Number(constraintMap["spacing"] || 0);
-			if (pathConstraintData.spacingMode == SpacingMode.length || pathConstraintData.spacingMode == SpacingMode.fixed) pathConstraintData.spacing *= scale;
-			pathConstraintData.rotateMix = constraintMap.hasOwnProperty("rotateMix") ? constraintMap["rotateMix"] : 1;
-			pathConstraintData.translateMix = constraintMap.hasOwnProperty("translateMix") ? constraintMap["translateMix"] : 1;
-
-			skeletonData.pathConstraints.push(pathConstraintData);
-		}
-
-		// Skins.
-		var skins:Object = root["skins"];
-		for (var skinName:String in skins) {
-			var skinMap:Object = skins[skinName];
-			var skin:Skin = new Skin(skinName);
-			for (slotName in skinMap) {
-				var slotIndex:int = skeletonData.findSlotIndex(slotName);
-				var slotEntry:Object = skinMap[slotName];
-				for (var attachmentName:String in slotEntry) {
-					var attachment:Attachment = readAttachment(slotEntry[attachmentName], skin, slotIndex, attachmentName);
-					if (attachment != null)
-						skin.addAttachment(slotIndex, attachmentName, attachment);
-				}
-			}
-			skeletonData.skins[skeletonData.skins.length] = skin;
-			if (skin.name == "default")
-				skeletonData.defaultSkin = skin;
-		}
-
-		// Linked meshes.
-		var linkedMeshes:Vector.<LinkedMesh> = this.linkedMeshes;
-		for each (var linkedMesh:LinkedMesh in linkedMeshes) {
-			var parentSkin:Skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);
-			if (!parentSkin) throw new Error("Skin not found: " + linkedMesh.skin);
-			var parentMesh:Attachment = parentSkin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
-			if (!parentMesh) throw new Error("Parent mesh not found: " + linkedMesh.parent);
-			linkedMesh.mesh.parentMesh = MeshAttachment(parentMesh);
-			linkedMesh.mesh.updateUVs();
-		}
-		linkedMeshes.length = 0;
-
-		// Events.
-		var events:Object = root["events"];
-		if (events) {
-			for (var eventName:String in events) {
-				var eventMap:Object = events[eventName];
-				var eventData:EventData = new EventData(eventName);
-				eventData.intValue = eventMap["int"] || 0;
-				eventData.floatValue = eventMap["float"] || 0;
-				eventData.stringValue = eventMap["string"] || null;
-				skeletonData.events.push(eventData);
-			}
-		}
-
-		// Animations.
-		var animations:Object = root["animations"];
-		for (var animationName:String in animations)
-			readAnimation(animations[animationName], animationName, skeletonData);
-
-		return skeletonData;
-	}
-
-	private function readAttachment (map:Object, skin:Skin, slotIndex:int, name:String) : Attachment {
-		name = map["name"] || name;
-
-		var typeName:String = map["type"] || "region";		
-		var type:AttachmentType = AttachmentType[typeName];		
-
-		var scale:Number = this.scale;
-		var color:String;
-		switch (type) {
-			case AttachmentType.region:
-				var region:RegionAttachment = attachmentLoader.newRegionAttachment(skin, name, map["path"] || name);
-				if (!region) return null;
-				region.path = map["path"] || name;
-				region.x = Number(map["x"] || 0) * scale;
-				region.y = Number(map["y"] || 0) * scale;
-				region.scaleX = map.hasOwnProperty("scaleX") ? map["scaleX"] : 1;
-				region.scaleY = map.hasOwnProperty("scaleY") ? map["scaleY"] : 1;
-				region.rotation = map["rotation"] || 0;
-				region.width = Number(map["width"] || 0) * scale;
-				region.height = Number(map["height"] || 0) * scale;
-				color = map["color"];
-				if (color) {
-					region.r = toColor(color, 0);
-					region.g = toColor(color, 1);
-					region.b = toColor(color, 2);
-					region.a = toColor(color, 3);
-				}
-				region.updateOffset();
-				return region;
-			case AttachmentType.mesh:
-			case AttachmentType.linkedmesh:
-				var mesh:MeshAttachment = attachmentLoader.newMeshAttachment(skin, name, map["path"] || name);
-				if (!mesh) return null;
-				mesh.path = map["path"] || name;
-
-				color = map["color"];
-				if (color) {
-					mesh.r = toColor(color, 0);
-					mesh.g = toColor(color, 1);
-					mesh.b = toColor(color, 2);
-					mesh.a = toColor(color, 3);
-				}
-
-				mesh.width = Number(map["width"] || 0) * scale;
-				mesh.height = Number(map["height"] || 0) * scale;
-
-				if (map["parent"]) {
-					mesh.inheritDeform = map.hasOwnProperty("deform") ? Boolean(map["deform"]) : true;
-					linkedMeshes.push(new LinkedMesh(mesh, map["skin"], slotIndex, map["parent"]));
-					return mesh;
-				}
-				
-				var uvs:Vector.<Number> = getFloatArray(map, "uvs", 1);
-				readVertices(map, mesh, uvs.length);			
-				mesh.triangles = getUintArray(map, "triangles");	
-				mesh.regionUVs = uvs;									
-				mesh.updateUVs();
-
-				mesh.hullLength = int(map["hull"] || 0) * 2;
-				if (map["edges"]) mesh.edges = getIntArray(map, "edges");
-				return mesh;			
-			case AttachmentType.boundingbox:
-				var box:BoundingBoxAttachment = attachmentLoader.newBoundingBoxAttachment(skin, name);
-				if (!box) return null;
-				readVertices(map, box, int(map["vertexCount"]) << 1);								
-				return box;
-			case AttachmentType.path:
-				var path:PathAttachment = attachmentLoader.newPathAttachment(skin, name);
-				if (!path) return null;
-				path.closed = map.hasOwnProperty("closed") ? Boolean(map["closed"]) : false;
-				path.constantSpeed = map.hasOwnProperty("constantSpeed") ? Boolean(map["constantSpeed"]) : true;
-				
-				var vertexCount:int = int(map["vertexCount"]);
-				readVertices(map, path, vertexCount << 1);
-				
-				var lengths:Vector.<Number> = new Vector.<Number>();							
-				for each (var curves:Object in map["lengths"]) {
-					lengths.push(Number(curves) * scale);
-				}
-				path.lengths = lengths;				
-				return path;
-		}
-
-		return null;
-	}
-	
-	private function readVertices(map:Object, attachment:VertexAttachment, verticesLength:int) : void {
-		attachment.worldVerticesLength = verticesLength;
-		var vertices:Vector.<Number> = getFloatArray(map, "vertices", 1);
-		if (verticesLength == vertices.length) {
-			if (scale != 1) {
-				for (var i:int = 0, n:int = vertices.length; i < n; i++) {
-					vertices[i] *= scale;
-				}
-			}
-			attachment.vertices = vertices;
-			return;
-		}
-		
-		var weights:Vector.<Number> = new Vector.<Number>(verticesLength * 3 * 3);
-		weights.length = 0;
-		var bones:Vector.<int> = new Vector.<int>(verticesLength * 3);
-		bones.length = 0;
-		for (i = 0, n = vertices.length; i < n;) {
-			 var boneCount:int = int(vertices[i++]);
-			 bones.push(boneCount);
-			 for (var nn:int = i + boneCount * 4; i < nn; i+=4) {
-				bones.push(int(vertices[i]));
-				weights.push(vertices[i + 1] * scale);
-				weights.push(vertices[i + 2] * scale);
-				weights.push(vertices[i + 3]);
-			 }
-		}
-		attachment.bones = bones;
-		attachment.vertices = weights;
-	}
-
-	private function readAnimation (map:Object, name:String, skeletonData:SkeletonData) : void {
-		var scale:Number = this.scale;
-		var timelines:Vector.<Timeline> = new Vector.<Timeline>();
-		var duration:Number = 0;
-
-		var slotMap:Object, slotIndex:int, slotName:String;
-		var values:Array, valueMap:Object, frameIndex:int;
-		var i:int;
-		var timelineName:String;
-
-		var slots:Object = map["slots"];
-		for (slotName in slots) {
-			slotMap = slots[slotName];
-			slotIndex = skeletonData.findSlotIndex(slotName);
-
-			for (timelineName in slotMap) {
-				values = slotMap[timelineName];
-				if (timelineName == "color") {
-					var colorTimeline:ColorTimeline = new ColorTimeline(values.length);
-					colorTimeline.slotIndex = slotIndex;
-
-					frameIndex = 0;
-					for each (valueMap in values) {
-						var color:String = valueMap["color"];
-						var r:Number = toColor(color, 0);
-						var g:Number = toColor(color, 1);
-						var b:Number = toColor(color, 2);
-						var a:Number = toColor(color, 3);
-						colorTimeline.setFrame(frameIndex, valueMap["time"], r, g, b, a);
-						readCurve(valueMap, colorTimeline, frameIndex);
-						frameIndex++;
-					}
-					timelines[timelines.length] = colorTimeline;
-					duration = Math.max(duration, colorTimeline.frames[(colorTimeline.frameCount - 1) * ColorTimeline.ENTRIES]);
-				} else if (timelineName == "attachment") {
-					var attachmentTimeline:AttachmentTimeline = new AttachmentTimeline(values.length);
-					attachmentTimeline.slotIndex = slotIndex;
-
-					frameIndex = 0;
-					for each (valueMap in values)
-						attachmentTimeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]);
-					timelines[timelines.length] = attachmentTimeline;
-					duration = Math.max(duration, attachmentTimeline.frames[attachmentTimeline.frameCount - 1]);
-				} else
-					throw new Error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")");
-			}
-		}
-
-		var bones:Object = map["bones"];
-		for (var boneName:String in bones) {
-			var boneIndex:int = skeletonData.findBoneIndex(boneName);
-			if (boneIndex == -1) throw new Error("Bone not found: " + boneName);
-			var boneMap:Object = bones[boneName];
-
-			for (timelineName in boneMap) {
-				values = boneMap[timelineName];
-				if (timelineName == "rotate") {
-					var rotateTimeline:RotateTimeline = new RotateTimeline(values.length);
-					rotateTimeline.boneIndex = boneIndex;
-
-					frameIndex = 0;
-					for each (valueMap in values) {
-						rotateTimeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]);
-						readCurve(valueMap, rotateTimeline, frameIndex);
-						frameIndex++;
-					}
-					timelines[timelines.length] = rotateTimeline;
-					duration = Math.max(duration, rotateTimeline.frames[(rotateTimeline.frameCount - 1) * RotateTimeline.ENTRIES]);
-				} else if (timelineName == "translate" || timelineName == "scale" || timelineName == "shear") {
-					var translateTimeline:TranslateTimeline;
-					var timelineScale:Number = 1;
-					if (timelineName == "scale")
-						translateTimeline = new ScaleTimeline(values.length);
-					else if (timelineName == "shear")
-						translateTimeline = new ShearTimeline(values.length);
-					else {
-						translateTimeline = new TranslateTimeline(values.length);
-						timelineScale = scale;
-					}
-					translateTimeline.boneIndex = boneIndex;
-
-					frameIndex = 0;
-					for each (valueMap in values) {
-						var x:Number = Number(valueMap["x"] || 0) * timelineScale;
-						var y:Number = Number(valueMap["y"] || 0) * timelineScale;
-						translateTimeline.setFrame(frameIndex, valueMap["time"], x, y);
-						readCurve(valueMap, translateTimeline, frameIndex);
-						frameIndex++;
-					}
-					timelines[timelines.length] = translateTimeline;
-					duration = Math.max(duration, translateTimeline.frames[(translateTimeline.frameCount - 1) * TranslateTimeline.ENTRIES]);
-				} else
-					throw new Error("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
-			}
-		}
-
-		var ikMap:Object = map["ik"];
-		for (var ikConstraintName:String in ikMap) {
-			var ikConstraint:IkConstraintData = skeletonData.findIkConstraint(ikConstraintName);
-			values = ikMap[ikConstraintName];
-			var ikTimeline:IkConstraintTimeline = new IkConstraintTimeline(values.length);
-			ikTimeline.ikConstraintIndex = skeletonData.ikConstraints.indexOf(ikConstraint);
-			frameIndex = 0;
-			for each (valueMap in values) {
-				var mix:Number = valueMap.hasOwnProperty("mix") ? valueMap["mix"] : 1;
-				var bendDirection:int = (!valueMap.hasOwnProperty("bendPositive") || valueMap["bendPositive"]) ? 1 : -1;
-				ikTimeline.setFrame(frameIndex, valueMap["time"], mix, bendDirection);
-				readCurve(valueMap, ikTimeline, frameIndex);
-				frameIndex++;
-			}
-			timelines[timelines.length] = ikTimeline;
-			duration = Math.max(duration, ikTimeline.frames[(ikTimeline.frameCount - 1) * IkConstraintTimeline.ENTRIES]);
-		}
-		
-		var transformMap:Object = map["transform"];
-		for (var transformName:String in transformMap) {
-			var transformConstraint:TransformConstraintData = skeletonData.findTransformConstraint(transformName);
-			values = transformMap[transformName];
-			var transformTimeline:TransformConstraintTimeline = new TransformConstraintTimeline(values.length);
-			transformTimeline.transformConstraintIndex = skeletonData.transformConstraints.indexOf(transformConstraint);
-			frameIndex = 0;
-			for each (valueMap in values) {
-				var rotateMix:Number = valueMap.hasOwnProperty("rotateMix") ? valueMap["rotateMix"] : 1;
-				var translateMix:Number = valueMap.hasOwnProperty("translateMix") ? valueMap["translateMix"] : 1;
-				var scaleMix:Number = valueMap.hasOwnProperty("scaleMix") ? valueMap["scaleMix"] : 1;
-				var shearMix:Number = valueMap.hasOwnProperty("shearMix") ? valueMap["shearMix"] : 1;
-				transformTimeline.setFrame(frameIndex, valueMap["time"], rotateMix, translateMix, scaleMix, shearMix);
-				readCurve(valueMap, transformTimeline, frameIndex);
-				frameIndex++;
-			}
-			timelines.push(transformTimeline);
-			duration = Math.max(duration, transformTimeline.frames[(transformTimeline.frameCount - 1) * TransformConstraintTimeline.ENTRIES]);
-		}
-				
-		// Path constraint timelines.
-		var paths:Object = map["paths"];
-		for (var pathName:String in paths) {
-			var index:int = skeletonData.findPathConstraintIndex(pathName);
-			if (index == -1) throw new Error("Path constraint not found: " + pathName);
-			var data:PathConstraintData = skeletonData.pathConstraints[index];
-			
-			var pathMap:Object = paths[pathName];
-			for (timelineName in pathMap) {
-				values = pathMap[timelineName];
-				
-				if (timelineName == "position" || timelineName == "spacing") {
-					var pathTimeline:PathConstraintPositionTimeline;
-					timelineScale = 1;
-					if (timelineName == "spacing") {
-						pathTimeline = new PathConstraintSpacingTimeline(values.length);
-						if (data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed) timelineScale = scale;
-					} else {
-						pathTimeline = new PathConstraintPositionTimeline(values.length);
-						if (data.positionMode == PositionMode.fixed) timelineScale = scale;
-					}
-					pathTimeline.pathConstraintIndex = index;
-					frameIndex = 0;
-					for each (valueMap in values) {
-						var value:Number = valueMap[timelineName] || 0;
-						pathTimeline.setFrame(frameIndex, valueMap["time"], value * timelineScale);
-						readCurve(valueMap, pathTimeline, frameIndex);
-						frameIndex++;
-					}
-					timelines.push(pathTimeline);
-					duration = Math.max(duration,
-						pathTimeline.frames[(pathTimeline.frameCount - 1) * PathConstraintPositionTimeline.ENTRIES]);
-				} else if (timelineName == "mix") {
-					var pathMixTimeline:PathConstraintMixTimeline = new PathConstraintMixTimeline(values.length);
-					pathMixTimeline.pathConstraintIndex = index;
-					frameIndex = 0;
-					for each (valueMap in values) {
-						rotateMix = valueMap.hasOwnProperty("rotateMix") ? valueMap["rotateMix"] : 1;
-						translateMix = valueMap.hasOwnProperty("translateMix") ? valueMap["translateMix"] : 1;
-						pathMixTimeline.setFrame(frameIndex, valueMap["time"], rotateMix, translateMix);
-						readCurve(valueMap, pathMixTimeline, frameIndex);
-						frameIndex++;
-					}
-					timelines.push(pathMixTimeline);
-					duration = Math.max(duration,
-						pathMixTimeline.frames[(pathMixTimeline.frameCount - 1) * PathConstraintMixTimeline.ENTRIES]);
-				}
-			}
-		}
-		
-		var deformMap:Object = map["deform"];
-		for (var skinName:String in deformMap) {
-			var skin:Skin = skeletonData.findSkin(skinName);
-			slotMap = deformMap[skinName];
-			for (slotName in slotMap) {
-				slotIndex = skeletonData.findSlotIndex(slotName);
-				var timelineMap:Object = slotMap[slotName];
-				for (timelineName in timelineMap) {
-					values = timelineMap[timelineName];
-
-					var attachment:VertexAttachment = skin.getAttachment(slotIndex, timelineName) as VertexAttachment;
-					if (attachment == null) throw new Error("Deform attachment not found: " + timelineName);
-					var weighted:Boolean = attachment.bones != null;
-					var vertices:Vector.<Number> = attachment.vertices;
-					var deformLength:int = weighted ? vertices.length / 3 * 2 : vertices.length;
-
-					var deformTimeline:DeformTimeline = new DeformTimeline(values.length);
-					deformTimeline.slotIndex = slotIndex;
-					deformTimeline.attachment = attachment;
-
-					frameIndex = 0;
-					for each (valueMap in values) {
-						var deform:Vector.<Number>;
-						var verticesValue:Object = valueMap["vertices"];
-						if (verticesValue == null)
-							deform = weighted ? new Vector.<Number>(deformLength, true) : vertices;
-						else {
-							deform = new Vector.<Number>(deformLength, true);
-							var start:int = Number(valueMap["offset"] || 0);
-							var temp:Vector.<Number> = getFloatArray(valueMap, "vertices", 1);
-							for (i = 0; i < temp.length; i++) {
-								deform[start + i] = temp[i];
-							}							
-							if (scale != 1) {
-								var n:int;
-								for (i = start, n = i + temp.length; i < n; i++)
-									deform[i] *= scale;
-							}
-							if (!weighted) {
-								for (i = 0; i < deformLength; i++)
-									deform[i] += vertices[i];
-							}
-						}
-
-						deformTimeline.setFrame(frameIndex, valueMap["time"], deform);
-						readCurve(valueMap, deformTimeline, frameIndex);
-						frameIndex++;
-					}
-					timelines[timelines.length] = deformTimeline;
-					duration = Math.max(duration, deformTimeline.frames[deformTimeline.frameCount - 1]);
-				}
-			}
-		}
-
-		var drawOrderValues:Array = map["drawOrder"];
-		if (!drawOrderValues) drawOrderValues = map["draworder"];
-		if (drawOrderValues) {
-			var drawOrderTimeline:DrawOrderTimeline = new DrawOrderTimeline(drawOrderValues.length);
-			var slotCount:int = skeletonData.slots.length;
-			frameIndex = 0;
-			for each (var drawOrderMap:Object in drawOrderValues) {
-				var drawOrder:Vector.<int> = null;
-				if (drawOrderMap["offsets"]) {
-					drawOrder = new Vector.<int>(slotCount);
-					for (i = slotCount - 1; i >= 0; i--)
-						drawOrder[i] = -1;
-					var offsets:Array = drawOrderMap["offsets"];
-					var unchanged:Vector.<int> = new Vector.<int>(slotCount - offsets.length);
-					var originalIndex:int = 0, unchangedIndex:int = 0;
-					for each (var offsetMap:Object in offsets) {
-						slotIndex = skeletonData.findSlotIndex(offsetMap["slot"]);
-						if (slotIndex == -1) throw new Error("Slot not found: " + offsetMap["slot"]);
-						// Collect unchanged items.
-						while (originalIndex != slotIndex)
-							unchanged[unchangedIndex++] = originalIndex++;
-						// Set changed items.
-						drawOrder[originalIndex + offsetMap["offset"]] = originalIndex++;
-					}
-					// Collect remaining unchanged items.
-					while (originalIndex < slotCount)
-						unchanged[unchangedIndex++] = originalIndex++;
-					// Fill in unchanged items.
-					for (i = slotCount - 1; i >= 0; i--)
-						if (drawOrder[i] == -1) drawOrder[i] = unchanged[--unchangedIndex];
-				}
-				drawOrderTimeline.setFrame(frameIndex++, drawOrderMap["time"], drawOrder);
-			}
-			timelines[timelines.length] = drawOrderTimeline;
-			duration = Math.max(duration, drawOrderTimeline.frames[drawOrderTimeline.frameCount - 1]);
-		}
-
-		var eventsMap:Array = map["events"];
-		if (eventsMap) {
-			var eventTimeline:EventTimeline = new EventTimeline(eventsMap.length);
-			frameIndex = 0;
-			for each (var eventMap:Object in eventsMap) {
-				var eventData:EventData = skeletonData.findEvent(eventMap["name"]);
-				if (!eventData) throw new Error("Event not found: " + eventMap["name"]);
-				var event:Event = new Event(eventMap["time"], eventData);
-				event.intValue = eventMap.hasOwnProperty("int") ? eventMap["int"] : eventData.intValue;
-				event.floatValue = eventMap.hasOwnProperty("float") ? eventMap["float"] : eventData.floatValue;
-				event.stringValue = eventMap.hasOwnProperty("string") ? eventMap["string"] : eventData.stringValue;
-				eventTimeline.setFrame(frameIndex++, event);
-			}
-			timelines[timelines.length] = eventTimeline;
-			duration = Math.max(duration, eventTimeline.frames[eventTimeline.frameCount - 1]);
-		}
-
-		skeletonData.animations[skeletonData.animations.length] = new Animation(name, timelines, duration);
-	}
-
-	static private function readCurve (map:Object, timeline:CurveTimeline, frameIndex:int) : void {
-		var curve:Object = map["curve"];
-		if (!curve) return;
-		if (curve == "stepped")
-			timeline.setStepped(frameIndex);
-		else if (curve is Array)
-			timeline.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]);
-	}
-
-	static private function toColor (hexString:String, colorIndex:int) : Number {
-		if (hexString.length != 8) throw new ArgumentError("Color hexidecimal length must be 8, recieved: " + hexString);
-		return parseInt(hexString.substring(colorIndex * 2, colorIndex * 2 + 2), 16) / 255;
-	}
-
-	static private function getFloatArray (map:Object, name:String, scale:Number) : Vector.<Number> {
-		var list:Array = map[name];
-		var values:Vector.<Number> = new Vector.<Number>(list.length, true);
-		var i:int = 0, n:int = list.length;
-		if (scale == 1) {
-			for (; i < n; i++)
-				values[i] = list[i];
-		} else {
-			for (; i < n; i++)
-				values[i] = list[i] * scale;
-		}
-		return values;
-	}
-
-	static private function getIntArray (map:Object, name:String) : Vector.<int> {
-		var list:Array = map[name];
-		var values:Vector.<int> = new Vector.<int>(list.length, true);
-		for (var i:int = 0, n:int = list.length; i < n; i++)
-			values[i] = int(list[i]);
-		return values;
-	}
-
-	static private function getUintArray (map:Object, name:String) : Vector.<uint> {
-		var list:Array = map[name];
-		var values:Vector.<uint> = new Vector.<uint>(list.length, true);
-		for (var i:int = 0, n:int = list.length; i < n; i++)
-			values[i] = int(list[i]);
-		return values;
-	}
-}
-
-}
-
-import spine.attachments.MeshAttachment;
-
-internal class LinkedMesh {
-	internal var parent:String, skin:String;
-	internal var slotIndex:int;
-	internal var mesh:MeshAttachment;
-
-	public function LinkedMesh (mesh:MeshAttachment, skin:String, slotIndex:int, parent:String) {
-		this.mesh = mesh;
-		this.skin = skin;
-		this.slotIndex = slotIndex;
-		this.parent = parent;
-	}
+package spine {
+import spine.animation.PathConstraintMixTimeline;
+import spine.animation.PathConstraintSpacingTimeline;
+import spine.animation.PathConstraintPositionTimeline;
+import spine.animation.TransformConstraintTimeline;
+import spine.animation.ShearTimeline;
+import spine.attachments.PathAttachment;
+import spine.attachments.VertexAttachment;
+import flash.utils.ByteArray;
+
+import spine.animation.Animation;
+import spine.animation.AttachmentTimeline;
+import spine.animation.ColorTimeline;
+import spine.animation.CurveTimeline;
+import spine.animation.DrawOrderTimeline;
+import spine.animation.EventTimeline;
+import spine.animation.DeformTimeline;
+import spine.animation.IkConstraintTimeline;
+import spine.animation.RotateTimeline;
+import spine.animation.ScaleTimeline;
+import spine.animation.Timeline;
+import spine.animation.TranslateTimeline;
+import spine.attachments.Attachment;
+import spine.attachments.AttachmentLoader;
+import spine.attachments.AttachmentType;
+import spine.attachments.BoundingBoxAttachment;
+import spine.attachments.MeshAttachment;
+import spine.attachments.RegionAttachment;
+
+public class SkeletonJson {
+	public var attachmentLoader:AttachmentLoader;
+	public var scale:Number = 1;
+	private var linkedMeshes:Vector.<LinkedMesh> = new Vector.<LinkedMesh>();
+
+	public function SkeletonJson (attachmentLoader:AttachmentLoader = null) {
+		this.attachmentLoader = attachmentLoader;
+	}
+
+	/** @param object A String or ByteArray. */
+	public function readSkeletonData (object:*, name:String = null) : SkeletonData {
+		if (object == null) throw new ArgumentError("object cannot be null.");
+
+		var root:Object;
+		if (object is String)
+			root = JSON.parse(String(object));
+		else if (object is ByteArray)
+			root = JSON.parse(ByteArray(object).readUTFBytes(ByteArray(object).length));
+		else if (object is Object)
+			root = object;
+		else
+			throw new ArgumentError("object must be a String, ByteArray or Object.");
+
+		var skeletonData:SkeletonData = new SkeletonData();
+		skeletonData.name = name;
+
+		// Skeleton.
+		var skeletonMap:Object = root["skeleton"];
+		if (skeletonMap) {
+			skeletonData.hash = skeletonMap["hash"];
+			skeletonData.version = skeletonMap["spine"];
+			skeletonData.width = skeletonMap["width"] || 0;
+			skeletonData.height = skeletonMap["height"] || 0;			
+		}			
+
+		// Bones.
+		var boneData:BoneData;
+		for each (var boneMap:Object in root["bones"]) {
+			var parent:BoneData = null;
+			var parentName:String = boneMap["parent"];
+			if (parentName) {
+				parent = skeletonData.findBone(parentName);
+				if (!parent) throw new Error("Parent bone not found: " + parentName);
+			}
+			boneData = new BoneData(skeletonData.bones.length, boneMap["name"], parent);
+			boneData.length = Number(boneMap["length"] || 0) * scale;
+			boneData.x = Number(boneMap["x"] || 0) * scale;
+			boneData.y = Number(boneMap["y"] || 0) * scale;
+			boneData.rotation = (boneMap["rotation"] || 0);
+			boneData.scaleX = boneMap.hasOwnProperty("scaleX") ? boneMap["scaleX"] : 1;
+			boneData.scaleY = boneMap.hasOwnProperty("scaleY") ? boneMap["scaleY"] : 1;
+			boneData.shearX = Number(boneMap["shearX"] || 0);
+			boneData.shearY = Number(boneMap["shearY"] || 0);
+			boneData.inheritRotation = boneMap.hasOwnProperty("inheritRotation") ? Boolean(boneMap["inheritRotation"]) : true;
+			boneData.inheritScale = boneMap.hasOwnProperty("inheritScale") ? Boolean(boneMap["inheritScale"]) : true;			
+			skeletonData.bones.push(boneData);
+		}
+		
+		// Slots.
+		for each (var slotMap:Object in root["slots"]) {
+			var slotName:String = slotMap["name"];
+			var boneName:String = slotMap["bone"];
+			boneData = skeletonData.findBone(boneName);
+			if (!boneData) throw new Error("Slot bone not found: " + boneName);
+			var slotData:SlotData = new SlotData(skeletonData.slots.length, slotName, boneData);
+
+			var color:String = slotMap["color"];
+			if (color) {
+				slotData.r = toColor(color, 0);
+				slotData.g = toColor(color, 1);
+				slotData.b = toColor(color, 2);
+				slotData.a = toColor(color, 3);
+			}
+
+			slotData.attachmentName = slotMap["attachment"];
+			slotData.blendMode = BlendMode[slotMap["blend"] || "normal"];
+			skeletonData.slots.push(slotData);
+		}
+
+		// IK constraints.
+		for each (var constraintMap:Object in root["ik"]) {
+			var ikConstraintData:IkConstraintData = new IkConstraintData(constraintMap["name"]);
+
+			for each (boneName in constraintMap["bones"]) {
+				var bone:BoneData = skeletonData.findBone(boneName);
+				if (!bone) throw new Error("IK constraint bone not found: " + boneName);
+				ikConstraintData.bones.push(bone);
+			}
+
+			ikConstraintData.target = skeletonData.findBone(constraintMap["target"]);
+			if (!ikConstraintData.target) throw new Error("Target bone not found: " + constraintMap["target"]);
+
+			ikConstraintData.bendDirection = (!constraintMap.hasOwnProperty("bendPositive") || constraintMap["bendPositive"]) ? 1 : -1;
+			ikConstraintData.mix = constraintMap.hasOwnProperty("mix") ? constraintMap["mix"] : 1;
+
+			skeletonData.ikConstraints.push(ikConstraintData);
+		}
+
+		// Transform constraints.
+		for each (constraintMap in root["transform"]) {
+			var transformConstraintData:TransformConstraintData = new TransformConstraintData(constraintMap["name"]);
+
+			for each (boneName in constraintMap["bones"]) {
+				bone = skeletonData.findBone(boneName);
+				if (!bone) throw new Error("Transform constraint bone not found: " + boneName);
+				transformConstraintData.bones.push(bone);
+			}
+		
+			transformConstraintData.target = skeletonData.findBone(constraintMap["target"]);
+			if (!transformConstraintData.target) throw new Error("Target bone not found: " + constraintMap["target"]);
+			
+			transformConstraintData.offsetRotation = Number(constraintMap["rotation"] || 0);
+			transformConstraintData.offsetX = Number(constraintMap["x"] || 0) * scale;
+			transformConstraintData.offsetY = Number(constraintMap["y"] || 0) * scale;
+			transformConstraintData.offsetScaleX = Number(constraintMap["scaleX"] || 0);
+			transformConstraintData.offsetScaleY = Number(constraintMap["scaleY"] || 0);
+			transformConstraintData.offsetShearY = Number(constraintMap["shearY"] || 0);
+			
+			transformConstraintData.rotateMix = constraintMap.hasOwnProperty("rotateMix") ? constraintMap["rotateMix"] : 1;
+			transformConstraintData.translateMix = constraintMap.hasOwnProperty("translateMix") ? constraintMap["translateMix"] : 1;
+			transformConstraintData.scaleMix = constraintMap.hasOwnProperty("scaleMix") ? constraintMap["scaleMix"] : 1;
+			transformConstraintData.shearMix = constraintMap.hasOwnProperty("shearMix") ? constraintMap["shearMix"] : 1;
+
+			skeletonData.transformConstraints.push(transformConstraintData);
+		}
+		
+		// Path constraints.
+		for each (constraintMap in root["path"]) {
+			var pathConstraintData:PathConstraintData = new PathConstraintData(constraintMap["name"]);
+
+			for each (boneName in constraintMap["bones"]) {
+				bone = skeletonData.findBone(boneName);
+				if (!bone) throw new Error("Path constraint bone not found: " + boneName);
+				pathConstraintData.bones.push(bone);
+			}
+		
+			pathConstraintData.target = skeletonData.findSlot(constraintMap["target"]);
+			if (!pathConstraintData.target) throw new Error("Path target slot not found: " + constraintMap["target"]);
+
+			pathConstraintData.positionMode = PositionMode[constraintMap["positionMode"] || "percent"];
+			pathConstraintData.spacingMode = SpacingMode[constraintMap["spacingMode"] || "length"];
+			pathConstraintData.rotateMode = RotateMode[constraintMap["rotateMode"] || "tangent"];
+			pathConstraintData.offsetRotation = Number(constraintMap["rotation"] || 0);
+			pathConstraintData.position = Number(constraintMap["position"] || 0);
+			if (pathConstraintData.positionMode == PositionMode.fixed) pathConstraintData.position *= scale;
+			pathConstraintData.spacing = Number(constraintMap["spacing"] || 0);
+			if (pathConstraintData.spacingMode == SpacingMode.length || pathConstraintData.spacingMode == SpacingMode.fixed) pathConstraintData.spacing *= scale;
+			pathConstraintData.rotateMix = constraintMap.hasOwnProperty("rotateMix") ? constraintMap["rotateMix"] : 1;
+			pathConstraintData.translateMix = constraintMap.hasOwnProperty("translateMix") ? constraintMap["translateMix"] : 1;
+
+			skeletonData.pathConstraints.push(pathConstraintData);
+		}
+
+		// Skins.
+		var skins:Object = root["skins"];
+		for (var skinName:String in skins) {
+			var skinMap:Object = skins[skinName];
+			var skin:Skin = new Skin(skinName);
+			for (slotName in skinMap) {
+				var slotIndex:int = skeletonData.findSlotIndex(slotName);
+				var slotEntry:Object = skinMap[slotName];
+				for (var attachmentName:String in slotEntry) {
+					var attachment:Attachment = readAttachment(slotEntry[attachmentName], skin, slotIndex, attachmentName);
+					if (attachment != null)
+						skin.addAttachment(slotIndex, attachmentName, attachment);
+				}
+			}
+			skeletonData.skins[skeletonData.skins.length] = skin;
+			if (skin.name == "default")
+				skeletonData.defaultSkin = skin;
+		}
+
+		// Linked meshes.
+		var linkedMeshes:Vector.<LinkedMesh> = this.linkedMeshes;
+		for each (var linkedMesh:LinkedMesh in linkedMeshes) {
+			var parentSkin:Skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);
+			if (!parentSkin) throw new Error("Skin not found: " + linkedMesh.skin);
+			var parentMesh:Attachment = parentSkin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
+			if (!parentMesh) throw new Error("Parent mesh not found: " + linkedMesh.parent);
+			linkedMesh.mesh.parentMesh = MeshAttachment(parentMesh);
+			linkedMesh.mesh.updateUVs();
+		}
+		linkedMeshes.length = 0;
+
+		// Events.
+		var events:Object = root["events"];
+		if (events) {
+			for (var eventName:String in events) {
+				var eventMap:Object = events[eventName];
+				var eventData:EventData = new EventData(eventName);
+				eventData.intValue = eventMap["int"] || 0;
+				eventData.floatValue = eventMap["float"] || 0;
+				eventData.stringValue = eventMap["string"] || null;
+				skeletonData.events.push(eventData);
+			}
+		}
+
+		// Animations.
+		var animations:Object = root["animations"];
+		for (var animationName:String in animations)
+			readAnimation(animations[animationName], animationName, skeletonData);
+
+		return skeletonData;
+	}
+
+	private function readAttachment (map:Object, skin:Skin, slotIndex:int, name:String) : Attachment {
+		name = map["name"] || name;
+
+		var typeName:String = map["type"] || "region";		
+		var type:AttachmentType = AttachmentType[typeName];		
+
+		var scale:Number = this.scale;
+		var color:String;
+		switch (type) {
+			case AttachmentType.region:
+				var region:RegionAttachment = attachmentLoader.newRegionAttachment(skin, name, map["path"] || name);
+				if (!region) return null;
+				region.path = map["path"] || name;
+				region.x = Number(map["x"] || 0) * scale;
+				region.y = Number(map["y"] || 0) * scale;
+				region.scaleX = map.hasOwnProperty("scaleX") ? map["scaleX"] : 1;
+				region.scaleY = map.hasOwnProperty("scaleY") ? map["scaleY"] : 1;
+				region.rotation = map["rotation"] || 0;
+				region.width = Number(map["width"] || 0) * scale;
+				region.height = Number(map["height"] || 0) * scale;
+				color = map["color"];
+				if (color) {
+					region.r = toColor(color, 0);
+					region.g = toColor(color, 1);
+					region.b = toColor(color, 2);
+					region.a = toColor(color, 3);
+				}
+				region.updateOffset();
+				return region;
+			case AttachmentType.mesh:
+			case AttachmentType.linkedmesh:
+				var mesh:MeshAttachment = attachmentLoader.newMeshAttachment(skin, name, map["path"] || name);
+				if (!mesh) return null;
+				mesh.path = map["path"] || name;
+
+				color = map["color"];
+				if (color) {
+					mesh.r = toColor(color, 0);
+					mesh.g = toColor(color, 1);
+					mesh.b = toColor(color, 2);
+					mesh.a = toColor(color, 3);
+				}
+
+				mesh.width = Number(map["width"] || 0) * scale;
+				mesh.height = Number(map["height"] || 0) * scale;
+
+				if (map["parent"]) {
+					mesh.inheritDeform = map.hasOwnProperty("deform") ? Boolean(map["deform"]) : true;
+					linkedMeshes.push(new LinkedMesh(mesh, map["skin"], slotIndex, map["parent"]));
+					return mesh;
+				}
+				
+				var uvs:Vector.<Number> = getFloatArray(map, "uvs", 1);
+				readVertices(map, mesh, uvs.length);			
+				mesh.triangles = getUintArray(map, "triangles");	
+				mesh.regionUVs = uvs;									
+				mesh.updateUVs();
+
+				mesh.hullLength = int(map["hull"] || 0) * 2;
+				if (map["edges"]) mesh.edges = getIntArray(map, "edges");
+				return mesh;			
+			case AttachmentType.boundingbox:
+				var box:BoundingBoxAttachment = attachmentLoader.newBoundingBoxAttachment(skin, name);
+				if (!box) return null;
+				readVertices(map, box, int(map["vertexCount"]) << 1);								
+				return box;
+			case AttachmentType.path:
+				var path:PathAttachment = attachmentLoader.newPathAttachment(skin, name);
+				if (!path) return null;
+				path.closed = map.hasOwnProperty("closed") ? Boolean(map["closed"]) : false;
+				path.constantSpeed = map.hasOwnProperty("constantSpeed") ? Boolean(map["constantSpeed"]) : true;
+				
+				var vertexCount:int = int(map["vertexCount"]);
+				readVertices(map, path, vertexCount << 1);
+				
+				var lengths:Vector.<Number> = new Vector.<Number>();							
+				for each (var curves:Object in map["lengths"]) {
+					lengths.push(Number(curves) * scale);
+				}
+				path.lengths = lengths;				
+				return path;
+		}
+
+		return null;
+	}
+	
+	private function readVertices(map:Object, attachment:VertexAttachment, verticesLength:int) : void {
+		attachment.worldVerticesLength = verticesLength;
+		var vertices:Vector.<Number> = getFloatArray(map, "vertices", 1);
+		if (verticesLength == vertices.length) {
+			if (scale != 1) {
+				for (var i:int = 0, n:int = vertices.length; i < n; i++) {
+					vertices[i] *= scale;
+				}
+			}
+			attachment.vertices = vertices;
+			return;
+		}
+		
+		var weights:Vector.<Number> = new Vector.<Number>(verticesLength * 3 * 3);
+		weights.length = 0;
+		var bones:Vector.<int> = new Vector.<int>(verticesLength * 3);
+		bones.length = 0;
+		for (i = 0, n = vertices.length; i < n;) {
+			 var boneCount:int = int(vertices[i++]);
+			 bones.push(boneCount);
+			 for (var nn:int = i + boneCount * 4; i < nn; i+=4) {
+				bones.push(int(vertices[i]));
+				weights.push(vertices[i + 1] * scale);
+				weights.push(vertices[i + 2] * scale);
+				weights.push(vertices[i + 3]);
+			 }
+		}
+		attachment.bones = bones;
+		attachment.vertices = weights;
+	}
+
+	private function readAnimation (map:Object, name:String, skeletonData:SkeletonData) : void {
+		var scale:Number = this.scale;
+		var timelines:Vector.<Timeline> = new Vector.<Timeline>();
+		var duration:Number = 0;
+
+		var slotMap:Object, slotIndex:int, slotName:String;
+		var values:Array, valueMap:Object, frameIndex:int;
+		var i:int;
+		var timelineName:String;
+
+		var slots:Object = map["slots"];
+		for (slotName in slots) {
+			slotMap = slots[slotName];
+			slotIndex = skeletonData.findSlotIndex(slotName);
+
+			for (timelineName in slotMap) {
+				values = slotMap[timelineName];
+				if (timelineName == "color") {
+					var colorTimeline:ColorTimeline = new ColorTimeline(values.length);
+					colorTimeline.slotIndex = slotIndex;
+
+					frameIndex = 0;
+					for each (valueMap in values) {
+						var color:String = valueMap["color"];
+						var r:Number = toColor(color, 0);
+						var g:Number = toColor(color, 1);
+						var b:Number = toColor(color, 2);
+						var a:Number = toColor(color, 3);
+						colorTimeline.setFrame(frameIndex, valueMap["time"], r, g, b, a);
+						readCurve(valueMap, colorTimeline, frameIndex);
+						frameIndex++;
+					}
+					timelines[timelines.length] = colorTimeline;
+					duration = Math.max(duration, colorTimeline.frames[(colorTimeline.frameCount - 1) * ColorTimeline.ENTRIES]);
+				} else if (timelineName == "attachment") {
+					var attachmentTimeline:AttachmentTimeline = new AttachmentTimeline(values.length);
+					attachmentTimeline.slotIndex = slotIndex;
+
+					frameIndex = 0;
+					for each (valueMap in values)
+						attachmentTimeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]);
+					timelines[timelines.length] = attachmentTimeline;
+					duration = Math.max(duration, attachmentTimeline.frames[attachmentTimeline.frameCount - 1]);
+				} else
+					throw new Error("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")");
+			}
+		}
+
+		var bones:Object = map["bones"];
+		for (var boneName:String in bones) {
+			var boneIndex:int = skeletonData.findBoneIndex(boneName);
+			if (boneIndex == -1) throw new Error("Bone not found: " + boneName);
+			var boneMap:Object = bones[boneName];
+
+			for (timelineName in boneMap) {
+				values = boneMap[timelineName];
+				if (timelineName == "rotate") {
+					var rotateTimeline:RotateTimeline = new RotateTimeline(values.length);
+					rotateTimeline.boneIndex = boneIndex;
+
+					frameIndex = 0;
+					for each (valueMap in values) {
+						rotateTimeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]);
+						readCurve(valueMap, rotateTimeline, frameIndex);
+						frameIndex++;
+					}
+					timelines[timelines.length] = rotateTimeline;
+					duration = Math.max(duration, rotateTimeline.frames[(rotateTimeline.frameCount - 1) * RotateTimeline.ENTRIES]);
+				} else if (timelineName == "translate" || timelineName == "scale" || timelineName == "shear") {
+					var translateTimeline:TranslateTimeline;
+					var timelineScale:Number = 1;
+					if (timelineName == "scale")
+						translateTimeline = new ScaleTimeline(values.length);
+					else if (timelineName == "shear")
+						translateTimeline = new ShearTimeline(values.length);
+					else {
+						translateTimeline = new TranslateTimeline(values.length);
+						timelineScale = scale;
+					}
+					translateTimeline.boneIndex = boneIndex;
+
+					frameIndex = 0;
+					for each (valueMap in values) {
+						var x:Number = Number(valueMap["x"] || 0) * timelineScale;
+						var y:Number = Number(valueMap["y"] || 0) * timelineScale;
+						translateTimeline.setFrame(frameIndex, valueMap["time"], x, y);
+						readCurve(valueMap, translateTimeline, frameIndex);
+						frameIndex++;
+					}
+					timelines[timelines.length] = translateTimeline;
+					duration = Math.max(duration, translateTimeline.frames[(translateTimeline.frameCount - 1) * TranslateTimeline.ENTRIES]);
+				} else
+					throw new Error("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
+			}
+		}
+
+		var ikMap:Object = map["ik"];
+		for (var ikConstraintName:String in ikMap) {
+			var ikConstraint:IkConstraintData = skeletonData.findIkConstraint(ikConstraintName);
+			values = ikMap[ikConstraintName];
+			var ikTimeline:IkConstraintTimeline = new IkConstraintTimeline(values.length);
+			ikTimeline.ikConstraintIndex = skeletonData.ikConstraints.indexOf(ikConstraint);
+			frameIndex = 0;
+			for each (valueMap in values) {
+				var mix:Number = valueMap.hasOwnProperty("mix") ? valueMap["mix"] : 1;
+				var bendDirection:int = (!valueMap.hasOwnProperty("bendPositive") || valueMap["bendPositive"]) ? 1 : -1;
+				ikTimeline.setFrame(frameIndex, valueMap["time"], mix, bendDirection);
+				readCurve(valueMap, ikTimeline, frameIndex);
+				frameIndex++;
+			}
+			timelines[timelines.length] = ikTimeline;
+			duration = Math.max(duration, ikTimeline.frames[(ikTimeline.frameCount - 1) * IkConstraintTimeline.ENTRIES]);
+		}
+		
+		var transformMap:Object = map["transform"];
+		for (var transformName:String in transformMap) {
+			var transformConstraint:TransformConstraintData = skeletonData.findTransformConstraint(transformName);
+			values = transformMap[transformName];
+			var transformTimeline:TransformConstraintTimeline = new TransformConstraintTimeline(values.length);
+			transformTimeline.transformConstraintIndex = skeletonData.transformConstraints.indexOf(transformConstraint);
+			frameIndex = 0;
+			for each (valueMap in values) {
+				var rotateMix:Number = valueMap.hasOwnProperty("rotateMix") ? valueMap["rotateMix"] : 1;
+				var translateMix:Number = valueMap.hasOwnProperty("translateMix") ? valueMap["translateMix"] : 1;
+				var scaleMix:Number = valueMap.hasOwnProperty("scaleMix") ? valueMap["scaleMix"] : 1;
+				var shearMix:Number = valueMap.hasOwnProperty("shearMix") ? valueMap["shearMix"] : 1;
+				transformTimeline.setFrame(frameIndex, valueMap["time"], rotateMix, translateMix, scaleMix, shearMix);
+				readCurve(valueMap, transformTimeline, frameIndex);
+				frameIndex++;
+			}
+			timelines.push(transformTimeline);
+			duration = Math.max(duration, transformTimeline.frames[(transformTimeline.frameCount - 1) * TransformConstraintTimeline.ENTRIES]);
+		}
+				
+		// Path constraint timelines.
+		var paths:Object = map["paths"];
+		for (var pathName:String in paths) {
+			var index:int = skeletonData.findPathConstraintIndex(pathName);
+			if (index == -1) throw new Error("Path constraint not found: " + pathName);
+			var data:PathConstraintData = skeletonData.pathConstraints[index];
+			
+			var pathMap:Object = paths[pathName];
+			for (timelineName in pathMap) {
+				values = pathMap[timelineName];
+				
+				if (timelineName == "position" || timelineName == "spacing") {
+					var pathTimeline:PathConstraintPositionTimeline;
+					timelineScale = 1;
+					if (timelineName == "spacing") {
+						pathTimeline = new PathConstraintSpacingTimeline(values.length);
+						if (data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed) timelineScale = scale;
+					} else {
+						pathTimeline = new PathConstraintPositionTimeline(values.length);
+						if (data.positionMode == PositionMode.fixed) timelineScale = scale;
+					}
+					pathTimeline.pathConstraintIndex = index;
+					frameIndex = 0;
+					for each (valueMap in values) {
+						var value:Number = valueMap[timelineName] || 0;
+						pathTimeline.setFrame(frameIndex, valueMap["time"], value * timelineScale);
+						readCurve(valueMap, pathTimeline, frameIndex);
+						frameIndex++;
+					}
+					timelines.push(pathTimeline);
+					duration = Math.max(duration,
+						pathTimeline.frames[(pathTimeline.frameCount - 1) * PathConstraintPositionTimeline.ENTRIES]);
+				} else if (timelineName == "mix") {
+					var pathMixTimeline:PathConstraintMixTimeline = new PathConstraintMixTimeline(values.length);
+					pathMixTimeline.pathConstraintIndex = index;
+					frameIndex = 0;
+					for each (valueMap in values) {
+						rotateMix = valueMap.hasOwnProperty("rotateMix") ? valueMap["rotateMix"] : 1;
+						translateMix = valueMap.hasOwnProperty("translateMix") ? valueMap["translateMix"] : 1;
+						pathMixTimeline.setFrame(frameIndex, valueMap["time"], rotateMix, translateMix);
+						readCurve(valueMap, pathMixTimeline, frameIndex);
+						frameIndex++;
+					}
+					timelines.push(pathMixTimeline);
+					duration = Math.max(duration,
+						pathMixTimeline.frames[(pathMixTimeline.frameCount - 1) * PathConstraintMixTimeline.ENTRIES]);
+				}
+			}
+		}
+		
+		var deformMap:Object = map["deform"];
+		for (var skinName:String in deformMap) {
+			var skin:Skin = skeletonData.findSkin(skinName);
+			slotMap = deformMap[skinName];
+			for (slotName in slotMap) {
+				slotIndex = skeletonData.findSlotIndex(slotName);
+				var timelineMap:Object = slotMap[slotName];
+				for (timelineName in timelineMap) {
+					values = timelineMap[timelineName];
+
+					var attachment:VertexAttachment = skin.getAttachment(slotIndex, timelineName) as VertexAttachment;
+					if (attachment == null) throw new Error("Deform attachment not found: " + timelineName);
+					var weighted:Boolean = attachment.bones != null;
+					var vertices:Vector.<Number> = attachment.vertices;
+					var deformLength:int = weighted ? vertices.length / 3 * 2 : vertices.length;
+
+					var deformTimeline:DeformTimeline = new DeformTimeline(values.length);
+					deformTimeline.slotIndex = slotIndex;
+					deformTimeline.attachment = attachment;
+
+					frameIndex = 0;
+					for each (valueMap in values) {
+						var deform:Vector.<Number>;
+						var verticesValue:Object = valueMap["vertices"];
+						if (verticesValue == null)
+							deform = weighted ? new Vector.<Number>(deformLength, true) : vertices;
+						else {
+							deform = new Vector.<Number>(deformLength, true);
+							var start:int = Number(valueMap["offset"] || 0);
+							var temp:Vector.<Number> = getFloatArray(valueMap, "vertices", 1);
+							for (i = 0; i < temp.length; i++) {
+								deform[start + i] = temp[i];
+							}							
+							if (scale != 1) {
+								var n:int;
+								for (i = start, n = i + temp.length; i < n; i++)
+									deform[i] *= scale;
+							}
+							if (!weighted) {
+								for (i = 0; i < deformLength; i++)
+									deform[i] += vertices[i];
+							}
+						}
+
+						deformTimeline.setFrame(frameIndex, valueMap["time"], deform);
+						readCurve(valueMap, deformTimeline, frameIndex);
+						frameIndex++;
+					}
+					timelines[timelines.length] = deformTimeline;
+					duration = Math.max(duration, deformTimeline.frames[deformTimeline.frameCount - 1]);
+				}
+			}
+		}
+
+		var drawOrderValues:Array = map["drawOrder"];
+		if (!drawOrderValues) drawOrderValues = map["draworder"];
+		if (drawOrderValues) {
+			var drawOrderTimeline:DrawOrderTimeline = new DrawOrderTimeline(drawOrderValues.length);
+			var slotCount:int = skeletonData.slots.length;
+			frameIndex = 0;
+			for each (var drawOrderMap:Object in drawOrderValues) {
+				var drawOrder:Vector.<int> = null;
+				if (drawOrderMap["offsets"]) {
+					drawOrder = new Vector.<int>(slotCount);
+					for (i = slotCount - 1; i >= 0; i--)
+						drawOrder[i] = -1;
+					var offsets:Array = drawOrderMap["offsets"];
+					var unchanged:Vector.<int> = new Vector.<int>(slotCount - offsets.length);
+					var originalIndex:int = 0, unchangedIndex:int = 0;
+					for each (var offsetMap:Object in offsets) {
+						slotIndex = skeletonData.findSlotIndex(offsetMap["slot"]);
+						if (slotIndex == -1) throw new Error("Slot not found: " + offsetMap["slot"]);
+						// Collect unchanged items.
+						while (originalIndex != slotIndex)
+							unchanged[unchangedIndex++] = originalIndex++;
+						// Set changed items.
+						drawOrder[originalIndex + offsetMap["offset"]] = originalIndex++;
+					}
+					// Collect remaining unchanged items.
+					while (originalIndex < slotCount)
+						unchanged[unchangedIndex++] = originalIndex++;
+					// Fill in unchanged items.
+					for (i = slotCount - 1; i >= 0; i--)
+						if (drawOrder[i] == -1) drawOrder[i] = unchanged[--unchangedIndex];
+				}
+				drawOrderTimeline.setFrame(frameIndex++, drawOrderMap["time"], drawOrder);
+			}
+			timelines[timelines.length] = drawOrderTimeline;
+			duration = Math.max(duration, drawOrderTimeline.frames[drawOrderTimeline.frameCount - 1]);
+		}
+
+		var eventsMap:Array = map["events"];
+		if (eventsMap) {
+			var eventTimeline:EventTimeline = new EventTimeline(eventsMap.length);
+			frameIndex = 0;
+			for each (var eventMap:Object in eventsMap) {
+				var eventData:EventData = skeletonData.findEvent(eventMap["name"]);
+				if (!eventData) throw new Error("Event not found: " + eventMap["name"]);
+				var event:Event = new Event(eventMap["time"], eventData);
+				event.intValue = eventMap.hasOwnProperty("int") ? eventMap["int"] : eventData.intValue;
+				event.floatValue = eventMap.hasOwnProperty("float") ? eventMap["float"] : eventData.floatValue;
+				event.stringValue = eventMap.hasOwnProperty("string") ? eventMap["string"] : eventData.stringValue;
+				eventTimeline.setFrame(frameIndex++, event);
+			}
+			timelines[timelines.length] = eventTimeline;
+			duration = Math.max(duration, eventTimeline.frames[eventTimeline.frameCount - 1]);
+		}
+
+		skeletonData.animations[skeletonData.animations.length] = new Animation(name, timelines, duration);
+	}
+
+	static private function readCurve (map:Object, timeline:CurveTimeline, frameIndex:int) : void {
+		var curve:Object = map["curve"];
+		if (!curve) return;
+		if (curve == "stepped")
+			timeline.setStepped(frameIndex);
+		else if (curve is Array)
+			timeline.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]);
+	}
+
+	static private function toColor (hexString:String, colorIndex:int) : Number {
+		if (hexString.length != 8) throw new ArgumentError("Color hexidecimal length must be 8, recieved: " + hexString);
+		return parseInt(hexString.substring(colorIndex * 2, colorIndex * 2 + 2), 16) / 255;
+	}
+
+	static private function getFloatArray (map:Object, name:String, scale:Number) : Vector.<Number> {
+		var list:Array = map[name];
+		var values:Vector.<Number> = new Vector.<Number>(list.length, true);
+		var i:int = 0, n:int = list.length;
+		if (scale == 1) {
+			for (; i < n; i++)
+				values[i] = list[i];
+		} else {
+			for (; i < n; i++)
+				values[i] = list[i] * scale;
+		}
+		return values;
+	}
+
+	static private function getIntArray (map:Object, name:String) : Vector.<int> {
+		var list:Array = map[name];
+		var values:Vector.<int> = new Vector.<int>(list.length, true);
+		for (var i:int = 0, n:int = list.length; i < n; i++)
+			values[i] = int(list[i]);
+		return values;
+	}
+
+	static private function getUintArray (map:Object, name:String) : Vector.<uint> {
+		var list:Array = map[name];
+		var values:Vector.<uint> = new Vector.<uint>(list.length, true);
+		for (var i:int = 0, n:int = list.length; i < n; i++)
+			values[i] = int(list[i]);
+		return values;
+	}
+}
+
+}
+
+import spine.attachments.MeshAttachment;
+
+internal class LinkedMesh {
+	internal var parent:String, skin:String;
+	internal var slotIndex:int;
+	internal var mesh:MeshAttachment;
+
+	public function LinkedMesh (mesh:MeshAttachment, skin:String, slotIndex:int, parent:String) {
+		this.mesh = mesh;
+		this.skin = skin;
+		this.slotIndex = slotIndex;
+		this.parent = parent;
+	}
 }

+ 90 - 91
spine-as3/spine-as3/src/spine/Skin.as

@@ -1,94 +1,93 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-import flash.utils.Dictionary;
-
-import spine.attachments.Attachment;
-
-/** Stores attachments by slot index and attachment name. */
-public class Skin {
-	internal var _name:String;
-	private var _attachments:Vector.<Dictionary> = new Vector.<Dictionary>();
-
-	public function Skin (name:String) {
-		if (name == null) throw new ArgumentError("name cannot be null.");
-		_name = name;
-	}
-
-	public function addAttachment (slotIndex:int, name:String, attachment:Attachment) : void {
-		if (attachment == null) throw new ArgumentError("attachment cannot be null.");
-		if (slotIndex >= attachments.length) attachments.length = slotIndex + 1;
-		if (!attachments[slotIndex]) attachments[slotIndex] = new Dictionary();
-		attachments[slotIndex][name] = attachment;
-	}
-
-	/** @return May be null. */
-	public function getAttachment (slotIndex:int, name:String) : Attachment {
-		if (slotIndex >= attachments.length) return null;
-		var dictionary:Dictionary = attachments[slotIndex];
-		return dictionary ? dictionary[name] : null;
-	}
-
-	public function get attachments () : Vector.<Dictionary> {
-		return _attachments;
-	}
-
-	public function get name () : String {
-		return _name;
-	}
-
-	public function toString () : String {
-		return _name;
-	}
-
-	/** Attach each attachment in this skin if the corresponding attachment in the old skin is currently attached. */
-	public function attachAll (skeleton:Skeleton, oldSkin:Skin) : void {
-		var slotIndex:int = 0;
-		for each (var slot:Slot in skeleton.slots) {
-			var slotAttachment:Attachment = slot.attachment;
-			if (slotAttachment && slotIndex < oldSkin.attachments.length) {
-				var dictionary:Dictionary = oldSkin.attachments[slotIndex];
-				for (var name:String in dictionary) {
-					var skinAttachment:Attachment = dictionary[name];
-					if (slotAttachment == skinAttachment) {
-						var attachment:Attachment = getAttachment(slotIndex, name);
-						if (attachment != null) slot.attachment = attachment;
-						break;
-					}
-				}
-			}
-			slotIndex++;
-		}
-	}
-}
-
+package spine {
+import flash.utils.Dictionary;
+
+import spine.attachments.Attachment;
+
+/** Stores attachments by slot index and attachment name. */
+public class Skin {
+	internal var _name:String;
+	private var _attachments:Vector.<Dictionary> = new Vector.<Dictionary>();
+
+	public function Skin (name:String) {
+		if (name == null) throw new ArgumentError("name cannot be null.");
+		_name = name;
+	}
+
+	public function addAttachment (slotIndex:int, name:String, attachment:Attachment) : void {
+		if (attachment == null) throw new ArgumentError("attachment cannot be null.");
+		if (slotIndex >= attachments.length) attachments.length = slotIndex + 1;
+		if (!attachments[slotIndex]) attachments[slotIndex] = new Dictionary();
+		attachments[slotIndex][name] = attachment;
+	}
+
+	/** @return May be null. */
+	public function getAttachment (slotIndex:int, name:String) : Attachment {
+		if (slotIndex >= attachments.length) return null;
+		var dictionary:Dictionary = attachments[slotIndex];
+		return dictionary ? dictionary[name] : null;
+	}
+
+	public function get attachments () : Vector.<Dictionary> {
+		return _attachments;
+	}
+
+	public function get name () : String {
+		return _name;
+	}
+
+	public function toString () : String {
+		return _name;
+	}
+
+	/** Attach each attachment in this skin if the corresponding attachment in the old skin is currently attached. */
+	public function attachAll (skeleton:Skeleton, oldSkin:Skin) : void {
+		var slotIndex:int = 0;
+		for each (var slot:Slot in skeleton.slots) {
+			var slotAttachment:Attachment = slot.attachment;
+			if (slotAttachment && slotIndex < oldSkin.attachments.length) {
+				var dictionary:Dictionary = oldSkin.attachments[slotIndex];
+				for (var name:String in dictionary) {
+					var skinAttachment:Attachment = dictionary[name];
+					if (slotAttachment == skinAttachment) {
+						var attachment:Attachment = getAttachment(slotIndex, name);
+						if (attachment != null) slot.attachment = attachment;
+						break;
+					}
+				}
+			}
+			slotIndex++;
+		}
+	}
+}
+
 }

+ 103 - 104
spine-as3/spine-as3/src/spine/Slot.as

@@ -1,107 +1,106 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-import spine.attachments.Attachment;
-
-public class Slot {
-	internal var _data:SlotData;
-	internal var _bone:Bone;
-	public var r:Number;
-	public var g:Number;
-	public var b:Number;
-	public var a:Number;
-	internal var _attachment:Attachment;
-	private var _attachmentTime:Number;
-	public var attachmentVertices:Vector.<Number> = new Vector.<Number>();
-
-	public function Slot (data:SlotData, bone:Bone) {
-		if (data == null) throw new ArgumentError("data cannot be null.");
-		if (bone == null) throw new ArgumentError("bone cannot be null.");
-		_data = data;
-		_bone = bone;
-		setToSetupPose();
-	}
-
-	public function get data () : SlotData {
-		return _data;
-	}
-	
-	public function get bone () : Bone {
-		return _bone;
-	}
-	
-	public function get skeleton () : Skeleton {
-		return _bone._skeleton;
-	}
-
-	/** @return May be null. */
-	public function get attachment () : Attachment {
-		return _attachment;
-	}
-
-	/** Sets the attachment and resets {@link #getAttachmentTime()}.
-	 * @param attachment May be null. */
-	public function set attachment (attachment:Attachment) : void {
-		if (_attachment == attachment) return;
-		_attachment = attachment;
-		_attachmentTime = _bone._skeleton.time;
-		attachmentVertices.length = 0;
-	}
-
-	public function set attachmentTime (time:Number) : void {
-		_attachmentTime = _bone._skeleton.time - time;
-	}
-
-	/** Returns the time since the attachment was set. */
-	public function get attachmentTime () : Number {
-		return _bone._skeleton.time - _attachmentTime;
-	}
-
-	public function setToSetupPose () : void {		
-		r = _data.r;
-		g = _data.g;
-		b = _data.b;
-		a = _data.a;
-		if (_data.attachmentName == null)
-			attachment = null;
-		else {
-			_attachment = null;
-			attachment = _bone._skeleton.getAttachmentForSlotIndex(data.index, data.attachmentName);
-		}
-	}
-
-	public function toString () : String {
-		return _data.name;
-	}
-}
-
+package spine {
+import spine.attachments.Attachment;
+
+public class Slot {
+	internal var _data:SlotData;
+	internal var _bone:Bone;
+	public var r:Number;
+	public var g:Number;
+	public var b:Number;
+	public var a:Number;
+	internal var _attachment:Attachment;
+	private var _attachmentTime:Number;
+	public var attachmentVertices:Vector.<Number> = new Vector.<Number>();
+
+	public function Slot (data:SlotData, bone:Bone) {
+		if (data == null) throw new ArgumentError("data cannot be null.");
+		if (bone == null) throw new ArgumentError("bone cannot be null.");
+		_data = data;
+		_bone = bone;
+		setToSetupPose();
+	}
+
+	public function get data () : SlotData {
+		return _data;
+	}
+	
+	public function get bone () : Bone {
+		return _bone;
+	}
+	
+	public function get skeleton () : Skeleton {
+		return _bone._skeleton;
+	}
+
+	/** @return May be null. */
+	public function get attachment () : Attachment {
+		return _attachment;
+	}
+
+	/** Sets the attachment and resets {@link #getAttachmentTime()}.
+	 * @param attachment May be null. */
+	public function set attachment (attachment:Attachment) : void {
+		if (_attachment == attachment) return;
+		_attachment = attachment;
+		_attachmentTime = _bone._skeleton.time;
+		attachmentVertices.length = 0;
+	}
+
+	public function set attachmentTime (time:Number) : void {
+		_attachmentTime = _bone._skeleton.time - time;
+	}
+
+	/** Returns the time since the attachment was set. */
+	public function get attachmentTime () : Number {
+		return _bone._skeleton.time - _attachmentTime;
+	}
+
+	public function setToSetupPose () : void {		
+		r = _data.r;
+		g = _data.g;
+		b = _data.b;
+		a = _data.a;
+		if (_data.attachmentName == null)
+			attachment = null;
+		else {
+			_attachment = null;
+			attachment = _bone._skeleton.getAttachmentForSlotIndex(data.index, data.attachmentName);
+		}
+	}
+
+	public function toString () : String {
+		return _data.name;
+	}
+}
+
 }

+ 67 - 68
spine-as3/spine-as3/src/spine/SlotData.as

@@ -1,71 +1,70 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public class SlotData {
-	internal var _index:int;
-	internal var _name:String;
-	internal var _boneData:BoneData;
-	public var r:Number = 1;
-	public var g:Number = 1;
-	public var b:Number = 1;
-	public var a:Number = 1;
-	public var attachmentName:String;
-	public var blendMode:BlendMode;
-
-	public function SlotData (index:int, name:String, boneData:BoneData) {
-		if (index < 0) throw new ArgumentError("index must be >= 0.");
-		if (name == null) throw new ArgumentError("name cannot be null.");
-		if (boneData == null) throw new ArgumentError("boneData cannot be null.");
-		_index = index;
-		_name = name;
-		_boneData = boneData;
-	}
-	
-	public function get index () : int {
-		return _index;
-	}
-
-	public function get name () : String {
-		return _name;
-	}
-
-	public function get boneData () : BoneData {
-		return _boneData;
-	}
-
-	public function toString () : String {
-		return _name;
-	}
-}
-
+package spine {
+
+public class SlotData {
+	internal var _index:int;
+	internal var _name:String;
+	internal var _boneData:BoneData;
+	public var r:Number = 1;
+	public var g:Number = 1;
+	public var b:Number = 1;
+	public var a:Number = 1;
+	public var attachmentName:String;
+	public var blendMode:BlendMode;
+
+	public function SlotData (index:int, name:String, boneData:BoneData) {
+		if (index < 0) throw new ArgumentError("index must be >= 0.");
+		if (name == null) throw new ArgumentError("name cannot be null.");
+		if (boneData == null) throw new ArgumentError("boneData cannot be null.");
+		_index = index;
+		_name = name;
+		_boneData = boneData;
+	}
+	
+	public function get index () : int {
+		return _index;
+	}
+
+	public function get name () : String {
+		return _name;
+	}
+
+	public function get boneData () : BoneData {
+		return _boneData;
+	}
+
+	public function toString () : String {
+		return _name;
+	}
+}
+
 }

+ 36 - 37
spine-as3/spine-as3/src/spine/SpacingMode.as

@@ -1,40 +1,39 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public class SpacingMode {
-	public static const length:SpacingMode = new SpacingMode();
-	public static const fixed:SpacingMode = new SpacingMode();
-	public static const percent:SpacingMode = new SpacingMode();
+package spine {
+
+public class SpacingMode {
+	public static const length:SpacingMode = new SpacingMode();
+	public static const fixed:SpacingMode = new SpacingMode();
+	public static const percent:SpacingMode = new SpacingMode();
+}
+
 }
-
-}

+ 129 - 130
spine-as3/spine-as3/src/spine/TransformConstraint.as

@@ -1,133 +1,132 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public class TransformConstraint implements Updatable {
-	internal var _data:TransformConstraintData;
-	internal var _bones:Vector.<Bone>;
-	public var target:Bone;
-	public var rotateMix:Number;	
-	public var translateMix:Number;
-	public var scaleMix:Number;
-	public var shearMix:Number;
-	internal var _temp:Vector.<Number> = new Vector.<Number>(2);
-
-	public function TransformConstraint (data:TransformConstraintData, skeleton:Skeleton) {
-		if (data == null) throw new ArgumentError("data cannot be null.");
-		if (skeleton == null) throw new ArgumentError("skeleton cannot be null.");
-		_data = data;
-		rotateMix = data.rotateMix;
-		translateMix = data.translateMix;
-		scaleMix = data.scaleMix;
-		shearMix = data.shearMix;
-		_bones = new Vector.<Bone>();		
-		for each (var boneData:BoneData in data.bones)
-			_bones.push(skeleton.findBone(boneData.name));		
-		target = skeleton.findBone(data.target._name);
-	}		
-
-	public function apply () : void {
-		update();
-	}
-
-	public function update () : void {
-		var rotateMix:Number = this.rotateMix, translateMix:Number = this.translateMix, scaleMix:Number = this.scaleMix, shearMix:Number = this.shearMix;
-		var target:Bone = this.target;
-		var ta:Number = target.a, tb:Number = target.b, tc:Number = target.c, td:Number = target.d;
-		var bones:Vector.<Bone> = this._bones;
-		for (var i:int = 0, n:int = bones.length; i < n; i++) {
-			var bone:Bone = bones[i];
-
-			if (rotateMix > 0) {
-				var a:Number = bone.a, b:Number = bone.b, c:Number = bone.c, d:Number = bone.d;
-				var r:Number = Math.atan2(tc, ta) - Math.atan2(c, a) + data.offsetRotation * MathUtils.degRad;
-				if (r > Math.PI)
-					r -= Math.PI * 2;
-				else if (r < -Math.PI) r += Math.PI * 2;
-				r *= rotateMix;
-				var cos:Number = Math.cos(r), sin:Number = Math.sin(r);
-				bone._a = cos * a - sin * c;
-				bone._b = cos * b - sin * d;
-				bone._c = sin * a + cos * c;
-				bone._d = sin * b + cos * d;
-			}
-
-			if (translateMix > 0) {
-				_temp[0] = data.offsetX;
-				_temp[1] = data.offsetY;
-				target.localToWorld(_temp);
-				bone._worldX += (_temp[0] - bone.worldX) * translateMix;
-				bone._worldY += (_temp[1] - bone.worldY) * translateMix;
-			}
-
-			if (scaleMix > 0) {
-				var bs:Number = Math.sqrt(bone.a * bone.a + bone.c * bone.c);
-				var ts:Number = Math.sqrt(ta * ta + tc * tc);
-				var s:Number = bs > 0.00001 ? (bs + (ts - bs + data.offsetScaleX) * scaleMix) / bs : 0;
-				bone._a *= s;
-				bone._c *= s;
-				bs = Math.sqrt(bone.b * bone.b + bone.d * bone.d);
-				ts = Math.sqrt(tb * tb + td * td);
-				s = bs > 0.00001 ? (bs + (ts - bs + data.offsetScaleY) * scaleMix) / bs : 0;
-				bone._b *= s;
-				bone._d *= s;
-			}
-
-			if (shearMix > 0) {
-				b = bone.b, d = bone.d;
-				var by:Number = Math.atan2(d, b);
-				r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a));
-				if (r > Math.PI)
-					r -= Math.PI * 2;
-				else if (r < -Math.PI) r += Math.PI * 2;
-				r = by + (r + data.offsetShearY * MathUtils.degRad) * shearMix;
-				s = Math.sqrt(b * b + d * d);
-				bone._b = Math.cos(r) * s;
-				bone._d = Math.sin(r) * s;
-			}
-		}
-	}
-
-	public function get data () : TransformConstraintData {
-		return _data;
-	}
-	
-	public function get bones () : Vector.<Bone> {
-		return _bones;
-	}
-
-	public function toString () : String {
-		return _data._name;
-	}
-}
-
+package spine {
+
+public class TransformConstraint implements Updatable {
+	internal var _data:TransformConstraintData;
+	internal var _bones:Vector.<Bone>;
+	public var target:Bone;
+	public var rotateMix:Number;	
+	public var translateMix:Number;
+	public var scaleMix:Number;
+	public var shearMix:Number;
+	internal var _temp:Vector.<Number> = new Vector.<Number>(2);
+
+	public function TransformConstraint (data:TransformConstraintData, skeleton:Skeleton) {
+		if (data == null) throw new ArgumentError("data cannot be null.");
+		if (skeleton == null) throw new ArgumentError("skeleton cannot be null.");
+		_data = data;
+		rotateMix = data.rotateMix;
+		translateMix = data.translateMix;
+		scaleMix = data.scaleMix;
+		shearMix = data.shearMix;
+		_bones = new Vector.<Bone>();		
+		for each (var boneData:BoneData in data.bones)
+			_bones.push(skeleton.findBone(boneData.name));		
+		target = skeleton.findBone(data.target._name);
+	}		
+
+	public function apply () : void {
+		update();
+	}
+
+	public function update () : void {
+		var rotateMix:Number = this.rotateMix, translateMix:Number = this.translateMix, scaleMix:Number = this.scaleMix, shearMix:Number = this.shearMix;
+		var target:Bone = this.target;
+		var ta:Number = target.a, tb:Number = target.b, tc:Number = target.c, td:Number = target.d;
+		var bones:Vector.<Bone> = this._bones;
+		for (var i:int = 0, n:int = bones.length; i < n; i++) {
+			var bone:Bone = bones[i];
+
+			if (rotateMix > 0) {
+				var a:Number = bone.a, b:Number = bone.b, c:Number = bone.c, d:Number = bone.d;
+				var r:Number = Math.atan2(tc, ta) - Math.atan2(c, a) + data.offsetRotation * MathUtils.degRad;
+				if (r > Math.PI)
+					r -= Math.PI * 2;
+				else if (r < -Math.PI) r += Math.PI * 2;
+				r *= rotateMix;
+				var cos:Number = Math.cos(r), sin:Number = Math.sin(r);
+				bone._a = cos * a - sin * c;
+				bone._b = cos * b - sin * d;
+				bone._c = sin * a + cos * c;
+				bone._d = sin * b + cos * d;
+			}
+
+			if (translateMix > 0) {
+				_temp[0] = data.offsetX;
+				_temp[1] = data.offsetY;
+				target.localToWorld(_temp);
+				bone._worldX += (_temp[0] - bone.worldX) * translateMix;
+				bone._worldY += (_temp[1] - bone.worldY) * translateMix;
+			}
+
+			if (scaleMix > 0) {
+				var bs:Number = Math.sqrt(bone.a * bone.a + bone.c * bone.c);
+				var ts:Number = Math.sqrt(ta * ta + tc * tc);
+				var s:Number = bs > 0.00001 ? (bs + (ts - bs + data.offsetScaleX) * scaleMix) / bs : 0;
+				bone._a *= s;
+				bone._c *= s;
+				bs = Math.sqrt(bone.b * bone.b + bone.d * bone.d);
+				ts = Math.sqrt(tb * tb + td * td);
+				s = bs > 0.00001 ? (bs + (ts - bs + data.offsetScaleY) * scaleMix) / bs : 0;
+				bone._b *= s;
+				bone._d *= s;
+			}
+
+			if (shearMix > 0) {
+				b = bone.b, d = bone.d;
+				var by:Number = Math.atan2(d, b);
+				r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a));
+				if (r > Math.PI)
+					r -= Math.PI * 2;
+				else if (r < -Math.PI) r += Math.PI * 2;
+				r = by + (r + data.offsetShearY * MathUtils.degRad) * shearMix;
+				s = Math.sqrt(b * b + d * d);
+				bone._b = Math.cos(r) * s;
+				bone._d = Math.sin(r) * s;
+			}
+		}
+	}
+
+	public function get data () : TransformConstraintData {
+		return _data;
+	}
+	
+	public function get bones () : Vector.<Bone> {
+		return _bones;
+	}
+
+	public function toString () : String {
+		return _data._name;
+	}
+}
+
 }

+ 63 - 64
spine-as3/spine-as3/src/spine/TransformConstraintData.as

@@ -1,67 +1,66 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public class TransformConstraintData {
-	internal var _name:String;
-	internal var _bones:Vector.<BoneData> = new Vector.<BoneData>();
-	public var target:BoneData;
-	public var rotateMix:Number;
-	public var translateMix:Number;
-	public var scaleMix:Number;
-	public var shearMix:Number;
-	public var offsetRotation:Number;
-	public var offsetX:Number;
-	public var offsetY:Number;
-	public var offsetScaleX:Number;
-	public var offsetScaleY:Number;
-	public var offsetShearY:Number;
-
-	public function TransformConstraintData (name:String) {
-		if (name == null) throw new ArgumentError("name cannot be null.");
-		_name = name;
-	}
-	
-	public function get bones () : Vector.<BoneData> {;
-		return _bones;
-	}
-
-	public function get name () : String {
-		return _name;
-	}
-
-	public function toString () : String {
-		return _name;
-	}
-}
-
+package spine {
+
+public class TransformConstraintData {
+	internal var _name:String;
+	internal var _bones:Vector.<BoneData> = new Vector.<BoneData>();
+	public var target:BoneData;
+	public var rotateMix:Number;
+	public var translateMix:Number;
+	public var scaleMix:Number;
+	public var shearMix:Number;
+	public var offsetRotation:Number;
+	public var offsetX:Number;
+	public var offsetY:Number;
+	public var offsetScaleX:Number;
+	public var offsetScaleY:Number;
+	public var offsetShearY:Number;
+
+	public function TransformConstraintData (name:String) {
+		if (name == null) throw new ArgumentError("name cannot be null.");
+		_name = name;
+	}
+	
+	public function get bones () : Vector.<BoneData> {;
+		return _bones;
+	}
+
+	public function get name () : String {
+		return _name;
+	}
+
+	public function toString () : String {
+		return _name;
+	}
+}
+
 }

+ 34 - 35
spine-as3/spine-as3/src/spine/Updatable.as

@@ -1,38 +1,37 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine {
-
-public interface Updatable {
-	function update () : void;
-}
-
+package spine {
+
+public interface Updatable {
+	function update () : void;
+}
+
 }

+ 130 - 131
spine-as3/spine-as3/src/spine/animation/Animation.as

@@ -1,134 +1,133 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-import spine.Event;
-import spine.Skeleton;
-
-public class Animation {
-	internal var _name:String;
-	private var _timelines:Vector.<Timeline>;
-	public var duration:Number;
-
-	public function Animation (name:String, timelines:Vector.<Timeline>, duration:Number) {
-		if (name == null) throw new ArgumentError("name cannot be null.");
-		if (timelines == null) throw new ArgumentError("timelines cannot be null.");
-		_name = name;
-		_timelines = timelines;
-		this.duration = duration;
-	}
-
-	public function get timelines () : Vector.<Timeline> {
-		return _timelines;
-	}
-
-	/** Poses the skeleton at the specified time for this animation. */
-	public function apply (skeleton:Skeleton, lastTime:Number, time:Number, loop:Boolean, events:Vector.<Event>) : void {
-		if (skeleton == null) throw new ArgumentError("skeleton cannot be null.");
-
-		if (loop && duration != 0) {
-			time %= duration;
-			if (lastTime > 0) lastTime %= duration;
-		}
-
-		for (var i:int = 0, n:int = timelines.length; i < n; i++)
-			timelines[i].apply(skeleton, lastTime, time, events, 1);
-	}
-
-	/** Poses the skeleton at the specified time for this animation mixed with the current pose.
-	 * @param alpha The amount of this animation that affects the current pose. */
-	public function mix (skeleton:Skeleton, lastTime:Number, time:Number, loop:Boolean, events:Vector.<Event>, alpha:Number) : void {
-		if (skeleton == null) throw new ArgumentError("skeleton cannot be null.");
-
-		if (loop && duration != 0) {
-			time %= duration;
-			if (lastTime > 0) lastTime %= duration;
-		}
-
-		for (var i:int = 0, n:int = timelines.length; i < n; i++)
-			timelines[i].apply(skeleton, lastTime, time, events, alpha);
-	}
-
-	public function get name () : String {
-		return _name;
-	}
-
-	public function toString () : String {
-		return _name;
-	}
-
-	/** @param target After the first and before the last entry. */
-	static public function binarySearch (values:Vector.<Number>, target:Number, step:int) : int {
-		var low:int = 0;
-		var high:int = values.length / step - 2;
-		if (high == 0)
-			return step;
-		var current:int = high >>> 1;
-		while (true) {
-			if (values[int((current + 1) * step)] <= target)
-				low = current + 1;
-			else
-				high = current;
-			if (low == high)
-				return (low + 1) * step;
-			current = (low + high) >>> 1;
-		}
-		return 0; // Can't happen.
-	}
-
-	/** @param target After the first and before the last entry. */
-	static public function binarySearch1 (values:Vector.<Number>, target:Number) : int {
-		var low:int = 0;
-		var high:int = values.length - 2;
-		if (high == 0)
-			return 1;
-		var current:int = high >>> 1;
-		while (true) {
-			if (values[int(current + 1)] <= target)
-				low = current + 1;
-			else
-				high = current;
-			if (low == high)
-				return low + 1;
-			current = (low + high) >>> 1;
-		}
-		return 0; // Can't happen.
-	}
-	
-	static public function linearSearch (values:Vector.<Number>, target:Number, step:int) : int {
-		for (var i:int = 0, last:int = values.length - step; i <= last; i += step)
-			if (values[i] > target)
-				return i;
-		return -1;
-	}
-}
-
+package spine.animation {
+import spine.Event;
+import spine.Skeleton;
+
+public class Animation {
+	internal var _name:String;
+	private var _timelines:Vector.<Timeline>;
+	public var duration:Number;
+
+	public function Animation (name:String, timelines:Vector.<Timeline>, duration:Number) {
+		if (name == null) throw new ArgumentError("name cannot be null.");
+		if (timelines == null) throw new ArgumentError("timelines cannot be null.");
+		_name = name;
+		_timelines = timelines;
+		this.duration = duration;
+	}
+
+	public function get timelines () : Vector.<Timeline> {
+		return _timelines;
+	}
+
+	/** Poses the skeleton at the specified time for this animation. */
+	public function apply (skeleton:Skeleton, lastTime:Number, time:Number, loop:Boolean, events:Vector.<Event>) : void {
+		if (skeleton == null) throw new ArgumentError("skeleton cannot be null.");
+
+		if (loop && duration != 0) {
+			time %= duration;
+			if (lastTime > 0) lastTime %= duration;
+		}
+
+		for (var i:int = 0, n:int = timelines.length; i < n; i++)
+			timelines[i].apply(skeleton, lastTime, time, events, 1);
+	}
+
+	/** Poses the skeleton at the specified time for this animation mixed with the current pose.
+	 * @param alpha The amount of this animation that affects the current pose. */
+	public function mix (skeleton:Skeleton, lastTime:Number, time:Number, loop:Boolean, events:Vector.<Event>, alpha:Number) : void {
+		if (skeleton == null) throw new ArgumentError("skeleton cannot be null.");
+
+		if (loop && duration != 0) {
+			time %= duration;
+			if (lastTime > 0) lastTime %= duration;
+		}
+
+		for (var i:int = 0, n:int = timelines.length; i < n; i++)
+			timelines[i].apply(skeleton, lastTime, time, events, alpha);
+	}
+
+	public function get name () : String {
+		return _name;
+	}
+
+	public function toString () : String {
+		return _name;
+	}
+
+	/** @param target After the first and before the last entry. */
+	static public function binarySearch (values:Vector.<Number>, target:Number, step:int) : int {
+		var low:int = 0;
+		var high:int = values.length / step - 2;
+		if (high == 0)
+			return step;
+		var current:int = high >>> 1;
+		while (true) {
+			if (values[int((current + 1) * step)] <= target)
+				low = current + 1;
+			else
+				high = current;
+			if (low == high)
+				return (low + 1) * step;
+			current = (low + high) >>> 1;
+		}
+		return 0; // Can't happen.
+	}
+
+	/** @param target After the first and before the last entry. */
+	static public function binarySearch1 (values:Vector.<Number>, target:Number) : int {
+		var low:int = 0;
+		var high:int = values.length - 2;
+		if (high == 0)
+			return 1;
+		var current:int = high >>> 1;
+		while (true) {
+			if (values[int(current + 1)] <= target)
+				low = current + 1;
+			else
+				high = current;
+			if (low == high)
+				return low + 1;
+			current = (low + high) >>> 1;
+		}
+		return 0; // Can't happen.
+	}
+	
+	static public function linearSearch (values:Vector.<Number>, target:Number, step:int) : int {
+		for (var i:int = 0, last:int = values.length - step; i <= last; i += step)
+			if (values[i] > target)
+				return i;
+		return -1;
+	}
+}
+
 }

+ 238 - 239
spine-as3/spine-as3/src/spine/animation/AnimationState.as

@@ -1,242 +1,241 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-
-import spine.Event;
-import spine.Skeleton;
-
-public class AnimationState {
-	private var _data:AnimationStateData;
-	private var _tracks:Vector.<TrackEntry> = new Vector.<TrackEntry>();
-	private var _events:Vector.<Event> = new Vector.<Event>();
-	public var onStart:Listeners = new Listeners();
-	public var onEnd:Listeners = new Listeners();
-	public var onComplete:Listeners = new Listeners();
-	public var onEvent:Listeners = new Listeners();
-	public var timeScale:Number = 1;
-
-	public function AnimationState (data:AnimationStateData) {
-		if (!data) throw new ArgumentError("data cannot be null.");
-		_data = data;
-	}
-
-	public function update (delta:Number) : void {
-		delta *= timeScale;
-		for (var i:int = 0; i < _tracks.length; i++) {
-			var current:TrackEntry = _tracks[i];
-			if (!current) continue;
-			
-			current.time += delta * current.timeScale;
-			if (current.previous) {
-				var previousDelta:Number = delta * current.previous.timeScale;
-				current.previous.time += previousDelta;
-				current.mixTime += previousDelta;
-			}
-
-			var next:TrackEntry = current.next;
-			if (next) {
-				next.time = current.lastTime - next.delay;
-				if (next.time >= 0) setCurrent(i, next);
-			} else {
-				// End non-looping animation when it reaches its end time and there is no next entry.
-				if (!current.loop && current.lastTime >= current.endTime) clearTrack(i);
-			}
-		}
-	}
-
-	public function apply (skeleton:Skeleton) : void {
-		for (var i:int = 0; i < _tracks.length; i++) {
-			var current:TrackEntry = _tracks[i];
-			if (!current) continue;
-			
-			_events.length = 0;
-			
-			var time:Number = current.time;
-			var lastTime:Number = current.lastTime;
-			var endTime:Number = current.endTime;
-			var loop:Boolean = current.loop;
-			if (!loop && time > endTime) time = endTime;
-			
-			var previous:TrackEntry = current.previous;
-			if (!previous) {
-				if (current.mix == 1)
-					current.animation.apply(skeleton, current.lastTime, time, loop, _events);
-				else
-					current.animation.mix(skeleton, current.lastTime, time, loop, _events, current.mix);
-			} else {
-				var previousTime:Number = previous.time;
-				if (!previous.loop && previousTime > previous.endTime) previousTime = previous.endTime;
-				previous.animation.apply(skeleton, previousTime, previousTime, previous.loop, null);
-				
-				var alpha:Number = current.mixTime / current.mixDuration * current.mix;
-				if (alpha >= 1) {
-					alpha = 1;
-					current.previous = null;
-				}
-				current.animation.mix(skeleton, current.lastTime, time, loop, _events, alpha);
-			}
-			
-			for each (var event:Event in _events) {
-				if (current.onEvent != null) current.onEvent(i, event);
-				onEvent.invoke(i, event);
-			}
-
-			// Check if completed the animation or a loop iteration.
-			if (loop ? (lastTime % endTime > time % endTime) : (lastTime < endTime && time >= endTime)) {
-				var count:int = (int)(time / endTime);
-				if (current.onComplete != null) current.onComplete(i, count);
-				onComplete.invoke(i, count);
-			}
-
-			current.lastTime = current.time;
-		}
-	}
-
-	public function clearTracks () : void {
-		for (var i:int = 0, n:int = _tracks.length; i < n; i++)
-			clearTrack(i);
-		_tracks.length = 0; 
-	}
-	
-	public function clearTrack (trackIndex:int) : void {
-		if (trackIndex >= _tracks.length) return;
-		var current:TrackEntry = _tracks[trackIndex];
-		if (!current) return;
-
-		if (current.onEnd != null) current.onEnd(trackIndex);
-		onEnd.invoke(trackIndex);
-
-		_tracks[trackIndex] = null;
-	}
-	
-	private function expandToIndex (index:int) : TrackEntry {
-		if (index < _tracks.length) return _tracks[index];
-		while (index >= _tracks.length)
-			_tracks[_tracks.length] = null;
-		return null;
-	}
-	
-	private function setCurrent (index:int, entry:TrackEntry) : void {
-		var current:TrackEntry = expandToIndex(index);
-		if (current) {
-			var previous:TrackEntry = current.previous;
-			current.previous = null;
-
-			if (current.onEnd != null) current.onEnd(index);
-			onEnd.invoke(index);
-
-			entry.mixDuration = _data.getMix(current.animation, entry.animation);
-			if (entry.mixDuration > 0) {
-				entry.mixTime = 0;
-				// If a mix is in progress, mix from the closest animation.
-				if (previous != null && current.mixTime / current.mixDuration < 0.5) {
-					entry.previous = previous;
-					previous = current;
-				} else
-					entry.previous = current;
-			}
-		}
-		
-		_tracks[index] = entry;
-
-		if (entry.onStart != null) entry.onStart(index);
-		onStart.invoke(index);
-	}
-	
-	public function setAnimationByName (trackIndex:int, animationName:String, loop:Boolean) : TrackEntry {
-		var animation:Animation = _data._skeletonData.findAnimation(animationName);
-		if (!animation) throw new ArgumentError("Animation not found: " + animationName);
-		return setAnimation(trackIndex, animation, loop);
-	}
-	
-	/** Set the current animation. Any queued animations are cleared. */
-	public function setAnimation (trackIndex:int, animation:Animation, loop:Boolean) : TrackEntry {
-		var entry:TrackEntry = new TrackEntry();
-		entry.animation = animation;
-		entry.loop = loop;
-		entry.endTime = animation.duration;
-		setCurrent(trackIndex, entry);
-		return entry;
-	}
-	
-	public function addAnimationByName (trackIndex:int, animationName:String, loop:Boolean, delay:Number) : TrackEntry {
-		var animation:Animation = _data._skeletonData.findAnimation(animationName);
-		if (!animation) throw new ArgumentError("Animation not found: " + animationName);
-		return addAnimation(trackIndex, animation, loop, delay);
-	}
-	
-	/** Adds an animation to be played delay seconds after the current or last queued animation.
-	 * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */
-	public function addAnimation (trackIndex:int, animation:Animation, loop:Boolean, delay:Number) : TrackEntry {
-		var entry:TrackEntry = new TrackEntry();
-		entry.animation = animation;
-		entry.loop = loop;
-		entry.endTime = animation.duration;
-		
-		var last:TrackEntry = expandToIndex(trackIndex);
-		if (last) {
-			while (last.next)
-				last = last.next;
-			last.next = entry;
-		} else
-			_tracks[trackIndex] = entry;
-		
-		if (delay <= 0) {
-			if (last)
-				delay += last.endTime - _data.getMix(last.animation, animation);
-			else
-				delay = 0;
-		}
-		entry.delay = delay;
-		
-		return entry;
-	}
-	
-	/** May be null. */
-	public function getCurrent (trackIndex:int) : TrackEntry {
-		if (trackIndex >= _tracks.length) return null;
-		return _tracks[trackIndex];
-	}
-
-	public function toString () : String {
-		var buffer:String = "";
-		for each (var entry:TrackEntry in _tracks) {
-			if (!entry) continue;
-			if (buffer.length > 0) buffer += ", ";
-			buffer += entry.toString();
-		}
-		if (buffer.length == 0) return "<none>";
-		return buffer;
-	}
-}
-
+package spine.animation {
+
+import spine.Event;
+import spine.Skeleton;
+
+public class AnimationState {
+	private var _data:AnimationStateData;
+	private var _tracks:Vector.<TrackEntry> = new Vector.<TrackEntry>();
+	private var _events:Vector.<Event> = new Vector.<Event>();
+	public var onStart:Listeners = new Listeners();
+	public var onEnd:Listeners = new Listeners();
+	public var onComplete:Listeners = new Listeners();
+	public var onEvent:Listeners = new Listeners();
+	public var timeScale:Number = 1;
+
+	public function AnimationState (data:AnimationStateData) {
+		if (!data) throw new ArgumentError("data cannot be null.");
+		_data = data;
+	}
+
+	public function update (delta:Number) : void {
+		delta *= timeScale;
+		for (var i:int = 0; i < _tracks.length; i++) {
+			var current:TrackEntry = _tracks[i];
+			if (!current) continue;
+			
+			current.time += delta * current.timeScale;
+			if (current.previous) {
+				var previousDelta:Number = delta * current.previous.timeScale;
+				current.previous.time += previousDelta;
+				current.mixTime += previousDelta;
+			}
+
+			var next:TrackEntry = current.next;
+			if (next) {
+				next.time = current.lastTime - next.delay;
+				if (next.time >= 0) setCurrent(i, next);
+			} else {
+				// End non-looping animation when it reaches its end time and there is no next entry.
+				if (!current.loop && current.lastTime >= current.endTime) clearTrack(i);
+			}
+		}
+	}
+
+	public function apply (skeleton:Skeleton) : void {
+		for (var i:int = 0; i < _tracks.length; i++) {
+			var current:TrackEntry = _tracks[i];
+			if (!current) continue;
+			
+			_events.length = 0;
+			
+			var time:Number = current.time;
+			var lastTime:Number = current.lastTime;
+			var endTime:Number = current.endTime;
+			var loop:Boolean = current.loop;
+			if (!loop && time > endTime) time = endTime;
+			
+			var previous:TrackEntry = current.previous;
+			if (!previous) {
+				if (current.mix == 1)
+					current.animation.apply(skeleton, current.lastTime, time, loop, _events);
+				else
+					current.animation.mix(skeleton, current.lastTime, time, loop, _events, current.mix);
+			} else {
+				var previousTime:Number = previous.time;
+				if (!previous.loop && previousTime > previous.endTime) previousTime = previous.endTime;
+				previous.animation.apply(skeleton, previousTime, previousTime, previous.loop, null);
+				
+				var alpha:Number = current.mixTime / current.mixDuration * current.mix;
+				if (alpha >= 1) {
+					alpha = 1;
+					current.previous = null;
+				}
+				current.animation.mix(skeleton, current.lastTime, time, loop, _events, alpha);
+			}
+			
+			for each (var event:Event in _events) {
+				if (current.onEvent != null) current.onEvent(i, event);
+				onEvent.invoke(i, event);
+			}
+
+			// Check if completed the animation or a loop iteration.
+			if (loop ? (lastTime % endTime > time % endTime) : (lastTime < endTime && time >= endTime)) {
+				var count:int = (int)(time / endTime);
+				if (current.onComplete != null) current.onComplete(i, count);
+				onComplete.invoke(i, count);
+			}
+
+			current.lastTime = current.time;
+		}
+	}
+
+	public function clearTracks () : void {
+		for (var i:int = 0, n:int = _tracks.length; i < n; i++)
+			clearTrack(i);
+		_tracks.length = 0; 
+	}
+	
+	public function clearTrack (trackIndex:int) : void {
+		if (trackIndex >= _tracks.length) return;
+		var current:TrackEntry = _tracks[trackIndex];
+		if (!current) return;
+
+		if (current.onEnd != null) current.onEnd(trackIndex);
+		onEnd.invoke(trackIndex);
+
+		_tracks[trackIndex] = null;
+	}
+	
+	private function expandToIndex (index:int) : TrackEntry {
+		if (index < _tracks.length) return _tracks[index];
+		while (index >= _tracks.length)
+			_tracks[_tracks.length] = null;
+		return null;
+	}
+	
+	private function setCurrent (index:int, entry:TrackEntry) : void {
+		var current:TrackEntry = expandToIndex(index);
+		if (current) {
+			var previous:TrackEntry = current.previous;
+			current.previous = null;
+
+			if (current.onEnd != null) current.onEnd(index);
+			onEnd.invoke(index);
+
+			entry.mixDuration = _data.getMix(current.animation, entry.animation);
+			if (entry.mixDuration > 0) {
+				entry.mixTime = 0;
+				// If a mix is in progress, mix from the closest animation.
+				if (previous != null && current.mixTime / current.mixDuration < 0.5) {
+					entry.previous = previous;
+					previous = current;
+				} else
+					entry.previous = current;
+			}
+		}
+		
+		_tracks[index] = entry;
+
+		if (entry.onStart != null) entry.onStart(index);
+		onStart.invoke(index);
+	}
+	
+	public function setAnimationByName (trackIndex:int, animationName:String, loop:Boolean) : TrackEntry {
+		var animation:Animation = _data._skeletonData.findAnimation(animationName);
+		if (!animation) throw new ArgumentError("Animation not found: " + animationName);
+		return setAnimation(trackIndex, animation, loop);
+	}
+	
+	/** Set the current animation. Any queued animations are cleared. */
+	public function setAnimation (trackIndex:int, animation:Animation, loop:Boolean) : TrackEntry {
+		var entry:TrackEntry = new TrackEntry();
+		entry.animation = animation;
+		entry.loop = loop;
+		entry.endTime = animation.duration;
+		setCurrent(trackIndex, entry);
+		return entry;
+	}
+	
+	public function addAnimationByName (trackIndex:int, animationName:String, loop:Boolean, delay:Number) : TrackEntry {
+		var animation:Animation = _data._skeletonData.findAnimation(animationName);
+		if (!animation) throw new ArgumentError("Animation not found: " + animationName);
+		return addAnimation(trackIndex, animation, loop, delay);
+	}
+	
+	/** Adds an animation to be played delay seconds after the current or last queued animation.
+	 * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */
+	public function addAnimation (trackIndex:int, animation:Animation, loop:Boolean, delay:Number) : TrackEntry {
+		var entry:TrackEntry = new TrackEntry();
+		entry.animation = animation;
+		entry.loop = loop;
+		entry.endTime = animation.duration;
+		
+		var last:TrackEntry = expandToIndex(trackIndex);
+		if (last) {
+			while (last.next)
+				last = last.next;
+			last.next = entry;
+		} else
+			_tracks[trackIndex] = entry;
+		
+		if (delay <= 0) {
+			if (last)
+				delay += last.endTime - _data.getMix(last.animation, animation);
+			else
+				delay = 0;
+		}
+		entry.delay = delay;
+		
+		return entry;
+	}
+	
+	/** May be null. */
+	public function getCurrent (trackIndex:int) : TrackEntry {
+		if (trackIndex >= _tracks.length) return null;
+		return _tracks[trackIndex];
+	}
+
+	public function toString () : String {
+		var buffer:String = "";
+		for each (var entry:TrackEntry in _tracks) {
+			if (!entry) continue;
+			if (buffer.length > 0) buffer += ", ";
+			buffer += entry.toString();
+		}
+		if (buffer.length == 0) return "<none>";
+		return buffer;
+	}
+}
+
 }

+ 65 - 66
spine-as3/spine-as3/src/spine/animation/AnimationStateData.as

@@ -1,69 +1,68 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-import spine.SkeletonData;
-
-public class AnimationStateData {
-	internal var _skeletonData:SkeletonData;
-	private var animationToMixTime:Object = new Object();
-	public var defaultMix:Number = 0;
-
-	public function AnimationStateData (skeletonData:SkeletonData) {
-		_skeletonData = skeletonData;
-	}
-
-	public function get skeletonData () : SkeletonData {
-		return _skeletonData;
-	}
-
-	public function setMixByName (fromName:String, toName:String, duration:Number) : void {
-		var from:Animation = _skeletonData.findAnimation(fromName);
-		if (from == null) throw new ArgumentError("Animation not found: " + fromName);
-		var to:Animation = _skeletonData.findAnimation(toName);
-		if (to == null) throw new ArgumentError("Animation not found: " + toName);
-		setMix(from, to, duration);
-	}
-
-	public function setMix (from:Animation, to:Animation, duration:Number) : void {
-		if (from == null) throw new ArgumentError("from cannot be null.");
-		if (to == null) throw new ArgumentError("to cannot be null.");
-		animationToMixTime[from.name + ":" + to.name] = duration;
-	}
-
-	public function getMix (from:Animation, to:Animation) : Number {
-		var time:Object = animationToMixTime[from.name + ":" + to.name];
-		if (time == null) return defaultMix;
-		return time as Number;
-	}
-}
-
+package spine.animation {
+import spine.SkeletonData;
+
+public class AnimationStateData {
+	internal var _skeletonData:SkeletonData;
+	private var animationToMixTime:Object = new Object();
+	public var defaultMix:Number = 0;
+
+	public function AnimationStateData (skeletonData:SkeletonData) {
+		_skeletonData = skeletonData;
+	}
+
+	public function get skeletonData () : SkeletonData {
+		return _skeletonData;
+	}
+
+	public function setMixByName (fromName:String, toName:String, duration:Number) : void {
+		var from:Animation = _skeletonData.findAnimation(fromName);
+		if (from == null) throw new ArgumentError("Animation not found: " + fromName);
+		var to:Animation = _skeletonData.findAnimation(toName);
+		if (to == null) throw new ArgumentError("Animation not found: " + toName);
+		setMix(from, to, duration);
+	}
+
+	public function setMix (from:Animation, to:Animation, duration:Number) : void {
+		if (from == null) throw new ArgumentError("from cannot be null.");
+		if (to == null) throw new ArgumentError("to cannot be null.");
+		animationToMixTime[from.name + ":" + to.name] = duration;
+	}
+
+	public function getMix (from:Animation, to:Animation) : Number {
+		var time:Object = animationToMixTime[from.name + ":" + to.name];
+		if (time == null) return defaultMix;
+		return time as Number;
+	}
+}
+
 }

+ 67 - 68
spine-as3/spine-as3/src/spine/animation/AttachmentTimeline.as

@@ -1,71 +1,70 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-import spine.Event;
-import spine.Skeleton;
-
-public class AttachmentTimeline implements Timeline {
-	public var slotIndex:int;
-	public var frames:Vector.<Number>; // time, ...
-	public var attachmentNames:Vector.<String>;
-
-	public function AttachmentTimeline (frameCount:int) {
-		frames = new Vector.<Number>(frameCount, true);
-		attachmentNames = new Vector.<String>(frameCount, true);
-	}
-
-	public function get frameCount () : int {
-		return frames.length;
-	}
-
-	/** Sets the time and value of the specified keyframe. */
-	public function setFrame (frameIndex:int, time:Number, attachmentName:String) : void {
-		frames[frameIndex] = time;
-		attachmentNames[frameIndex] = attachmentName;
-	}
-
-	public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
-		var frames:Vector.<Number> = this.frames;
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var frameIndex:int;
-		if (time >= frames[frames.length - 1]) // Time is after last frame.
-			frameIndex = frames.length - 1;
-		else
-			frameIndex = Animation.binarySearch(frames, time, 1) - 1;
-
-		var attachmentName:String = attachmentNames[frameIndex];
-		skeleton.slots[slotIndex].attachment = attachmentName == null ? null : skeleton.getAttachmentForSlotIndex(slotIndex, attachmentName);
-	}
-}
-
+package spine.animation {
+import spine.Event;
+import spine.Skeleton;
+
+public class AttachmentTimeline implements Timeline {
+	public var slotIndex:int;
+	public var frames:Vector.<Number>; // time, ...
+	public var attachmentNames:Vector.<String>;
+
+	public function AttachmentTimeline (frameCount:int) {
+		frames = new Vector.<Number>(frameCount, true);
+		attachmentNames = new Vector.<String>(frameCount, true);
+	}
+
+	public function get frameCount () : int {
+		return frames.length;
+	}
+
+	/** Sets the time and value of the specified keyframe. */
+	public function setFrame (frameIndex:int, time:Number, attachmentName:String) : void {
+		frames[frameIndex] = time;
+		attachmentNames[frameIndex] = attachmentName;
+	}
+
+	public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
+		var frames:Vector.<Number> = this.frames;
+		if (time < frames[0]) return; // Time is before first frame.
+
+		var frameIndex:int;
+		if (time >= frames[frames.length - 1]) // Time is after last frame.
+			frameIndex = frames.length - 1;
+		else
+			frameIndex = Animation.binarySearch(frames, time, 1) - 1;
+
+		var attachmentName:String = attachmentNames[frameIndex];
+		skeleton.slots[slotIndex].attachment = attachmentName == null ? null : skeleton.getAttachmentForSlotIndex(slotIndex, attachmentName);
+	}
+}
+
 }

+ 99 - 100
spine-as3/spine-as3/src/spine/animation/ColorTimeline.as

@@ -1,103 +1,102 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-import spine.Event;
-import spine.Skeleton;
-import spine.Slot;
-
-public class ColorTimeline extends CurveTimeline {
-	static public const ENTRIES:int = 5;
-	static internal const PREV_TIME:int = -5, PREV_R:int = -4, PREV_G:int = -3, PREV_B:int = -2, PREV_A:int = -1;
-	static internal const R:int = 1, G:int = 2, B:int = 3, A:int = 4;
-
-	public var slotIndex:int;
-	public var frames:Vector.<Number>; // time, r, g, b, a, ...
-
-	public function ColorTimeline (frameCount:int) {
-		super(frameCount);
-		frames = new Vector.<Number>(frameCount * 5, true);
-	}
-
-	/** Sets the time and value of the specified keyframe. */
-	public function setFrame (frameIndex:int, time:Number, r:Number, g:Number, b:Number, a:Number) : void {
-		frameIndex *= ENTRIES;
-		frames[frameIndex] = time;
-		frames[int(frameIndex + R)] = r;
-		frames[int(frameIndex + G)] = g;
-		frames[int(frameIndex + B)] = b;
-		frames[int(frameIndex + A)] = a;
-	}
-
-	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
-		if (time < frames[0])
-			return; // Time is before first frame.
-
-		var r:Number, g:Number, b:Number, a:Number;
-		if (time >= frames[int(frames.length - ENTRIES)]) {
-			// Time is after last frame.
-			var i:int = frames.length;
-			r = frames[int(i + PREV_R)];
-			g = frames[int(i + PREV_G)];
-			b = frames[int(i + PREV_B)];
-			a = frames[int(i + PREV_A)];
-		} else {
-			// Interpolate between the previous frame and the current frame.
-			var frame:int = Animation.binarySearch(frames, time, ENTRIES);
-			r = frames[int(frame + PREV_R)];
-			g = frames[int(frame + PREV_G)];
-			b = frames[int(frame + PREV_B)];
-			a = frames[int(frame + PREV_A)];
-			var frameTime:Number = frames[frame];
-			var percent:Number = getCurvePercent(frame / ENTRIES - 1,
-					1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
-
-			r += (frames[frame + R] - r) * percent;
-			g += (frames[frame + G] - g) * percent;
-			b += (frames[frame + B] - b) * percent;
-			a += (frames[frame + A] - a) * percent;
-		}
-		var slot:Slot = skeleton.slots[slotIndex];
-		if (alpha < 1) {
-			slot.r += (r - slot.r) * alpha;
-			slot.g += (g - slot.g) * alpha;
-			slot.b += (b - slot.b) * alpha;
-			slot.a += (a - slot.a) * alpha;
-		} else {
-			slot.r = r;
-			slot.g = g;
-			slot.b = b;
-			slot.a = a;
-		}
-	}
-}
-
+package spine.animation {
+import spine.Event;
+import spine.Skeleton;
+import spine.Slot;
+
+public class ColorTimeline extends CurveTimeline {
+	static public const ENTRIES:int = 5;
+	static internal const PREV_TIME:int = -5, PREV_R:int = -4, PREV_G:int = -3, PREV_B:int = -2, PREV_A:int = -1;
+	static internal const R:int = 1, G:int = 2, B:int = 3, A:int = 4;
+
+	public var slotIndex:int;
+	public var frames:Vector.<Number>; // time, r, g, b, a, ...
+
+	public function ColorTimeline (frameCount:int) {
+		super(frameCount);
+		frames = new Vector.<Number>(frameCount * 5, true);
+	}
+
+	/** Sets the time and value of the specified keyframe. */
+	public function setFrame (frameIndex:int, time:Number, r:Number, g:Number, b:Number, a:Number) : void {
+		frameIndex *= ENTRIES;
+		frames[frameIndex] = time;
+		frames[int(frameIndex + R)] = r;
+		frames[int(frameIndex + G)] = g;
+		frames[int(frameIndex + B)] = b;
+		frames[int(frameIndex + A)] = a;
+	}
+
+	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
+		if (time < frames[0])
+			return; // Time is before first frame.
+
+		var r:Number, g:Number, b:Number, a:Number;
+		if (time >= frames[int(frames.length - ENTRIES)]) {
+			// Time is after last frame.
+			var i:int = frames.length;
+			r = frames[int(i + PREV_R)];
+			g = frames[int(i + PREV_G)];
+			b = frames[int(i + PREV_B)];
+			a = frames[int(i + PREV_A)];
+		} else {
+			// Interpolate between the previous frame and the current frame.
+			var frame:int = Animation.binarySearch(frames, time, ENTRIES);
+			r = frames[int(frame + PREV_R)];
+			g = frames[int(frame + PREV_G)];
+			b = frames[int(frame + PREV_B)];
+			a = frames[int(frame + PREV_A)];
+			var frameTime:Number = frames[frame];
+			var percent:Number = getCurvePercent(frame / ENTRIES - 1,
+					1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
+
+			r += (frames[frame + R] - r) * percent;
+			g += (frames[frame + G] - g) * percent;
+			b += (frames[frame + B] - b) * percent;
+			a += (frames[frame + A] - a) * percent;
+		}
+		var slot:Slot = skeleton.slots[slotIndex];
+		if (alpha < 1) {
+			slot.r += (r - slot.r) * alpha;
+			slot.g += (g - slot.g) * alpha;
+			slot.b += (b - slot.b) * alpha;
+			slot.a += (a - slot.a) * alpha;
+		} else {
+			slot.r = r;
+			slot.g = g;
+			slot.b = b;
+			slot.a = a;
+		}
+	}
+}
+
 }

+ 115 - 116
spine-as3/spine-as3/src/spine/animation/CurveTimeline.as

@@ -1,119 +1,118 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-	import spine.MathUtils;
-import spine.Event;
-import spine.Skeleton;
-
-/** Base class for frames that use an interpolation bezier curve. */
-public class CurveTimeline implements Timeline {
-	static private const LINEAR:Number = 0;
-	static private const STEPPED:Number = 1;
-	static private const BEZIER:Number = 2;	
-	static private const BEZIER_SIZE:int = 10 * 2 - 1;
-
-	private var curves:Vector.<Number>; // type, x, y, ...
-
-	public function CurveTimeline (frameCount:int) {
-		curves = new Vector.<Number>((frameCount - 1) * BEZIER_SIZE, true);
-	}
-
-	public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
-	}
-
-	public function get frameCount () : int {
-		return curves.length / BEZIER_SIZE + 1;
-	}
-
-	public function setLinear (frameIndex:int) : void {
-		curves[int(frameIndex * BEZIER_SIZE)] = LINEAR;
-	}
-
-	public function setStepped (frameIndex:int) : void {
-		curves[int(frameIndex * BEZIER_SIZE)] = STEPPED;
-	}
-
-	/** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next.
-	 * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of
-	 * the difference between the keyframe's values. */
-	public function setCurve (frameIndex:int, cx1:Number, cy1:Number, cx2:Number, cy2:Number) : void {
-		var tmpx:Number = (-cx1 * 2 + cx2) * 0.03, tmpy:Number = (-cy1 * 2 + cy2) * 0.03;
-		var dddfx:Number = ((cx1 - cx2) * 3 + 1) * 0.006, dddfy:Number = ((cy1 - cy2) * 3 + 1) * 0.006;
-		var ddfx:Number = tmpx * 2 + dddfx, ddfy:Number = tmpy * 2 + dddfy;
-		var dfx:Number = cx1 * 0.3 + tmpx + dddfx * 0.16666667, dfy:Number = cy1 * 0.3 + tmpy + dddfy * 0.16666667;
-
-		var i:int = frameIndex * BEZIER_SIZE;
-		var curves:Vector.<Number> = this.curves;
-		curves[int(i++)] = BEZIER;
-
-		var x:Number = dfx, y:Number = dfy;
-		for (var n:int = i + BEZIER_SIZE - 1; i < n; i += 2) {
-			curves[i] = x;
-			curves[int(i + 1)] = y;
-			dfx += ddfx;
-			dfy += ddfy;
-			ddfx += dddfx;
-			ddfy += dddfy;
-			x += dfx;
-			y += dfy;
-		}
-	}
-
-	public function getCurvePercent (frameIndex:int, percent:Number) : Number {
-		percent = MathUtils.clamp(percent, 0, 1);
-		var curves:Vector.<Number> = this.curves;
-		var i:int = frameIndex * BEZIER_SIZE;
-		var type:Number = curves[i];
-		if (type == LINEAR) return percent;
-		if (type == STEPPED) return 0;
-		i++;
-		var x:Number = 0;
-		for (var start:int = i, n:int = i + BEZIER_SIZE - 1; i < n; i += 2) {
-			x = curves[i];
-			if (x >= percent) {
-				var prevX:Number, prevY:Number;
-				if (i == start) {
-					prevX = 0;
-					prevY = 0;
-				} else {
-					prevX = curves[int(i - 2)];
-					prevY = curves[int(i - 1)];
-				}
-				return prevY + (curves[int(i + 1)] - prevY) * (percent - prevX) / (x - prevX);
-			}
-		}
-		var y:Number = curves[int(i - 1)];
-		return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1.
-	}
-}
-
+package spine.animation {
+	import spine.MathUtils;
+import spine.Event;
+import spine.Skeleton;
+
+/** Base class for frames that use an interpolation bezier curve. */
+public class CurveTimeline implements Timeline {
+	static private const LINEAR:Number = 0;
+	static private const STEPPED:Number = 1;
+	static private const BEZIER:Number = 2;	
+	static private const BEZIER_SIZE:int = 10 * 2 - 1;
+
+	private var curves:Vector.<Number>; // type, x, y, ...
+
+	public function CurveTimeline (frameCount:int) {
+		curves = new Vector.<Number>((frameCount - 1) * BEZIER_SIZE, true);
+	}
+
+	public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
+	}
+
+	public function get frameCount () : int {
+		return curves.length / BEZIER_SIZE + 1;
+	}
+
+	public function setLinear (frameIndex:int) : void {
+		curves[int(frameIndex * BEZIER_SIZE)] = LINEAR;
+	}
+
+	public function setStepped (frameIndex:int) : void {
+		curves[int(frameIndex * BEZIER_SIZE)] = STEPPED;
+	}
+
+	/** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next.
+	 * cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of
+	 * the difference between the keyframe's values. */
+	public function setCurve (frameIndex:int, cx1:Number, cy1:Number, cx2:Number, cy2:Number) : void {
+		var tmpx:Number = (-cx1 * 2 + cx2) * 0.03, tmpy:Number = (-cy1 * 2 + cy2) * 0.03;
+		var dddfx:Number = ((cx1 - cx2) * 3 + 1) * 0.006, dddfy:Number = ((cy1 - cy2) * 3 + 1) * 0.006;
+		var ddfx:Number = tmpx * 2 + dddfx, ddfy:Number = tmpy * 2 + dddfy;
+		var dfx:Number = cx1 * 0.3 + tmpx + dddfx * 0.16666667, dfy:Number = cy1 * 0.3 + tmpy + dddfy * 0.16666667;
+
+		var i:int = frameIndex * BEZIER_SIZE;
+		var curves:Vector.<Number> = this.curves;
+		curves[int(i++)] = BEZIER;
+
+		var x:Number = dfx, y:Number = dfy;
+		for (var n:int = i + BEZIER_SIZE - 1; i < n; i += 2) {
+			curves[i] = x;
+			curves[int(i + 1)] = y;
+			dfx += ddfx;
+			dfy += ddfy;
+			ddfx += dddfx;
+			ddfy += dddfy;
+			x += dfx;
+			y += dfy;
+		}
+	}
+
+	public function getCurvePercent (frameIndex:int, percent:Number) : Number {
+		percent = MathUtils.clamp(percent, 0, 1);
+		var curves:Vector.<Number> = this.curves;
+		var i:int = frameIndex * BEZIER_SIZE;
+		var type:Number = curves[i];
+		if (type == LINEAR) return percent;
+		if (type == STEPPED) return 0;
+		i++;
+		var x:Number = 0;
+		for (var start:int = i, n:int = i + BEZIER_SIZE - 1; i < n; i += 2) {
+			x = curves[i];
+			if (x >= percent) {
+				var prevX:Number, prevY:Number;
+				if (i == start) {
+					prevX = 0;
+					prevY = 0;
+				} else {
+					prevX = curves[int(i - 2)];
+					prevY = curves[int(i - 1)];
+				}
+				return prevY + (curves[int(i + 1)] - prevY) * (percent - prevX) / (x - prevX);
+			}
+		}
+		var y:Number = curves[int(i - 1)];
+		return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1.
+	}
+}
+
 }

+ 102 - 103
spine-as3/spine-as3/src/spine/animation/DeformTimeline.as

@@ -1,106 +1,105 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-import spine.attachments.VertexAttachment;
-import spine.Event;
-import spine.Skeleton;
-import spine.Slot;
-
-public class DeformTimeline extends CurveTimeline {
-	public var slotIndex:int;
-	public var frames:Vector.<Number>;
-	public var frameVertices:Vector.<Vector.<Number>>;
-	public var attachment:VertexAttachment;
-
-	public function DeformTimeline (frameCount:int) {
-		super(frameCount);
-		frames = new Vector.<Number>(frameCount, true);
-		frameVertices = new Vector.<Vector.<Number>>(frameCount, true);
-	}
-
-	/** Sets the time and value of the specified keyframe. */
-	public function setFrame (frameIndex:int, time:Number, vertices:Vector.<Number>) : void {
-		frames[frameIndex] = time;
-		frameVertices[frameIndex] = vertices;
-	}
-
-	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
-		var slot:Slot = skeleton.slots[slotIndex];
-		var slotAttachment:VertexAttachment = slot.attachment as VertexAttachment;
-		if (!slotAttachment || !slotAttachment.applyDeform(attachment)) return;
-
-		var frames:Vector.<Number> = this.frames;
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var frameVertices:Vector.<Vector.<Number>> = this.frameVertices;
-		var vertexCount:int = frameVertices[0].length;
-
-		var vertices:Vector.<Number> = slot.attachmentVertices;
-		if (vertices.length != vertexCount) alpha = 1; // Don't mix from uninitialized slot vertices.
-		vertices.length = vertexCount;
-
-		var i:int;
-		if (time >= frames[frames.length - 1]) { // Time is after last frame.
-			var lastVertices:Vector.<Number> = frameVertices[int(frames.length - 1)];
-			if (alpha < 1) {
-				for (i = 0; i < vertexCount; i++)
-					vertices[i] += (lastVertices[i] - vertices[i]) * alpha;
-			} else {
-				for (i = 0; i < vertexCount; i++)
-					vertices[i] = lastVertices[i];
-			}
-			return;
-		}
-
-		// Interpolate between the previous frame and the current frame.
-		var frame:int = Animation.binarySearch1(frames, time);
-		var prevVertices:Vector.<Number> = frameVertices[int(frame - 1)];
-		var nextVertices:Vector.<Number> = frameVertices[frame];
-		var frameTime:Number = frames[frame];		
-		var percent:Number = getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime));		
-
-		var prev:Number;
-		if (alpha < 1) {
-			for (i = 0; i < vertexCount; i++) {
-				prev = prevVertices[i];
-				vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha;
-			}
-		} else {
-			for (i = 0; i < vertexCount; i++) {
-				prev = prevVertices[i];
-				vertices[i] = prev + (nextVertices[i] - prev) * percent;
-			}
-		}
-	}
-}
-
+package spine.animation {
+import spine.attachments.VertexAttachment;
+import spine.Event;
+import spine.Skeleton;
+import spine.Slot;
+
+public class DeformTimeline extends CurveTimeline {
+	public var slotIndex:int;
+	public var frames:Vector.<Number>;
+	public var frameVertices:Vector.<Vector.<Number>>;
+	public var attachment:VertexAttachment;
+
+	public function DeformTimeline (frameCount:int) {
+		super(frameCount);
+		frames = new Vector.<Number>(frameCount, true);
+		frameVertices = new Vector.<Vector.<Number>>(frameCount, true);
+	}
+
+	/** Sets the time and value of the specified keyframe. */
+	public function setFrame (frameIndex:int, time:Number, vertices:Vector.<Number>) : void {
+		frames[frameIndex] = time;
+		frameVertices[frameIndex] = vertices;
+	}
+
+	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
+		var slot:Slot = skeleton.slots[slotIndex];
+		var slotAttachment:VertexAttachment = slot.attachment as VertexAttachment;
+		if (!slotAttachment || !slotAttachment.applyDeform(attachment)) return;
+
+		var frames:Vector.<Number> = this.frames;
+		if (time < frames[0]) return; // Time is before first frame.
+
+		var frameVertices:Vector.<Vector.<Number>> = this.frameVertices;
+		var vertexCount:int = frameVertices[0].length;
+
+		var vertices:Vector.<Number> = slot.attachmentVertices;
+		if (vertices.length != vertexCount) alpha = 1; // Don't mix from uninitialized slot vertices.
+		vertices.length = vertexCount;
+
+		var i:int;
+		if (time >= frames[frames.length - 1]) { // Time is after last frame.
+			var lastVertices:Vector.<Number> = frameVertices[int(frames.length - 1)];
+			if (alpha < 1) {
+				for (i = 0; i < vertexCount; i++)
+					vertices[i] += (lastVertices[i] - vertices[i]) * alpha;
+			} else {
+				for (i = 0; i < vertexCount; i++)
+					vertices[i] = lastVertices[i];
+			}
+			return;
+		}
+
+		// Interpolate between the previous frame and the current frame.
+		var frame:int = Animation.binarySearch1(frames, time);
+		var prevVertices:Vector.<Number> = frameVertices[int(frame - 1)];
+		var nextVertices:Vector.<Number> = frameVertices[frame];
+		var frameTime:Number = frames[frame];		
+		var percent:Number = getCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime));		
+
+		var prev:Number;
+		if (alpha < 1) {
+			for (i = 0; i < vertexCount; i++) {
+				prev = prevVertices[i];
+				vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha;
+			}
+		} else {
+			for (i = 0; i < vertexCount; i++) {
+				prev = prevVertices[i];
+				vertices[i] = prev + (nextVertices[i] - prev) * percent;
+			}
+		}
+	}
+}
+
 }

+ 76 - 77
spine-as3/spine-as3/src/spine/animation/DrawOrderTimeline.as

@@ -1,80 +1,79 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-import spine.Event;
-import spine.Skeleton;
-import spine.Slot;
-
-public class DrawOrderTimeline implements Timeline {
-	public var frames:Vector.<Number>; // time, ...
-	public var drawOrders:Vector.<Vector.<int>>;
-
-	public function DrawOrderTimeline (frameCount:int) {
-		frames = new Vector.<Number>(frameCount, true);
-		drawOrders = new Vector.<Vector.<int>>(frameCount, true);
-	}
-
-	public function get frameCount () : int {
-		return frames.length;
-	}
-
-	/** Sets the time and value of the specified keyframe. */
-	public function setFrame (frameIndex:int, time:Number, drawOrder:Vector.<int>) : void {
-		frames[frameIndex] = time;
-		drawOrders[frameIndex] = drawOrder;
-	}
-
-	public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
-		if (time < frames[0])
-			return; // Time is before first frame.
-
-		var frameIndex:int;
-		if (time >= frames[int(frames.length - 1)]) // Time is after last frame.
-			frameIndex = frames.length - 1;
-		else
-			frameIndex = Animation.binarySearch1(frames, time) - 1;
-
-		var drawOrder:Vector.<Slot> = skeleton.drawOrder;
-		var slots:Vector.<Slot> = skeleton.slots;
-		var drawOrderToSetupIndex:Vector.<int> = drawOrders[frameIndex];
-		var i:int = 0;
-		if (!drawOrderToSetupIndex) {
-			for each (var slot:Slot in slots)
-				drawOrder[i++] = slot;
-		} else {
-			for each (var setupIndex:int in drawOrderToSetupIndex) 
-				drawOrder[i++] = slots[setupIndex];
-		}
-	}
-}
-
+package spine.animation {
+import spine.Event;
+import spine.Skeleton;
+import spine.Slot;
+
+public class DrawOrderTimeline implements Timeline {
+	public var frames:Vector.<Number>; // time, ...
+	public var drawOrders:Vector.<Vector.<int>>;
+
+	public function DrawOrderTimeline (frameCount:int) {
+		frames = new Vector.<Number>(frameCount, true);
+		drawOrders = new Vector.<Vector.<int>>(frameCount, true);
+	}
+
+	public function get frameCount () : int {
+		return frames.length;
+	}
+
+	/** Sets the time and value of the specified keyframe. */
+	public function setFrame (frameIndex:int, time:Number, drawOrder:Vector.<int>) : void {
+		frames[frameIndex] = time;
+		drawOrders[frameIndex] = drawOrder;
+	}
+
+	public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
+		if (time < frames[0])
+			return; // Time is before first frame.
+
+		var frameIndex:int;
+		if (time >= frames[int(frames.length - 1)]) // Time is after last frame.
+			frameIndex = frames.length - 1;
+		else
+			frameIndex = Animation.binarySearch1(frames, time) - 1;
+
+		var drawOrder:Vector.<Slot> = skeleton.drawOrder;
+		var slots:Vector.<Slot> = skeleton.slots;
+		var drawOrderToSetupIndex:Vector.<int> = drawOrders[frameIndex];
+		var i:int = 0;
+		if (!drawOrderToSetupIndex) {
+			for each (var slot:Slot in slots)
+				drawOrder[i++] = slot;
+		} else {
+			for each (var setupIndex:int in drawOrderToSetupIndex) 
+				drawOrder[i++] = slots[setupIndex];
+		}
+	}
+}
+
 }

+ 78 - 79
spine-as3/spine-as3/src/spine/animation/EventTimeline.as

@@ -1,82 +1,81 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-import spine.Event;
-import spine.Skeleton;
-
-public class EventTimeline implements Timeline {
-	public var frames:Vector.<Number>; // time, ...
-	public var events:Vector.<Event>;
-
-	public function EventTimeline (frameCount:int) {
-		frames = new Vector.<Number>(frameCount, true);
-		events = new Vector.<Event>(frameCount, true);
-	}
-
-	public function get frameCount () : int {
-		return frames.length;
-	}
-
-	/** Sets the time and value of the specified keyframe. */
-	public function setFrame (frameIndex:int, event:Event) : void {
-		frames[frameIndex] = event.time;
-		events[frameIndex] = event;
-	}
-
-	/** Fires events for frames > lastTime and <= time. */
-	public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
-		if (!firedEvents) return;
-		
-		if (lastTime > time) { // Fire events after last time for looped animations.
-			apply(skeleton, lastTime, int.MAX_VALUE, firedEvents, alpha);
-			lastTime = -1;
-		} else if (lastTime >= frames[int(frameCount - 1)]) // Last time is after last frame.
-			return;
-		if (time < frames[0]) return; // Time is before first frame.
-		
-		var frame:int;
-		if (lastTime < frames[0])
-			frame = 0;
-		else {
-			frame = Animation.binarySearch1(frames, lastTime);
-			var frameTime:Number = frames[frame];
-			while (frame > 0) { // Fire multiple events with the same frame.
-				if (frames[int(frame - 1)] != frameTime) break;
-				frame--;
-			}
-		}
-		for (; frame < frameCount && time >= frames[frame]; frame++)
-			firedEvents[firedEvents.length] = events[frame];
-	}
-}
-
+package spine.animation {
+import spine.Event;
+import spine.Skeleton;
+
+public class EventTimeline implements Timeline {
+	public var frames:Vector.<Number>; // time, ...
+	public var events:Vector.<Event>;
+
+	public function EventTimeline (frameCount:int) {
+		frames = new Vector.<Number>(frameCount, true);
+		events = new Vector.<Event>(frameCount, true);
+	}
+
+	public function get frameCount () : int {
+		return frames.length;
+	}
+
+	/** Sets the time and value of the specified keyframe. */
+	public function setFrame (frameIndex:int, event:Event) : void {
+		frames[frameIndex] = event.time;
+		events[frameIndex] = event;
+	}
+
+	/** Fires events for frames > lastTime and <= time. */
+	public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
+		if (!firedEvents) return;
+		
+		if (lastTime > time) { // Fire events after last time for looped animations.
+			apply(skeleton, lastTime, int.MAX_VALUE, firedEvents, alpha);
+			lastTime = -1;
+		} else if (lastTime >= frames[int(frameCount - 1)]) // Last time is after last frame.
+			return;
+		if (time < frames[0]) return; // Time is before first frame.
+		
+		var frame:int;
+		if (lastTime < frames[0])
+			frame = 0;
+		else {
+			frame = Animation.binarySearch1(frames, lastTime);
+			var frameTime:Number = frames[frame];
+			while (frame > 0) { // Fire multiple events with the same frame.
+				if (frames[int(frame - 1)] != frameTime) break;
+				frame--;
+			}
+		}
+		for (; frame < frameCount && time >= frames[frame]; frame++)
+			firedEvents[firedEvents.length] = events[frame];
+	}
+}
+
 }

+ 76 - 77
spine-as3/spine-as3/src/spine/animation/IkConstraintTimeline.as

@@ -1,80 +1,79 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-import spine.Event;
-import spine.IkConstraint;
-import spine.Skeleton;
-
-public class IkConstraintTimeline extends CurveTimeline {
-	static public const ENTRIES:int = 3;
-	static internal const PREV_TIME:int = -3, PREV_MIX:int = -2, PREV_BEND_DIRECTION:int = -1;
-	static internal const MIX:int = 1, BEND_DIRECTION:int = 2;
-
-	public var ikConstraintIndex:int;
-	public var frames:Vector.<Number>; // time, mix, bendDirection, ...
-
-	public function IkConstraintTimeline (frameCount:int) {
-		super(frameCount);
-		frames = new Vector.<Number>(frameCount * ENTRIES, true);
-	}
-
-	/** Sets the time, mix and bend direction of the specified keyframe. */
-	public function setFrame (frameIndex:int, time:Number, mix:Number, bendDirection:int) : void {
-		frameIndex *= ENTRIES;
-		frames[frameIndex] = time;
-		frames[int(frameIndex + MIX)] = mix;
-		frames[int(frameIndex + BEND_DIRECTION)] = bendDirection;
-	}
-
-	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var constraint:IkConstraint = skeleton.ikConstraints[ikConstraintIndex];
-
-		if (time >= frames[int(frames.length - ENTRIES)]) { // Time is after last frame.
-			constraint.mix += (frames[int(frames.length + PREV_MIX)] - constraint.mix) * alpha;
-			constraint.bendDirection = int(frames[int(frames.length + PREV_BEND_DIRECTION)]);
-			return;
-		}
-
-		// Interpolate between the previous frame and the current frame.
-		var frame:int = Animation.binarySearch(frames, time, ENTRIES);
-		var mix:Number = frames[int(frame + PREV_MIX)];
-		var frameTime:Number = frames[frame];
-		var percent:Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
-
-		constraint.mix += (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha;
-		constraint.bendDirection = int(frames[frame + PREV_BEND_DIRECTION]);
-	}
-}
-
+package spine.animation {
+import spine.Event;
+import spine.IkConstraint;
+import spine.Skeleton;
+
+public class IkConstraintTimeline extends CurveTimeline {
+	static public const ENTRIES:int = 3;
+	static internal const PREV_TIME:int = -3, PREV_MIX:int = -2, PREV_BEND_DIRECTION:int = -1;
+	static internal const MIX:int = 1, BEND_DIRECTION:int = 2;
+
+	public var ikConstraintIndex:int;
+	public var frames:Vector.<Number>; // time, mix, bendDirection, ...
+
+	public function IkConstraintTimeline (frameCount:int) {
+		super(frameCount);
+		frames = new Vector.<Number>(frameCount * ENTRIES, true);
+	}
+
+	/** Sets the time, mix and bend direction of the specified keyframe. */
+	public function setFrame (frameIndex:int, time:Number, mix:Number, bendDirection:int) : void {
+		frameIndex *= ENTRIES;
+		frames[frameIndex] = time;
+		frames[int(frameIndex + MIX)] = mix;
+		frames[int(frameIndex + BEND_DIRECTION)] = bendDirection;
+	}
+
+	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
+		if (time < frames[0]) return; // Time is before first frame.
+
+		var constraint:IkConstraint = skeleton.ikConstraints[ikConstraintIndex];
+
+		if (time >= frames[int(frames.length - ENTRIES)]) { // Time is after last frame.
+			constraint.mix += (frames[int(frames.length + PREV_MIX)] - constraint.mix) * alpha;
+			constraint.bendDirection = int(frames[int(frames.length + PREV_BEND_DIRECTION)]);
+			return;
+		}
+
+		// Interpolate between the previous frame and the current frame.
+		var frame:int = Animation.binarySearch(frames, time, ENTRIES);
+		var mix:Number = frames[int(frame + PREV_MIX)];
+		var frameTime:Number = frames[frame];
+		var percent:Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
+
+		constraint.mix += (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha;
+		constraint.bendDirection = int(frames[frame + PREV_BEND_DIRECTION]);
+	}
+}
+
 }

+ 60 - 61
spine-as3/spine-as3/src/spine/animation/Listeners.as

@@ -1,64 +1,63 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-	public class Listeners {
-		private var _listeners:Vector.<Function> = new Vector.<Function>();
-		
-		public function Listeners () {			
-		}
-		
-		public function get listeners () : Vector.<Function> {
-			return _listeners;
-		}
-		
-		public function add (listener:Function) : void {
-			if (listener == null)
-				throw new ArgumentError("listener cannot be null.");
-			var indexOf:int = _listeners.indexOf(listener);
-			if (indexOf == -1)
-				_listeners[_listeners.length] = listener;
-		}
-
-		public function remove (listener:Function) : void {
-			if (listener == null)
-				throw new ArgumentError("listener cannot be null.");
-			var indexOf:int = _listeners.indexOf(listener);
-			if (indexOf != -1)
-				_listeners.splice(_listeners.indexOf(listener), 1);
-		}
-
-		public function invoke (... args:*) : void {
-			for each (var listener:Function in _listeners)
-				listener.apply(null, args);
-		}
-	}
+package spine.animation {
+	public class Listeners {
+		private var _listeners:Vector.<Function> = new Vector.<Function>();
+		
+		public function Listeners () {			
+		}
+		
+		public function get listeners () : Vector.<Function> {
+			return _listeners;
+		}
+		
+		public function add (listener:Function) : void {
+			if (listener == null)
+				throw new ArgumentError("listener cannot be null.");
+			var indexOf:int = _listeners.indexOf(listener);
+			if (indexOf == -1)
+				_listeners[_listeners.length] = listener;
+		}
+
+		public function remove (listener:Function) : void {
+			if (listener == null)
+				throw new ArgumentError("listener cannot be null.");
+			var indexOf:int = _listeners.indexOf(listener);
+			if (indexOf != -1)
+				_listeners.splice(_listeners.indexOf(listener), 1);
+		}
+
+		public function invoke (... args:*) : void {
+			for each (var listener:Function in _listeners)
+				listener.apply(null, args);
+		}
+	}
 }

+ 79 - 80
spine-as3/spine-as3/src/spine/animation/PathConstraintMixTimeline.as

@@ -1,83 +1,82 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-import spine.Event;
-import spine.Skeleton;
-import spine.PathConstraint;
-
-public class PathConstraintMixTimeline extends CurveTimeline {
-	static public const ENTRIES:int = 3;
-	static internal const PREV_TIME:int = -3, PREV_ROTATE:int = -2, PREV_TRANSLATE:int = -1;
-	static internal const ROTATE:int = 1, TRANSLATE:int = 2;
-
-	public var pathConstraintIndex:int;
-	
-	public var frames:Vector.<Number>; // time, rotate mix, translate mix, ...
-
-	public function PathConstraintMixTimeline (frameCount:int) {
-		super(frameCount);
-		frames = new Vector.<Number>(frameCount * ENTRIES, true);
-	}	
-
-	/** Sets the time and mixes of the specified keyframe. */
-	public function setFrame (frameIndex:int, time:Number, rotateMix:Number, translateMix:Number) : void {
-		frameIndex *= ENTRIES;
-		frames[frameIndex] = time;
-		frames[frameIndex + ROTATE] = rotateMix;
-		frames[frameIndex + TRANSLATE] = translateMix;
-	}
-
-	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {		
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var constraint:PathConstraint = skeleton.pathConstraints[pathConstraintIndex];
-
-		if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame.
-			var i:int = frames.length;
-			constraint.rotateMix += (frames[i + PREV_ROTATE] - constraint.rotateMix) * alpha;
-			constraint.translateMix += (frames[i + PREV_TRANSLATE] - constraint.translateMix) * alpha;
-			return;
-		}
-
-		// Interpolate between the previous frame and the current frame.
-		var frame:int = Animation.binarySearch(frames, time, ENTRIES);
-		var rotate:Number = frames[frame + PREV_ROTATE];
-		var translate:Number = frames[frame + PREV_TRANSLATE];
-		var frameTime:Number = frames[frame];
-		var percent:Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
-
-		constraint.rotateMix += (rotate + (frames[frame + ROTATE] - rotate) * percent - constraint.rotateMix) * alpha;
-		constraint.translateMix += (translate + (frames[frame + TRANSLATE] - translate) * percent - constraint.translateMix)
-			* alpha;
-	}
+package spine.animation {
+import spine.Event;
+import spine.Skeleton;
+import spine.PathConstraint;
+
+public class PathConstraintMixTimeline extends CurveTimeline {
+	static public const ENTRIES:int = 3;
+	static internal const PREV_TIME:int = -3, PREV_ROTATE:int = -2, PREV_TRANSLATE:int = -1;
+	static internal const ROTATE:int = 1, TRANSLATE:int = 2;
+
+	public var pathConstraintIndex:int;
+	
+	public var frames:Vector.<Number>; // time, rotate mix, translate mix, ...
+
+	public function PathConstraintMixTimeline (frameCount:int) {
+		super(frameCount);
+		frames = new Vector.<Number>(frameCount * ENTRIES, true);
+	}	
+
+	/** Sets the time and mixes of the specified keyframe. */
+	public function setFrame (frameIndex:int, time:Number, rotateMix:Number, translateMix:Number) : void {
+		frameIndex *= ENTRIES;
+		frames[frameIndex] = time;
+		frames[frameIndex + ROTATE] = rotateMix;
+		frames[frameIndex + TRANSLATE] = translateMix;
+	}
+
+	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {		
+		if (time < frames[0]) return; // Time is before first frame.
+
+		var constraint:PathConstraint = skeleton.pathConstraints[pathConstraintIndex];
+
+		if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame.
+			var i:int = frames.length;
+			constraint.rotateMix += (frames[i + PREV_ROTATE] - constraint.rotateMix) * alpha;
+			constraint.translateMix += (frames[i + PREV_TRANSLATE] - constraint.translateMix) * alpha;
+			return;
+		}
+
+		// Interpolate between the previous frame and the current frame.
+		var frame:int = Animation.binarySearch(frames, time, ENTRIES);
+		var rotate:Number = frames[frame + PREV_ROTATE];
+		var translate:Number = frames[frame + PREV_TRANSLATE];
+		var frameTime:Number = frames[frame];
+		var percent:Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
+
+		constraint.rotateMix += (rotate + (frames[frame + ROTATE] - rotate) * percent - constraint.rotateMix) * alpha;
+		constraint.translateMix += (translate + (frames[frame + TRANSLATE] - translate) * percent - constraint.translateMix)
+			* alpha;
+	}
+}
 }
-}

+ 74 - 75
spine-as3/spine-as3/src/spine/animation/PathConstraintPositionTimeline.as

@@ -1,78 +1,77 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-import spine.PathConstraint;
-import spine.Event;
-import spine.Skeleton;
-	
-public class PathConstraintPositionTimeline extends CurveTimeline {
-	static public const ENTRIES:int = 2;
-	static internal const PREV_TIME:int = -2, PREV_VALUE:int = -1;
-	static internal const VALUE:int = 1;
-
-	public var pathConstraintIndex:int;
-
-	public var frames:Vector.<Number>; // time, position, ...
-
-	public function PathConstraintPositionTimeline (frameCount:int) {
-		super(frameCount);
-		frames = new Vector.<Number>(frameCount * ENTRIES, true);
-	}
-
-	/** Sets the time and value of the specified keyframe. */
-	public function setFrame (frameIndex:int, time:Number, value:Number) : void {
-		frameIndex *= ENTRIES;
-		frames[frameIndex] = time;
-		frames[frameIndex + VALUE] = value;
-	}
-
-	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {		
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var constraint:PathConstraint = skeleton.pathConstraints[pathConstraintIndex];
-
-		if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame.
-			var i:int = frames.length;
-			constraint.position += (frames[i + PREV_VALUE] - constraint.position) * alpha;
-			return;
-		}
-
-		// Interpolate between the previous frame and the current frame.
-		var frame:int = Animation.binarySearch(frames, time, ENTRIES);
-		var position:Number = frames[frame + PREV_VALUE];
-		var frameTime:Number = frames[frame];
-		var percent:Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
-
-		constraint.position += (position + (frames[frame + VALUE] - position) * percent - constraint.position) * alpha;
-	}
+package spine.animation {
+import spine.PathConstraint;
+import spine.Event;
+import spine.Skeleton;
+	
+public class PathConstraintPositionTimeline extends CurveTimeline {
+	static public const ENTRIES:int = 2;
+	static internal const PREV_TIME:int = -2, PREV_VALUE:int = -1;
+	static internal const VALUE:int = 1;
+
+	public var pathConstraintIndex:int;
+
+	public var frames:Vector.<Number>; // time, position, ...
+
+	public function PathConstraintPositionTimeline (frameCount:int) {
+		super(frameCount);
+		frames = new Vector.<Number>(frameCount * ENTRIES, true);
+	}
+
+	/** Sets the time and value of the specified keyframe. */
+	public function setFrame (frameIndex:int, time:Number, value:Number) : void {
+		frameIndex *= ENTRIES;
+		frames[frameIndex] = time;
+		frames[frameIndex + VALUE] = value;
+	}
+
+	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {		
+		if (time < frames[0]) return; // Time is before first frame.
+
+		var constraint:PathConstraint = skeleton.pathConstraints[pathConstraintIndex];
+
+		if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame.
+			var i:int = frames.length;
+			constraint.position += (frames[i + PREV_VALUE] - constraint.position) * alpha;
+			return;
+		}
+
+		// Interpolate between the previous frame and the current frame.
+		var frame:int = Animation.binarySearch(frames, time, ENTRIES);
+		var position:Number = frames[frame + PREV_VALUE];
+		var frameTime:Number = frames[frame];
+		var percent:Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
+
+		constraint.position += (position + (frames[frame + VALUE] - position) * percent - constraint.position) * alpha;
+	}
+}
 }
-}

+ 58 - 59
spine-as3/spine-as3/src/spine/animation/PathConstraintSpacingTimeline.as

@@ -1,62 +1,61 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-import spine.Skeleton;
-import spine.Event;
-import spine.PathConstraint;
-
-public class PathConstraintSpacingTimeline extends PathConstraintPositionTimeline {
-	public function PathConstraintSpacingTimeline (frameCount:int) {
-		super(frameCount);
-	}
-
-	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {		
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var constraint:PathConstraint = skeleton.pathConstraints[pathConstraintIndex];
-
-		if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame.
-			var i:int = frames.length;
-			constraint.spacing += (frames[i + PREV_VALUE] - constraint.spacing) * alpha;
-			return;
-		}
-
-		// Interpolate between the previous frame and the current frame.
-		var frame:int = Animation.binarySearch(frames, time, ENTRIES);
-		var spacing:Number = frames[frame + PREV_VALUE];
-		var frameTime:Number = frames[frame];
-		var percent:Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
-
-		constraint.spacing += (spacing + (frames[frame + VALUE] - spacing) * percent - constraint.spacing) * alpha;
-	}
+package spine.animation {
+import spine.Skeleton;
+import spine.Event;
+import spine.PathConstraint;
+
+public class PathConstraintSpacingTimeline extends PathConstraintPositionTimeline {
+	public function PathConstraintSpacingTimeline (frameCount:int) {
+		super(frameCount);
+	}
+
+	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {		
+		if (time < frames[0]) return; // Time is before first frame.
+
+		var constraint:PathConstraint = skeleton.pathConstraints[pathConstraintIndex];
+
+		if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame.
+			var i:int = frames.length;
+			constraint.spacing += (frames[i + PREV_VALUE] - constraint.spacing) * alpha;
+			return;
+		}
+
+		// Interpolate between the previous frame and the current frame.
+		var frame:int = Animation.binarySearch(frames, time, ENTRIES);
+		var spacing:Number = frames[frame + PREV_VALUE];
+		var frameTime:Number = frames[frame];
+		var percent:Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
+
+		constraint.spacing += (spacing + (frames[frame + VALUE] - spacing) * percent - constraint.spacing) * alpha;
+	}
+}
 }
-}

+ 89 - 90
spine-as3/spine-as3/src/spine/animation/RotateTimeline.as

@@ -1,93 +1,92 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-import spine.Bone;
-import spine.Event;
-import spine.Skeleton;
-
-public class RotateTimeline extends CurveTimeline {
-	static public const ENTRIES:int = 2;
-	static private const PREV_TIME:int = -2, PREV_ROTATION:int = -1;
-	static private const ROTATION:int = 1;
-
-	public var boneIndex:int;
-	public var frames:Vector.<Number>; // time, value, ...
-
-	public function RotateTimeline (frameCount:int) {
-		super(frameCount);
-		frames = new Vector.<Number>(frameCount * 2, true);
-	}
-
-	/** Sets the time and angle of the specified keyframe. */
-	public function setFrame (frameIndex:int, time:Number, degrees:Number) : void {
-		frameIndex <<= 1;
-		frames[frameIndex] = time;
-		frames[int(frameIndex + ROTATION)] = degrees;
-	}
-
-	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
-		if (time < frames[0])
-			return; // Time is before first frame.
-
-		var bone:Bone = skeleton.bones[boneIndex];
-		
-		if (time >= frames[int(frames.length - 2)]) { // Time is after last frame.
-			var amount:Number = bone.data.rotation + frames[int(frames.length + PREV_ROTATION)] - bone.rotation;
-			while (amount > 180)
-				amount -= 360;
-			while (amount < -180)
-				amount += 360;
-			bone.rotation += amount * alpha;
-			return;
-		}
-
-		// Interpolate between the previous frame and the current frame.
-		var frame:int = Animation.binarySearch(frames, time, ENTRIES);
-		var prevRotation:Number = frames[int(frame + PREV_ROTATION)];
-		var frameTime:Number = frames[frame];		
-		var percent:Number = getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
-
-		amount = frames[int(frame + ROTATION)] - prevRotation;
-		while (amount > 180)
-			amount -= 360;
-		while (amount < -180)
-			amount += 360;
-		amount = bone.data.rotation + (prevRotation + amount * percent) - bone.rotation;
-		while (amount > 180)
-			amount -= 360;
-		while (amount < -180)
-			amount += 360;
-		bone.rotation += amount * alpha;
-	}
-}
-
+package spine.animation {
+import spine.Bone;
+import spine.Event;
+import spine.Skeleton;
+
+public class RotateTimeline extends CurveTimeline {
+	static public const ENTRIES:int = 2;
+	static private const PREV_TIME:int = -2, PREV_ROTATION:int = -1;
+	static private const ROTATION:int = 1;
+
+	public var boneIndex:int;
+	public var frames:Vector.<Number>; // time, value, ...
+
+	public function RotateTimeline (frameCount:int) {
+		super(frameCount);
+		frames = new Vector.<Number>(frameCount * 2, true);
+	}
+
+	/** Sets the time and angle of the specified keyframe. */
+	public function setFrame (frameIndex:int, time:Number, degrees:Number) : void {
+		frameIndex <<= 1;
+		frames[frameIndex] = time;
+		frames[int(frameIndex + ROTATION)] = degrees;
+	}
+
+	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
+		if (time < frames[0])
+			return; // Time is before first frame.
+
+		var bone:Bone = skeleton.bones[boneIndex];
+		
+		if (time >= frames[int(frames.length - 2)]) { // Time is after last frame.
+			var amount:Number = bone.data.rotation + frames[int(frames.length + PREV_ROTATION)] - bone.rotation;
+			while (amount > 180)
+				amount -= 360;
+			while (amount < -180)
+				amount += 360;
+			bone.rotation += amount * alpha;
+			return;
+		}
+
+		// Interpolate between the previous frame and the current frame.
+		var frame:int = Animation.binarySearch(frames, time, ENTRIES);
+		var prevRotation:Number = frames[int(frame + PREV_ROTATION)];
+		var frameTime:Number = frames[frame];		
+		var percent:Number = getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
+
+		amount = frames[int(frame + ROTATION)] - prevRotation;
+		while (amount > 180)
+			amount -= 360;
+		while (amount < -180)
+			amount += 360;
+		amount = bone.data.rotation + (prevRotation + amount * percent) - bone.rotation;
+		while (amount > 180)
+			amount -= 360;
+		while (amount < -180)
+			amount += 360;
+		bone.rotation += amount * alpha;
+	}
+}
+
 }

+ 61 - 62
spine-as3/spine-as3/src/spine/animation/ScaleTimeline.as

@@ -1,65 +1,64 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-import spine.Bone;
-import spine.Event;
-import spine.Skeleton;
-
-public class ScaleTimeline extends TranslateTimeline {
-	public function ScaleTimeline (frameCount:int) {
-		super(frameCount);
-	}
-
-	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
-		if (time < frames[0])
-			return; // Time is before first frame.
-
-		var bone:Bone = skeleton.bones[boneIndex];
-		if (time >= frames[int(frames.length - ENTRIES)]) { // Time is after last frame.
-			bone.scaleX += (bone.data.scaleX * frames[int(frames.length + PREV_X)] - bone.scaleX) * alpha;
-			bone.scaleY += (bone.data.scaleY * frames[int(frames.length + PREV_Y)] - bone.scaleY) * alpha;
-			return;
-		}
-
-		// Interpolate between the previous frame and the current frame.
-		var frame:int = Animation.binarySearch(frames, time, ENTRIES);
-		var prevX:Number = frames[frame + PREV_X];
-		var prevY:Number = frames[frame + PREV_Y];
-		var frameTime:Number = frames[frame];
-		var percent:Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
-
-		bone.scaleX += (bone.data.scaleX * (prevX + (frames[frame + X] - prevX) * percent) - bone.scaleX) * alpha;
-		bone.scaleY += (bone.data.scaleY * (prevY + (frames[frame + Y] - prevY) * percent) - bone.scaleY) * alpha;
-	}
-}
-
+package spine.animation {
+import spine.Bone;
+import spine.Event;
+import spine.Skeleton;
+
+public class ScaleTimeline extends TranslateTimeline {
+	public function ScaleTimeline (frameCount:int) {
+		super(frameCount);
+	}
+
+	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
+		if (time < frames[0])
+			return; // Time is before first frame.
+
+		var bone:Bone = skeleton.bones[boneIndex];
+		if (time >= frames[int(frames.length - ENTRIES)]) { // Time is after last frame.
+			bone.scaleX += (bone.data.scaleX * frames[int(frames.length + PREV_X)] - bone.scaleX) * alpha;
+			bone.scaleY += (bone.data.scaleY * frames[int(frames.length + PREV_Y)] - bone.scaleY) * alpha;
+			return;
+		}
+
+		// Interpolate between the previous frame and the current frame.
+		var frame:int = Animation.binarySearch(frames, time, ENTRIES);
+		var prevX:Number = frames[frame + PREV_X];
+		var prevY:Number = frames[frame + PREV_Y];
+		var frameTime:Number = frames[frame];
+		var percent:Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
+
+		bone.scaleX += (bone.data.scaleX * (prevX + (frames[frame + X] - prevX) * percent) - bone.scaleX) * alpha;
+		bone.scaleY += (bone.data.scaleY * (prevY + (frames[frame + Y] - prevY) * percent) - bone.scaleY) * alpha;
+	}
+}
+
 }

+ 62 - 32
spine-as3/spine-as3/src/spine/animation/ShearTimeline.as

@@ -1,34 +1,64 @@
-package spine.animation {
-	import spine.Event;
-	import spine.Skeleton;
-	import spine.Bone;
+/******************************************************************************
+ * 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.
+ *****************************************************************************/
 
-public class ShearTimeline extends TranslateTimeline {
-	public function ShearTimeline (frameCount:int) {
-		super(frameCount);
-	}
-
-	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
-		var frames:Vector.<Number> = this.frames;
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var bone:Bone = skeleton.bones[boneIndex];
-		if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame.
-			bone.shearX += (bone.data.shearX + frames[frames.length + PREV_X] - bone.shearX) * alpha;
-			bone.shearY += (bone.data.shearY + frames[frames.length + PREV_Y] - bone.shearY) * alpha;
-			return;
-		}
-
-		// Interpolate between the previous frame and the current frame.
-		var frame:int = Animation.binarySearch(frames, time, ENTRIES);
-		var prevX:Number = frames[frame + PREV_X];
-		var prevY:Number = frames[frame + PREV_Y];
-		var frameTime:Number = frames[frame];
-		var percent:Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
-
-		bone.shearX += (bone.data.shearX + (prevX + (frames[frame + X] - prevX) * percent) - bone.shearX) * alpha;
-		bone.shearY += (bone.data.shearY + (prevY + (frames[frame + Y] - prevY) * percent) - bone.shearY) * alpha;
-	}
+package spine.animation {
+	import spine.Event;
+	import spine.Skeleton;
+	import spine.Bone;
+
+public class ShearTimeline extends TranslateTimeline {
+	public function ShearTimeline (frameCount:int) {
+		super(frameCount);
+	}
+
+	override public function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void {
+		var frames:Vector.<Number> = this.frames;
+		if (time < frames[0]) return; // Time is before first frame.
+
+		var bone:Bone = skeleton.bones[boneIndex];
+		if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame.
+			bone.shearX += (bone.data.shearX + frames[frames.length + PREV_X] - bone.shearX) * alpha;
+			bone.shearY += (bone.data.shearY + frames[frames.length + PREV_Y] - bone.shearY) * alpha;
+			return;
+		}
+
+		// Interpolate between the previous frame and the current frame.
+		var frame:int = Animation.binarySearch(frames, time, ENTRIES);
+		var prevX:Number = frames[frame + PREV_X];
+		var prevY:Number = frames[frame + PREV_Y];
+		var frameTime:Number = frames[frame];
+		var percent:Number = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime));
+
+		bone.shearX += (bone.data.shearX + (prevX + (frames[frame + X] - prevX) * percent) - bone.shearX) * alpha;
+		bone.shearY += (bone.data.shearY + (prevY + (frames[frame + Y] - prevY) * percent) - bone.shearY) * alpha;
+	}
+}
+
 }
-
-}

+ 37 - 38
spine-as3/spine-as3/src/spine/animation/Timeline.as

@@ -1,41 +1,40 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-import spine.Event;
-import spine.Skeleton;
-
-public interface Timeline {
-	/** Sets the value(s) for the specified time. */
-	function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void;
-}
-
+package spine.animation {
+import spine.Event;
+import spine.Skeleton;
+
+public interface Timeline {
+	/** Sets the value(s) for the specified time. */
+	function apply (skeleton:Skeleton, lastTime:Number, time:Number, firedEvents:Vector.<Event>, alpha:Number) : void;
+}
+
 }

+ 47 - 48
spine-as3/spine-as3/src/spine/animation/TrackEntry.as

@@ -1,51 +1,50 @@
-/******************************************************************************
- * Spine Runtimes Software License
- * Version 2.3
- * 
- * Copyright (c) 2013-2015, 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 (the "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 otherwise create derivative works, improvements of the
- * Software or develop new applications using the Software 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; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) 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.
+/******************************************************************************
+ * 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.
  *****************************************************************************/
 
-package spine.animation {
-
-public class TrackEntry {
-	public var next:TrackEntry;
-	internal var previous:TrackEntry;
-	public var animation:Animation;
-	public var loop:Boolean;
-	public var delay:Number, time:Number = 0, lastTime:Number = -1, endTime:Number, timeScale:Number = 1;
-	internal var mixTime:Number, mixDuration:Number, mix:Number = 1;
-	public var onStart:Function, onEnd:Function, onComplete:Function, onEvent:Function;
-	
-	public function TrackEntry () {		
-	}
-	
-	public function toString () : String {
-		return animation == null ? "<none>" : animation.name;
-	}
-}
-
+package spine.animation {
+
+public class TrackEntry {
+	public var next:TrackEntry;
+	internal var previous:TrackEntry;
+	public var animation:Animation;
+	public var loop:Boolean;
+	public var delay:Number, time:Number = 0, lastTime:Number = -1, endTime:Number, timeScale:Number = 1;
+	internal var mixTime:Number, mixDuration:Number, mix:Number = 1;
+	public var onStart:Function, onEnd:Function, onComplete:Function, onEvent:Function;
+	
+	public function TrackEntry () {		
+	}
+	
+	public function toString () : String {
+		return animation == null ? "<none>" : animation.name;
+	}
+}
+
 }

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно