Sfoglia il codice sorgente

[spine-js] Deprecated, updated README.md

badlogic 9 anni fa
parent
commit
6e4784232f
5 ha cambiato i file con 1 aggiunte e 3115 eliminazioni
  1. 0 28
      spine-js/LICENSE
  2. 1 33
      spine-js/README.md
  3. 0 74
      spine-js/example/index.html
  4. 0 118
      spine-js/spine-canvas.js
  5. 0 2862
      spine-js/spine.js

+ 0 - 28
spine-js/LICENSE

@@ -1,28 +0,0 @@
-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.

+ 1 - 33
spine-js/README.md

@@ -1,35 +1,3 @@
 # spine-js
 
-The spine-js runtime provides functionality to load and manipulate [Spine](http://esotericsoftware.com) skeletal animation data using JavaScript. It does not perform rendering but can be extended to enable Spine animations for other JavaScript-based projects.
-
-# spine-canvas
-
-The spine-canvas runtime extends spine-js and is a basic example of how to perform rendering using an HTML5 canvas. Because spine-canvas renders rectangular images, nonuniform scaling and mesh attachments are not supported.
-
-## Licensing
-
-This Spine Runtime may only be used for personal or internal use, typically to evaluate Spine before purchasing. If you would like to incorporate a Spine Runtime into your applications, distribute software containing a Spine Runtime, or modify a Spine Runtime, then you will need a valid [Spine license](https://esotericsoftware.com/spine-purchase). Please see the [Spine Runtimes Software License](https://github.com/EsotericSoftware/spine-runtimes/blob/master/LICENSE) for detailed information.
-
-The Spine Runtimes are developed with the intent to be used with data exported from Spine. By purchasing Spine, `Section 2` of the [Spine Software License](https://esotericsoftware.com/files/license.txt) grants the right to create and distribute derivative works of the Spine Runtimes.
-
-## Spine version
-
-spine-js works with data exported from Spine 3.1.08. Updating spine-js to [v3.2](https://github.com/EsotericSoftware/spine-runtimes/issues/586) and [v3.3](https://github.com/EsotericSoftware/spine-runtimes/issues/613) is in progress.
-
-spine-js supports all Spine features. spine-canvas does not support color tinting, mesh attachments, or nonuniform scaling.
-
-spine-js does not yet support loading the binary format.
-
-## Setup
-
-1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
-1. Include the `spine.js` file (and optionally the `spine-canvas.js` file) in your project.
-
-## Demos
-
-- [spine-canvas](http://esotericsoftware.com/files/runtimes/spine-js/example/)
-
-## Runtimes Extending spine-js
-
-- [spine-turbulenz](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-turbulenz)
-- [spine-threejs](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-threejs)
+spine-js has been deprecated and is superseded by [spine-ts](https://github.com/EsotericSoftware/spine-runtimes/tree/master/spine-ts). The most recent version of spine-js can be found in the [spine-js branch](https://github.com/EsotericSoftware/spine-runtimes/tree/spine-js/spine-js)

File diff suppressed because it is too large
+ 0 - 74
spine-js/example/index.html


+ 0 - 118
spine-js/spine-canvas.js

@@ -1,118 +0,0 @@
-/******************************************************************************
- * 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.SkeletonRenderer = function (imagesPath) {
-	this.imagesPath = imagesPath;
-	this.lastTime = Date.now();
-};
-
-spine.SkeletonRenderer.prototype = {
-	skeletonData: null,
-	state: null,
-	scale: 1,
-	skeleton: null,
-	
-	load: function(jsonText) {
-		var imagesPath = this.imagesPath;
-		var json = new spine.SkeletonJson({
-			newRegionAttachment: function (skin, name, path) {
-				var image = new Image();
-				image.src = imagesPath + path + ".png";
-				var attachment = new spine.RegionAttachment(name);
-				attachment.rendererObject = image;
-				return attachment;
-			},
-			newBoundingBoxAttachment: function (skin, name) {
-				return new spine.BoundingBoxAttachment(name);
-			}
-		});
-		json.scale = this.scale;
-		this.skeletonData = json.readSkeletonData(JSON.parse(jsonText));
-		spine.Bone.yDown = true;
-		
-		this.skeleton = new spine.Skeleton(this.skeletonData);
-
-		var stateData = new spine.AnimationStateData(this.skeletonData);
-		this.state = new spine.AnimationState(stateData);
-	},
-
-	update: function() {
-		var now = Date.now();
-		var delta = (now - this.lastTime) / 1000;
-		this.lastTime = now;
-
-		this.state.update(delta);
-		this.state.apply(this.skeleton);
-		this.skeleton.updateWorldTransform();
-	},
-
-	render: function(context) {
-		var skeleton = this.skeleton, drawOrder = skeleton.drawOrder;
-		context.translate(skeleton.x, skeleton.y);
-
-		for (var i = 0, n = drawOrder.length; i < n; i++) {
-			var slot = drawOrder[i];
-			var attachment = slot.attachment;
-			if (!(attachment instanceof spine.RegionAttachment)) continue;
-			var bone = slot.bone;
-			var x = attachment.x * bone.a + attachment.y * bone.b + bone.worldX;
-			var y = attachment.x * bone.c + attachment.y * bone.d + bone.worldY;
-			var rotation = (bone.getWorldRotationX() - attachment.rotation) * Math.PI / 180;
-			var w = attachment.width * bone.getWorldScaleX(), h = attachment.height * bone.getWorldScaleY();
-			context.translate(x, y);
-			context.rotate(rotation);
-			context.drawImage(attachment.rendererObject, -w / 2, -h / 2, w, h);
-			context.rotate(-rotation);
-			context.translate(-x, -y);
-		}
-
-		context.translate(-skeleton.x, -skeleton.y);
-	},
-
-	animate: function (id) {
-		var canvas = document.getElementById(id);
-		var context = canvas.getContext("2d");
-		var requestAnimationFrame = window.requestAnimationFrame ||
-			window.webkitRequestAnimationFrame ||
-			window.mozRequestAnimationFrame ||
-			function (callback) {
-				window.setTimeout(callback, 1000 / 60);
-			};
-		var self = this;
-		function renderFrame () {
-			context.clearRect(0, 0, canvas.width, canvas.height);
-			self.update();
-			self.render(context);
-			requestAnimationFrame(renderFrame);
-		};
-		renderFrame();
-	}
-};

+ 0 - 2862
spine-js/spine.js

@@ -1,2862 +0,0 @@
-/******************************************************************************
- * 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.
- *****************************************************************************/
-
-var spine = {
-	radDeg: 180 / Math.PI,
-	degRad: Math.PI / 180,
-	Float32Array: typeof(Float32Array) === 'undefined' ? Array : Float32Array,
-	Uint32Array: typeof(Uint32Array) === 'undefined' ? Array : Uint32Array,
-	Uint16Array: typeof(Uint16Array) === 'undefined' ? Array : Uint16Array
-};
-spine.temp = new spine.Float32Array(2);
-
-spine.BoneData = function (name, parent) {
-	this.name = name;
-	this.parent = parent;
-};
-spine.BoneData.prototype = {
-	length: 0,
-	x: 0, y: 0,
-	rotation: 0,
-	scaleX: 1, scaleY: 1,
-	inheritScale: true,
-	inheritRotation: true
-};
-
-spine.BlendMode = {
-	normal: 0,
-	additive: 1,
-	multiply: 2,
-	screen: 3
-};
-
-spine.SlotData = function (name, boneData) {
-	this.name = name;
-	this.boneData = boneData;
-};
-spine.SlotData.prototype = {
-	r: 1, g: 1, b: 1, a: 1,
-	attachmentName: null,
-	blendMode: spine.BlendMode.normal
-};
-
-spine.IkConstraintData = function (name) {
-	this.name = name;
-	this.bones = [];
-};
-spine.IkConstraintData.prototype = {
-	target: null,
-	bendDirection: 1,
-	mix: 1
-};
-
-spine.TransformConstraintData = function (name) {
-	this.name = name;
-};
-spine.TransformConstraintData.prototype = {
-	bone: null,
-	target: null,
-	translateMix: 1,
-	x: 0, y: 0
-};
-
-spine.Bone = function (boneData, skeleton, parent) {
-	this.data = boneData;
-	this.skeleton = skeleton;
-	this.parent = parent;
-	this.setToSetupPose();
-};
-spine.Bone.yDown = false;
-spine.Bone.prototype = {
-	x: 0, y: 0, rotation: 0, scaleX: 1, scaleY: 1,
-	a: 0, b: 0, worldX: 0,
-	c: 0, d: 0, worldY: 0,
-	worldSignX: 1, worldSignY: 1,
-	update: function () {
-		this.updateWorldTransform(this.x, this.y, this.rotation, this.scaleX, this.scaleY);
-	},
-	updateWorldTransformWith: function () {
-		this.updateWorldTransform(this.x, this.y, this.rotation, this.scaleX, this.scaleY);
-	},
-	updateWorldTransform: function (x, y, rotation, scaleX, scaleY) {
-		this.appliedRotation = rotation;
-		this.appliedScaleX = scaleX;
-		this.appliedScaleY = scaleY;
-
-		rotation *= spine.degRad;
-		var cos = Math.cos(rotation), sin = Math.sin(rotation);
-		var la = cos * scaleX, lb = -sin * scaleY, lc = sin * scaleX, ld = cos * scaleY;
-		var parent = this.parent;
-		if (!parent) { // Root bone.
-			var skeleton = this.skeleton;
-			if (skeleton.flipX) {
-				x = -x;
-				la = -la;
-				lb = -lb;
-			}
-			if (skeleton.flipY != spine.Bone.yDown) {
-				y = -y;
-				lc = -lc;
-				ld = -ld;
-			}
-			this.a = la;
-			this.b = lb;
-			this.c = lc;
-			this.d = ld;
-			this.worldX = x;
-			this.worldY = y;
-			this.worldSignX = scaleX < 0 ? -1 : 1;
-			this.worldSignY = scaleY < 0 ? -1 : 1;
-			return;
-		}
-
-		var pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
-		this.worldX = pa * x + pb * y + parent.worldX;
-		this.worldY = pc * x + pd * y + parent.worldY;
-		this.worldSignX = parent.worldSignX * (scaleX < 0 ? -1 : 1);
-		this.worldSignY = parent.worldSignY * (scaleY < 0 ? -1 : 1);
-
-		if (this.data.inheritRotation && this.data.inheritScale) {
-			this.a = pa * la + pb * lc;
-			this.b = pa * lb + pb * ld;
-			this.c = pc * la + pd * lc;
-			this.d = pc * lb + pd * ld;
-		} else {
-			if (this.data.inheritRotation) { // No scale inheritance.
-				pa = 1;
-				pb = 0;
-				pc = 0;
-				pd = 1;
-				do {
-					rotation = parent.appliedRotation * spine.degRad;
-					cos = Math.cos(rotation);
-					sin = Math.sin(rotation);
-					var temp = pa * cos + pb * sin;
-					pb = pa * -sin + pb * cos;
-					pa = temp;
-					temp = pc * cos + pd * sin;
-					pd = pc * -sin + pd * cos;
-					pc = temp;
-
-					if (!parent.data.inheritRotation) break;
-					parent = parent.parent;
-				} while (parent);
-				this.a = pa * la + pb * lc;
-				this.b = pa * lb + pb * ld;
-				this.c = pc * la + pd * lc;
-				this.d = pc * lb + pd * ld;
-			} else if (this.data.inheritScale) { // No rotation inheritance.
-				pa = 1;
-				pb = 0;
-				pc = 0;
-				pd = 1;
-				do {
-					rotation = parent.appliedRotation * spine.degRad;
-					cos = Math.cos(rotation);
-					sin = Math.sin(rotation);
-					var psx = parent.appliedScaleX, psy = parent.appliedScaleY;
-					var za = cos * psx, zb = -sin * psy, zc = sin * psx, zd = cos * psy;
-					var temp = pa * za + pb * zc;
-					pb = pa * zb + pb * zd;
-					pa = temp;
-					temp = pc * za + pd * zc;
-					pd = pc * zb + pd * zd;
-					pc = temp;
-
-					if (psx < 0) rotation = -rotation;
-					cos = Math.cos(-rotation);
-					sin = Math.sin(-rotation);
-					temp = pa * cos + pb * sin;
-					pb = pa * -sin + pb * cos;
-					pa = temp;
-					temp = pc * cos + pd * sin;
-					pd = pc * -sin + pd * cos;
-					pc = temp;
-
-					if (!parent.data.inheritScale) break;
-					parent = parent.parent;
-				} while (parent);
-				this.a = pa * la + pb * lc;
-				this.b = pa * lb + pb * ld;
-				this.c = pc * la + pd * lc;
-				this.d = pc * lb + pd * ld;
-			} else {
-				this.a = la;
-				this.b = lb;
-				this.c = lc;
-				this.d = ld;
-			}
-			if (this.skeleton.flipX) {
-				this.a = -this.a;
-				this.b = -this.b;
-			}
-			if (this.skeleton.flipY != spine.Bone.yDown) {
-				this.c = -this.c;
-				this.d = -this.d;
-			}
-		}
-	},
-	setToSetupPose: function () {
-		var data = this.data;
-		this.x = data.x;
-		this.y = data.y;
-		this.rotation = data.rotation;
-		this.scaleX = data.scaleX;
-		this.scaleY = data.scaleY;
-	},
-	getWorldRotationX: function () {
-		return Math.atan2(this.c, this.a) * spine.radDeg;
-	},
-	getWorldRotationY: function () {
-		return Math.atan2(this.d, this.b) * spine.radDeg;
-	},
-	getWorldScaleX: function () {
-		return Math.sqrt(this.a * this.a + this.b * this.b) * this.worldSignX;
-	},
-	getWorldScaleY: function () {
-		return Math.sqrt(this.c * this.c + this.d * this.d) * this.worldSignY;
-	},
-	worldToLocal: function (world) {
-		var x = world[0] - this.worldX, y = world[1] - this.worldY;
-		var a = this.a, b = this.b, c = this.c, d = this.d;
-		var invDet = 1 / (a * d - b * c);
-		world[0] = (x * d * invDet - y * b * invDet);
-		world[1] = (y * a * invDet - x * c * invDet);
-		return world;
-	},
-	localToWorld: function (local) {
-		var x = local[0], y = local[1];
-		local[0] = x * this.a + y * this.b + this.worldX;
-		local[1] = x * this.c + y * this.d + this.worldY;
-		return local;
-	}
-};
-
-spine.Slot = function (slotData, bone) {
-	this.data = slotData;
-	this.bone = bone;
-	this.attachmentVertices = new spine.Float32Array();
-	this.setToSetupPose();
-};
-spine.Slot.prototype = {
-	r: 1, g: 1, b: 1, a: 1,
-	_attachmentTime: 0,
-	attachment: null,
-	setAttachment: function (attachment) {
-		if (this.attachment == attachment) return;
-		this.attachment = attachment;
-		this._attachmentTime = this.bone.skeleton.time;
-		this.attachmentVertices.length = 0;
-	},
-	setAttachmentTime: function (time) {
-		this._attachmentTime = this.bone.skeleton.time - time;
-	},
-	getAttachmentTime: function () {
-		return this.bone.skeleton.time - this._attachmentTime;
-	},
-	setToSetupPose: function () {
-		var data = this.data;
-		this.r = data.r;
-		this.g = data.g;
-		this.b = data.b;
-		this.a = data.a;
-
-		if (!data.attachmentName)
-			this.setAttachment(null);
-		else {
-			var slotDatas = this.bone.skeleton.data.slots;
-			for (var i = 0, n = slotDatas.length; i < n; i++) {
-				if (slotDatas[i] == data) {
-					this.attachment = null;
-					this.setAttachment(this.bone.skeleton.getAttachmentBySlotIndex(i, data.attachmentName));
-					break;
-				}
-			}
-		}
-	}
-};
-
-spine.IkConstraint = function (data, skeleton) {
-	this.data = data;
-	this.mix = data.mix;
-	this.bendDirection = data.bendDirection;
-
-	this.bones = [];
-	for (var i = 0, n = data.bones.length; i < n; i++)
-		this.bones[i] = skeleton.findBone(data.bones[i].name);
-	this.target = skeleton.findBone(data.target.name);
-};
-spine.IkConstraint.prototype = {
-	apply: function () {
-		this.update();
-	},
-	update: function () {
-		var target = this.target;
-		var bones = this.bones;
-		switch (bones.length) {
-		case 1:
-			spine.IkConstraint.apply1(bones[0], target.worldX, target.worldY, this.mix);
-			break;
-		case 2:
-			spine.IkConstraint.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.mix);
-			break;
-		}
-	},
-};
-/** 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. */
-spine.IkConstraint.apply1 = function (bone, targetX, targetY, alpha) {
-	var parentRotation = !bone.parent ? 0 : bone.parent.getWorldRotationX();
-	var rotation = bone.rotation;
-	var rotationIK = Math.atan2(targetY - bone.worldY, targetX - bone.worldX) * spine.radDeg - parentRotation;
-	if ((bone.worldSignX != bone.worldSignY) != (bone.skeleton.flipX != (bone.skeleton.flipY != spine.Bone.yDown)))
-		rotationIK = 360 - rotationIK;
-	if (rotationIK > 180) rotationIK -= 360;
-	else if (rotationIK < -180) rotationIK += 360;
-	bone.updateWorldTransform(bone.x, bone.y, rotation + (rotationIK - rotation) * alpha, bone.appliedScaleX, bone.appliedScaleY);
-};
-/** 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 A direct descendant of the parent bone. */
-spine.IkConstraint.apply2 = function (parent, child, targetX, targetY, bendDir, alpha) {
-	if (alpha == 0) return;
-	var px = parent.x, py = parent.y, psx = parent.appliedScaleX, psy = parent.appliedScaleY;
-	var os1, os2, s2;
-	if (psx < 0) {
-		psx = -psx;
-		os1 = 180;
-		s2 = -1;
-	} else {
-		os1 = 0;
-		s2 = 1;
-	}
-	if (psy < 0) {
-		psy = -psy;
-		s2 = -s2;
-	}
-	var cx = child.x, cy = child.y, csx = child.appliedScaleX;
-	var u = Math.abs(psx - psy) <= 0.0001;
-	if (!u && cy != 0) {
-		child.worldX = parent.a * cx + parent.worldX;
-		child.worldY = parent.c * cx + parent.worldY;
-		cy = 0;
-	}
-	if (csx < 0) {
-		csx = -csx;
-		os2 = 180;
-	} else
-		os2 = 0;
-	var pp = parent.parent;
-	var tx, ty, dx, dy;
-	if (!pp) {
-		tx = targetX - px;
-		ty = targetY - py;
-		dx = child.worldX - px;
-		dy = child.worldY - py;
-	} else {
-		var a = pp.a, b = pp.b, c = pp.c, d = pp.d, invDet = 1 / (a * d - b * c);
-		var wx = pp.worldX, wy = pp.worldY, x = targetX - wx, y = targetY - wy;
-		tx = (x * d - y * b) * invDet - px;
-		ty = (y * a - x * c) * invDet - py;
-		x = child.worldX - wx;
-		y = child.worldY - wy;
-		dx = (x * d - y * b) * invDet - px;
-		dy = (y * a - x * c) * invDet - py;
-	}
-	var l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2;
-	outer:
-	if (u) {
-		l2 *= psx;
-		var cos = (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;
-		var a = l1 + l2 * cos, o = l2 * Math.sin(a2);
-		a1 = Math.atan2(ty * a - tx * o, tx * a + ty * o);
-	} else {
-		var a = psx * l2, b = psy * l2, ta = Math.atan2(ty, tx);
-		var aa = a * a, bb = b * b, ll = l1 * l1, dd = tx * tx + ty * ty;
-		var c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa;
-		var d = c1 * c1 - 4 * c2 * c0;
-		if (d >= 0) {
-			var q = Math.sqrt(d);
-			if (c1 < 0) q = -q;
-			q = -(c1 + q) / 2;
-			var r0 = q / c2, r1 = c0 / q;
-			var r = Math.abs(r0) < Math.abs(r1) ? r0 : r1;
-			if (r * r <= dd) {
-				var 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 = 0, minDist = Number.MAX_VALUE, minX = 0, minY = 0;
-		var maxAngle = 0, maxDist = 0, maxX = 0, maxY = 0;
-		var x = l1 + a, dist = x * x;
-		if (dist > maxDist) {
-			maxAngle = 0;
-			maxDist = dist;
-			maxX = x;
-		}
-		x = l1 - a;
-		dist = x * x;
-		if (dist < minDist) {
-			minAngle = Math.PI;
-			minDist = dist;
-			minX = x;
-		}
-		var angle = Math.acos(-a * l1 / (aa - bb));
-		x = a * Math.cos(angle) + l1;
-		var y = b * Math.sin(angle);
-		dist = x * x + y * y;
-		if (dist < minDist) {
-			minAngle = angle;
-			minDist = dist;
-			minX = x;
-			minY = y;
-		}
-		if (dist > maxDist) {
-			maxAngle = angle;
-			maxDist = dist;
-			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 = Math.atan2(cy, cx) * s2;
-	a1 = (a1 - os) * spine.radDeg + os1;
-	a2 = (a2 + os) * spine.radDeg * s2 + os2;
-	if (a1 > 180) a1 -= 360;
-	else if (a1 < -180) a1 += 360;
-	if (a2 > 180) a2 -= 360;
-	else if (a2 < -180) a2 += 360;
-	var rotation = parent.rotation;
-	parent.updateWorldTransform(px, py, rotation + (a1 - rotation) * alpha, parent.appliedScaleX, parent.appliedScaleY);
-	rotation = child.rotation;
-	child.updateWorldTransform(cx, cy, rotation + (a2 - rotation) * alpha, child.appliedScaleX, child.appliedScaleY);
-};
-
-spine.TransformConstraint = function (data, skeleton) {
-	this.data = data;
-	this.translateMix = data.translateMix;
-	this.x = data.x;
-	this.y = data.y;
-	this.bone = skeleton.findBone(data.bone.name);
-	this.target = skeleton.findBone(data.target.name);
-};
-spine.TransformConstraint.prototype = {
-	apply: function () {
-		this.update();
-	},
-	update: function () {
-		var translateMix = this.translateMix;
-		if (translateMix > 0) {
-			var temp = spine.temp;
-			temp[0] = x;
-			temp[1] = y;
-			this.target.localToWorld(temp);
-			var bone = this.bone;
-			bone.worldX += (temp[0] - bone.worldX) * translateMix;
-			bone.worldY += (temp[1] - bone.worldY) * translateMix;
-		}
-	},
-};
-
-spine.Skin = function (name) {
-	this.name = name;
-	this.attachments = {};
-};
-spine.Skin.prototype = {
-	addAttachment: function (slotIndex, name, attachment) {
-		this.attachments[slotIndex + ":" + name] = attachment;
-	},
-	getAttachment: function (slotIndex, name) {
-		return this.attachments[slotIndex + ":" + name];
-	},
-	_attachAll: function (skeleton, oldSkin) {
-		for (var key in oldSkin.attachments) {
-			var colon = key.indexOf(":");
-			var slotIndex = parseInt(key.substring(0, colon));
-			var name = key.substring(colon + 1);
-			var slot = skeleton.slots[slotIndex];
-			if (slot.attachment && slot.attachment.name == name) {
-				var attachment = this.getAttachment(slotIndex, name);
-				if (attachment) slot.setAttachment(attachment);
-			}
-		}
-	}
-};
-
-spine.Animation = function (name, timelines, duration) {
-	this.name = name;
-	this.timelines = timelines;
-	this.duration = duration;
-};
-spine.Animation.prototype = {
-	apply: function (skeleton, lastTime, time, loop, events) {
-		if (loop && this.duration != 0) {
-			time %= this.duration;
-			if (lastTime > 0) lastTime %= this.duration;
-		}
-		var timelines = this.timelines;
-		for (var i = 0, n = timelines.length; i < n; i++)
-			timelines[i].apply(skeleton, lastTime, time, events, 1);
-	},
-	mix: function (skeleton, lastTime, time, loop, events, alpha) {
-		if (loop && this.duration != 0) {
-			time %= this.duration;
-			if (lastTime > 0) lastTime %= this.duration;
-		}
-		var timelines = this.timelines;
-		for (var i = 0, n = timelines.length; i < n; i++)
-			timelines[i].apply(skeleton, lastTime, time, events, alpha);
-	}
-};
-spine.Animation.binarySearch = function (values, target, step) {
-	var low = 0;
-	var high = Math.floor(values.length / step) - 2;
-	if (!high) return step;
-	var current = high >>> 1;
-	while (true) {
-		if (values[(current + 1) * step] <= target)
-			low = current + 1;
-		else
-			high = current;
-		if (low == high) return (low + 1) * step;
-		current = (low + high) >>> 1;
-	}
-};
-spine.Animation.binarySearch1 = function (values, target) {
-	var low = 0;
-	var high = values.length - 2;
-	if (!high) return 1;
-	var current = high >>> 1;
-	while (true) {
-		if (values[current + 1] <= target)
-			low = current + 1;
-		else
-			high = current;
-		if (low == high) return low + 1;
-		current = (low + high) >>> 1;
-	}
-};
-spine.Animation.linearSearch = function (values, target, step) {
-	for (var i = 0, last = values.length - step; i <= last; i += step)
-		if (values[i] > target) return i;
-	return -1;
-};
-
-spine.Curves = function (frameCount) {
-	var count = (frameCount - 1) * 19/*BEZIER_SIZE*/;
-	this.curves = new spine.Float32Array(count); // type, x, y, ...
-	this.curves.length = count;
-};
-spine.Curves.prototype = {
-	setLinear: function (frameIndex) {
-		this.curves[frameIndex * 19/*BEZIER_SIZE*/] = 0/*LINEAR*/;
-	},
-	setStepped: function (frameIndex) {
-		this.curves[frameIndex * 19/*BEZIER_SIZE*/] = 1/*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. */
-	setCurve: function (frameIndex, cx1, cy1, cx2, cy2) {
-		var subdiv1 = 1 / 10/*BEZIER_SEGMENTS*/, subdiv2 = subdiv1 * subdiv1, subdiv3 = subdiv2 * subdiv1;
-		var pre1 = 3 * subdiv1, pre2 = 3 * subdiv2, pre4 = 6 * subdiv2, pre5 = 6 * subdiv3;
-		var tmp1x = -cx1 * 2 + cx2, tmp1y = -cy1 * 2 + cy2, tmp2x = (cx1 - cx2) * 3 + 1, tmp2y = (cy1 - cy2) * 3 + 1;
-		var dfx = cx1 * pre1 + tmp1x * pre2 + tmp2x * subdiv3, dfy = cy1 * pre1 + tmp1y * pre2 + tmp2y * subdiv3;
-		var ddfx = tmp1x * pre4 + tmp2x * pre5, ddfy = tmp1y * pre4 + tmp2y * pre5;
-		var dddfx = tmp2x * pre5, dddfy = tmp2y * pre5;
-
-		var i = frameIndex * 19/*BEZIER_SIZE*/;
-		var curves = this.curves;
-		curves[i++] = 2/*BEZIER*/;
-
-		var x = dfx, y = dfy;
-		for (var n = i + 19/*BEZIER_SIZE*/ - 1; i < n; i += 2) {
-			curves[i] = x;
-			curves[i + 1] = y;
-			dfx += ddfx;
-			dfy += ddfy;
-			ddfx += dddfx;
-			ddfy += dddfy;
-			x += dfx;
-			y += dfy;
-		}
-	},
-	getCurvePercent: function (frameIndex, percent) {
-		percent = percent < 0 ? 0 : (percent > 1 ? 1 : percent);
-		var curves = this.curves;
-		var i = frameIndex * 19/*BEZIER_SIZE*/;
-		var type = curves[i];
-		if (type === 0/*LINEAR*/) return percent;
-		if (type == 1/*STEPPED*/) return 0;
-		i++;
-		var x = 0;
-		for (var start = i, n = i + 19/*BEZIER_SIZE*/ - 1; i < n; i += 2) {
-			x = curves[i];
-			if (x >= percent) {
-				var prevX, prevY;
-				if (i == start) {
-					prevX = 0;
-					prevY = 0;
-				} else {
-					prevX = curves[i - 2];
-					prevY = curves[i - 1];
-				}
-				return prevY + (curves[i + 1] - prevY) * (percent - prevX) / (x - prevX);
-			}
-		}
-		var y = curves[i - 1];
-		return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1.
-	}
-};
-
-spine.RotateTimeline = function (frameCount) {
-	this.curves = new spine.Curves(frameCount);
-	this.frames = new spine.Float32Array(frameCount * 2); // time, angle, ...
-	this.frames.length = frameCount * 2;
-};
-spine.RotateTimeline.prototype = {
-	boneIndex: 0,
-	getFrameCount: function () {
-		return this.frames.length / 2;
-	},
-	setFrame: function (frameIndex, time, angle) {
-		frameIndex *= 2;
-		this.frames[frameIndex] = time;
-		this.frames[frameIndex + 1] = angle;
-	},
-	apply: function (skeleton, lastTime, time, firedEvents, alpha) {
-		var frames = this.frames;
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var bone = skeleton.bones[this.boneIndex];
-
-		if (time >= frames[frames.length - 2]) { // Time is after last frame.
-			var amount = bone.data.rotation + frames[frames.length - 1] - 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 frameIndex = spine.Animation.binarySearch(frames, time, 2);
-		var prevFrameValue = frames[frameIndex - 1];
-		var frameTime = frames[frameIndex];
-		var percent = 1 - (time - frameTime) / (frames[frameIndex - 2/*PREV_FRAME_TIME*/] - frameTime);
-		percent = this.curves.getCurvePercent(frameIndex / 2 - 1, percent);
-
-		var amount = frames[frameIndex + 1/*FRAME_VALUE*/] - prevFrameValue;
-		while (amount > 180)
-			amount -= 360;
-		while (amount < -180)
-			amount += 360;
-		amount = bone.data.rotation + (prevFrameValue + amount * percent) - bone.rotation;
-		while (amount > 180)
-			amount -= 360;
-		while (amount < -180)
-			amount += 360;
-		bone.rotation += amount * alpha;
-	}
-};
-
-spine.TranslateTimeline = function (frameCount) {
-	this.curves = new spine.Curves(frameCount);
-	this.frames = new spine.Float32Array(frameCount * 3); // time, x, y, ...
-	this.frames.length = frameCount * 3;
-};
-spine.TranslateTimeline.prototype = {
-	boneIndex: 0,
-	getFrameCount: function () {
-		return this.frames.length / 3;
-	},
-	setFrame: function (frameIndex, time, x, y) {
-		frameIndex *= 3;
-		this.frames[frameIndex] = time;
-		this.frames[frameIndex + 1] = x;
-		this.frames[frameIndex + 2] = y;
-	},
-	apply: function (skeleton, lastTime, time, firedEvents, alpha) {
-		var frames = this.frames;
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var bone = skeleton.bones[this.boneIndex];
-
-		if (time >= frames[frames.length - 3]) { // Time is after last frame.
-			bone.x += (bone.data.x + frames[frames.length - 2] - bone.x) * alpha;
-			bone.y += (bone.data.y + frames[frames.length - 1] - bone.y) * alpha;
-			return;
-		}
-
-		// Interpolate between the previous frame and the current frame.
-		var frameIndex = spine.Animation.binarySearch(frames, time, 3);
-		var prevFrameX = frames[frameIndex - 2];
-		var prevFrameY = frames[frameIndex - 1];
-		var frameTime = frames[frameIndex];
-		var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*PREV_FRAME_TIME*/] - frameTime);
-		percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent);
-
-		bone.x += (bone.data.x + prevFrameX + (frames[frameIndex + 1/*FRAME_X*/] - prevFrameX) * percent - bone.x) * alpha;
-		bone.y += (bone.data.y + prevFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - prevFrameY) * percent - bone.y) * alpha;
-	}
-};
-
-spine.ScaleTimeline = function (frameCount) {
-	this.curves = new spine.Curves(frameCount);
-	this.frames = new spine.Float32Array(frameCount * 3); // time, x, y, ...
-	this.frames.length = frameCount * 3;
-};
-spine.ScaleTimeline.prototype = {
-	boneIndex: 0,
-	getFrameCount: function () {
-		return this.frames.length / 3;
-	},
-	setFrame: function (frameIndex, time, x, y) {
-		frameIndex *= 3;
-		this.frames[frameIndex] = time;
-		this.frames[frameIndex + 1] = x;
-		this.frames[frameIndex + 2] = y;
-	},
-	apply: function (skeleton, lastTime, time, firedEvents, alpha) {
-		var frames = this.frames;
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var bone = skeleton.bones[this.boneIndex];
-
-		if (time >= frames[frames.length - 3]) { // Time is after last frame.
-			bone.scaleX += (bone.data.scaleX * frames[frames.length - 2] - bone.scaleX) * alpha;
-			bone.scaleY += (bone.data.scaleY * frames[frames.length - 1] - bone.scaleY) * alpha;
-			return;
-		}
-
-		// Interpolate between the previous frame and the current frame.
-		var frameIndex = spine.Animation.binarySearch(frames, time, 3);
-		var prevFrameX = frames[frameIndex - 2];
-		var prevFrameY = frames[frameIndex - 1];
-		var frameTime = frames[frameIndex];
-		var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*PREV_FRAME_TIME*/] - frameTime);
-		percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent);
-
-		bone.scaleX += (bone.data.scaleX * (prevFrameX + (frames[frameIndex + 1/*FRAME_X*/] - prevFrameX) * percent) - bone.scaleX) * alpha;
-		bone.scaleY += (bone.data.scaleY * (prevFrameY + (frames[frameIndex + 2/*FRAME_Y*/] - prevFrameY) * percent) - bone.scaleY) * alpha;
-	}
-};
-
-spine.ColorTimeline = function (frameCount) {
-	this.curves = new spine.Curves(frameCount);
-	this.frames = new spine.Float32Array(frameCount * 5); // time, r, g, b, a, ...
-	this.frames.length = frameCount * 5;
-};
-spine.ColorTimeline.prototype = {
-	slotIndex: 0,
-	getFrameCount: function () {
-		return this.frames.length / 5;
-	},
-	setFrame: function (frameIndex, time, r, g, b, a) {
-		frameIndex *= 5;
-		this.frames[frameIndex] = time;
-		this.frames[frameIndex + 1] = r;
-		this.frames[frameIndex + 2] = g;
-		this.frames[frameIndex + 3] = b;
-		this.frames[frameIndex + 4] = a;
-	},
-	apply: function (skeleton, lastTime, time, firedEvents, alpha) {
-		var frames = this.frames;
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var r, g, b, a;
-		if (time >= frames[frames.length - 5]) {
-			// Time is after last frame.
-			var i = frames.length - 1;
-			r = frames[i - 3];
-			g = frames[i - 2];
-			b = frames[i - 1];
-			a = frames[i];
-		} else {
-			// Interpolate between the previous frame and the current frame.
-			var frameIndex = spine.Animation.binarySearch(frames, time, 5);
-			var prevFrameR = frames[frameIndex - 4];
-			var prevFrameG = frames[frameIndex - 3];
-			var prevFrameB = frames[frameIndex - 2];
-			var prevFrameA = frames[frameIndex - 1];
-			var frameTime = frames[frameIndex];
-			var percent = 1 - (time - frameTime) / (frames[frameIndex - 5/*PREV_FRAME_TIME*/] - frameTime);
-			percent = this.curves.getCurvePercent(frameIndex / 5 - 1, percent);
-
-			r = prevFrameR + (frames[frameIndex + 1/*FRAME_R*/] - prevFrameR) * percent;
-			g = prevFrameG + (frames[frameIndex + 2/*FRAME_G*/] - prevFrameG) * percent;
-			b = prevFrameB + (frames[frameIndex + 3/*FRAME_B*/] - prevFrameB) * percent;
-			a = prevFrameA + (frames[frameIndex + 4/*FRAME_A*/] - prevFrameA) * percent;
-		}
-		var slot = skeleton.slots[this.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;
-		}
-	}
-};
-
-spine.AttachmentTimeline = function (frameCount) {
-	this.curves = new spine.Curves(frameCount);
-	this.frames = new spine.Float32Array(frameCount); // time, ...
-	this.frames.length = frameCount;
-	this.attachmentNames = [];
-	this.attachmentNames.length = frameCount;
-};
-spine.AttachmentTimeline.prototype = {
-	slotIndex: 0,
-	getFrameCount: function () {
-		return this.frames.length;
-	},
-	setFrame: function (frameIndex, time, attachmentName) {
-		this.frames[frameIndex] = time;
-		this.attachmentNames[frameIndex] = attachmentName;
-	},
-	apply: function (skeleton, lastTime, time, firedEvents, alpha) {
-		var frames = this.frames;
-		if (time < frames[0]) {
-			if (lastTime > time) this.apply(skeleton, lastTime, Number.MAX_VALUE, null, 0);
-			return;
-		} else if (lastTime > time) //
-			lastTime = -1;
-
-		var frameIndex = time >= frames[frames.length - 1] ? frames.length - 1 : spine.Animation.binarySearch1(frames, time) - 1;
-		if (frames[frameIndex] < lastTime) return;
-
-		var attachmentName = this.attachmentNames[frameIndex];
-		skeleton.slots[this.slotIndex].setAttachment(
-			!attachmentName ? null : skeleton.getAttachmentBySlotIndex(this.slotIndex, attachmentName));
-	}
-};
-
-spine.EventTimeline = function (frameCount) {
-	this.frames = new spine.Float32Array(frameCount); // time, ...
-	this.frames.length = frameCount;
-	this.events = [];
-	this.events.length = frameCount;
-};
-spine.EventTimeline.prototype = {
-	getFrameCount: function () {
-		return this.frames.length;
-	},
-	setFrame: function (frameIndex, event) {
-		this.frames[frameIndex] = event.time;
-		this.events[frameIndex] = event;
-	},
-	/** Fires events for frames > lastTime and <= time. */
-	apply: function (skeleton, lastTime, time, firedEvents, alpha) {
-		if (!firedEvents) return;
-
-		var frames = this.frames;
-		var frameCount = frames.length;
-
-		if (lastTime > time) { // Fire events after last time for looped animations.
-			this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha);
-			lastTime = -1;
-		} else if (lastTime >= frames[frameCount - 1]) // Last time is after last frame.
-			return;
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var frameIndex;
-		if (lastTime < frames[0])
-			frameIndex = 0;
-		else {
-			frameIndex = spine.Animation.binarySearch1(frames, lastTime);
-			var frame = frames[frameIndex];
-			while (frameIndex > 0) { // Fire multiple events with the same frame.
-				if (frames[frameIndex - 1] != frame) break;
-				frameIndex--;
-			}
-		}
-		var events = this.events;
-		for (; frameIndex < frameCount && time >= frames[frameIndex]; frameIndex++)
-			firedEvents[firedEvents.length] = events[frameIndex];
-	}
-};
-
-spine.DrawOrderTimeline = function (frameCount) {
-	this.frames = new spine.Float32Array(frameCount); // time, ...
-	this.frames.length = frameCount;
-	this.drawOrders = [];
-	this.drawOrders.length = frameCount;
-};
-spine.DrawOrderTimeline.prototype = {
-	getFrameCount: function () {
-		return this.frames.length;
-	},
-	setFrame: function (frameIndex, time, drawOrder) {
-		this.frames[frameIndex] = time;
-		this.drawOrders[frameIndex] = drawOrder;
-	},
-	apply: function (skeleton, lastTime, time, firedEvents, alpha) {
-		var frames = this.frames;
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var frameIndex;
-		if (time >= frames[frames.length - 1]) // Time is after last frame.
-			frameIndex = frames.length - 1;
-		else
-			frameIndex = spine.Animation.binarySearch1(frames, time) - 1;
-
-		var drawOrder = skeleton.drawOrder;
-		var slots = skeleton.slots;
-		var drawOrderToSetupIndex = this.drawOrders[frameIndex];
-		if (!drawOrderToSetupIndex) {
-			for (var i = 0, n = slots.length; i < n; i++)
-				drawOrder[i] = slots[i];
-		} else {
-			for (var i = 0, n = drawOrderToSetupIndex.length; i < n; i++)
-				drawOrder[i] = skeleton.slots[drawOrderToSetupIndex[i]];
-		}
-
-	}
-};
-
-spine.FfdTimeline = function (frameCount) {
-	this.curves = new spine.Curves(frameCount);
-	this.frames = new spine.Float32Array(frameCount);
-	this.frames.length = frameCount;
-	this.frameVertices = [];
-	this.frameVertices.length = frameCount;
-};
-spine.FfdTimeline.prototype = {
-	slotIndex: 0,
-	attachment: 0,
-	getFrameCount: function () {
-		return this.frames.length;
-	},
-	setFrame: function (frameIndex, time, vertices) {
-		this.frames[frameIndex] = time;
-		this.frameVertices[frameIndex] = vertices;
-	},
-	apply: function (skeleton, lastTime, time, firedEvents, alpha) {
-		var slot = skeleton.slots[this.slotIndex];
-		var slotAttachment = slot.attachment;
-		if (!slotAttachment) return;
-		if (slotAttachment != this.attachment && (!slotAttachment.inheritFFD || slotAttachment.parentMesh != this.attachment)) return;
-
-		var frames = this.frames;
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var frameVertices = this.frameVertices;
-		var vertexCount = frameVertices[0].length;
-
-		var vertices = slot.attachmentVertices;
-		if (vertices.length != vertexCount) {
-			slot.attachmentVertices = vertices = new spine.Float32Array(vertexCount);
-			alpha = 1;
-		}
-
-		if (time >= frames[frames.length - 1]) { // Time is after last frame.
-			var lastVertices = frameVertices[frames.length - 1];
-			if (alpha < 1) {
-				for (var i = 0; i < vertexCount; i++)
-					vertices[i] += (lastVertices[i] - vertices[i]) * alpha;
-			} else {
-				for (var i = 0; i < vertexCount; i++)
-					vertices[i] = lastVertices[i];
-			}
-			return;
-		}
-
-		// Interpolate between the previous frame and the current frame.
-		var frameIndex = spine.Animation.binarySearch1(frames, time);
-		var frameTime = frames[frameIndex];
-		var percent = 1 - (time - frameTime) / (frames[frameIndex - 1] - frameTime);
-		percent = this.curves.getCurvePercent(frameIndex - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
-
-		var prevVertices = frameVertices[frameIndex - 1];
-		var nextVertices = frameVertices[frameIndex];
-
-		if (alpha < 1) {
-			for (var i = 0; i < vertexCount; i++) {
-				var prev = prevVertices[i];
-				vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha;
-			}
-		} else {
-			for (var i = 0; i < vertexCount; i++) {
-				var prev = prevVertices[i];
-				vertices[i] = prev + (nextVertices[i] - prev) * percent;
-			}
-		}
-	}
-};
-
-spine.IkConstraintTimeline = function (frameCount) {
-	this.curves = new spine.Curves(frameCount);
-	this.frames = new spine.Float32Array(frameCount * 3); // time, mix, bendDirection, ...
-	this.frames.length = frameCount * 3;
-};
-spine.IkConstraintTimeline.prototype = {
-	ikConstraintIndex: 0,
-	getFrameCount: function () {
-		return this.frames.length / 3;
-	},
-	setFrame: function (frameIndex, time, mix, bendDirection) {
-		frameIndex *= 3;
-		this.frames[frameIndex] = time;
-		this.frames[frameIndex + 1] = mix;
-		this.frames[frameIndex + 2] = bendDirection;
-	},
-	apply: function (skeleton, lastTime, time, firedEvents, alpha) {
-		var frames = this.frames;
-		if (time < frames[0]) return; // Time is before first frame.
-
-		var ikConstraint = skeleton.ikConstraints[this.ikConstraintIndex];
-
-		if (time >= frames[frames.length - 3]) { // Time is after last frame.
-			ikConstraint.mix += (frames[frames.length - 2] - ikConstraint.mix) * alpha;
-			ikConstraint.bendDirection = frames[frames.length - 1];
-			return;
-		}
-
-		// Interpolate between the previous frame and the current frame.
-		var frameIndex = spine.Animation.binarySearch(frames, time, 3);
-		var prevFrameMix = frames[frameIndex + -2/*PREV_FRAME_MIX*/];
-		var frameTime = frames[frameIndex];
-		var percent = 1 - (time - frameTime) / (frames[frameIndex + -3/*PREV_FRAME_TIME*/] - frameTime);
-		percent = this.curves.getCurvePercent(frameIndex / 3 - 1, percent);
-
-		var mix = prevFrameMix + (frames[frameIndex + 1/*FRAME_MIX*/] - prevFrameMix) * percent;
-		ikConstraint.mix += (mix - ikConstraint.mix) * alpha;
-		ikConstraint.bendDirection = frames[frameIndex + -1/*PREV_FRAME_BEND_DIRECTION*/];
-	}
-};
-
-spine.SkeletonData = function () {
-	this.bones = [];
-	this.slots = [];
-	this.skins = [];
-	this.events = [];
-	this.animations = [];
-	this.ikConstraints = [];
-	this.transformConstraints = [];
-};
-spine.SkeletonData.prototype = {
-	name: null,
-	defaultSkin: null,
-	width: 0, height: 0,
-	version: null, hash: null,
-	/** @return May be null. */
-	findBone: function (boneName) {
-		var bones = this.bones;
-		for (var i = 0, n = bones.length; i < n; i++)
-			if (bones[i].name == boneName) return bones[i];
-		return null;
-	},
-	/** @return -1 if the bone was not found. */
-	findBoneIndex: function (boneName) {
-		var bones = this.bones;
-		for (var i = 0, n = bones.length; i < n; i++)
-			if (bones[i].name == boneName) return i;
-		return -1;
-	},
-	/** @return May be null. */
-	findSlot: function (slotName) {
-		var slots = this.slots;
-		for (var i = 0, n = slots.length; i < n; i++) {
-			if (slots[i].name == slotName) return slot[i];
-		}
-		return null;
-	},
-	/** @return -1 if the bone was not found. */
-	findSlotIndex: function (slotName) {
-		var slots = this.slots;
-		for (var i = 0, n = slots.length; i < n; i++)
-			if (slots[i].name == slotName) return i;
-		return -1;
-	},
-	/** @return May be null. */
-	findSkin: function (skinName) {
-		var skins = this.skins;
-		for (var i = 0, n = skins.length; i < n; i++)
-			if (skins[i].name == skinName) return skins[i];
-		return null;
-	},
-	/** @return May be null. */
-	findEvent: function (eventName) {
-		var events = this.events;
-		for (var i = 0, n = events.length; i < n; i++)
-			if (events[i].name == eventName) return events[i];
-		return null;
-	},
-	/** @return May be null. */
-	findAnimation: function (animationName) {
-		var animations = this.animations;
-		for (var i = 0, n = animations.length; i < n; i++)
-			if (animations[i].name == animationName) return animations[i];
-		return null;
-	},
-	/** @return May be null. */
-	findIkConstraint: function (constraintName) {
-		var ikConstraints = this.ikConstraints;
-		for (var i = 0, n = ikConstraints.length; i < n; i++)
-			if (ikConstraints[i].name == constraintName) return ikConstraints[i];
-		return null;
-	},
-	/** @return May be null. */
-	findTransformConstraints: function (constraintName) {
-		var transformConstraints = this.transformConstraints;
-		for (var i = 0, n = transformConstraints.length; i < n; i++)
-			if (transformConstraints[i].name == constraintName) return transformConstraints[i];
-		return null;
-	}
-};
-
-spine.Skeleton = function (skeletonData) {
-	this.data = skeletonData;
-
-	this.bones = [];
-	for (var i = 0, n = skeletonData.bones.length; i < n; i++) {
-		var boneData = skeletonData.bones[i];
-		var parent = !boneData.parent ? null : this.bones[skeletonData.bones.indexOf(boneData.parent)];
-		this.bones[i] = new spine.Bone(boneData, this, parent);
-	}
-
-	this.slots = [];
-	this.drawOrder = [];
-	for (var i = 0, n = skeletonData.slots.length; i < n; i++) {
-		var slotData = skeletonData.slots[i];
-		var bone = this.bones[skeletonData.bones.indexOf(slotData.boneData)];
-		var slot = new spine.Slot(slotData, bone);
-		this.slots[i] = slot;
-		this.drawOrder[i] = slot;
-	}
-
-	this.ikConstraints = [];
-	for (var i = 0, n = skeletonData.ikConstraints.length; i < n; i++)
-		this.ikConstraints[i] = new spine.IkConstraint(skeletonData.ikConstraints[i], this);
-
-	this.transformConstraints = [];
-	for (var i = 0, n = skeletonData.transformConstraints.length; i < n; i++)
-		this.transformConstraints[i] = new spine.TransformConstraint(skeletonData.transformConstraints[i], this);
-
-	this.cache = [];
-	this.updateCache();
-};
-spine.Skeleton.prototype = {
-	x: 0, y: 0,
-	skin: null,
-	r: 1, g: 1, b: 1, a: 1,
-	time: 0,
-	flipX: false, flipY: false,
-	/** Caches information about bones and constraints. Must be called if bones or constraints are added or removed. */
-	updateCache: function () {
-		var bones = this.bones;
-		var updateCache = this.cache;
-		var ikConstraints = this.ikConstraints;
-		var transformConstraints = this.transformConstraints;
-		var ikConstraintsCount = ikConstraints.length;
-		var transformConstraintsCount = transformConstraints.length;
-		updateCache.length = 0;
-
-		for (var i = 0, n = bones.length; i < n; i++) {
-			var bone = bones[i];
-			updateCache[updateCache.length] = bone;
-			for (var ii = 0; ii < ikConstraintsCount; ii++) {
-				var ikConstraint = ikConstraints[ii];
-				if (bone == ikConstraint.bones[ikConstraint.bones.length - 1]) {
-					updateCache[updateCache.length] = ikConstraint;
-					break;
-				}
-			}
-		}
-
-		for (var i = 0; i < transformConstraintsCount; i++) {
-			var transformConstraint = transformConstraints[i];
-			for (var ii = updateCache.length - 1; ii >= 0; ii--) {
-				var object = updateCache[ii];
-				if (object == transformConstraint.bone || object == transformConstraint.target) {
-					updateCache.splice(ii + 1, 0, transformConstraint);
-					break;
-				}
-			}
-		}
-	},
-	/** Updates the world transform for each bone and applies constraints. */
-	updateWorldTransform: function () {
-		var updateCache = this.cache;
-		for (var i = 0, n = updateCache.length; i < n; i++)
-			updateCache[i].update();
-	},
-	/** Sets the bones, constraints, and slots to their setup pose values. */
-	setToSetupPose: function () {
-		this.setBonesToSetupPose();
-		this.setSlotsToSetupPose();
-	},
-	/** Sets the bones and constraints to their setup pose values. */
-	setBonesToSetupPose: function () {
-		var bones = this.bones;
-		for (var i = 0, n = bones.length; i < n; i++)
-			bones[i].setToSetupPose();
-
-		var ikConstraints = this.ikConstraints;
-		for (var i = 0, n = ikConstraints.length; i < n; i++) {
-			var constraint = ikConstraints[i];
-			constraint.bendDirection = constraint.data.bendDirection;
-			constraint.mix = constraint.data.mix;
-		}
-
-		var transformConstraints = this.transformConstraints;
-		for (var i = 0, n = transformConstraints.length; i < n; i++) {
-			var constraint = transformConstraints[i];
-			constraint.translateMix = constraint.data.translateMix;
-			constraint.x = constraint.data.x;
-			constraint.y = constraint.data.y;
-		}
-	},
-	setSlotsToSetupPose: function () {
-		var slots = this.slots;
-		var drawOrder = this.drawOrder;
-		for (var i = 0, n = slots.length; i < n; i++) {
-			drawOrder[i] = slots[i];
-			slots[i].setToSetupPose(i);
-		}
-	},
-	/** @return May return null. */
-	getRootBone: function () {
-		return this.bones.length ? this.bones[0] : null;
-	},
-	/** @return May be null. */
-	findBone: function (boneName) {
-		var bones = this.bones;
-		for (var i = 0, n = bones.length; i < n; i++)
-			if (bones[i].data.name == boneName) return bones[i];
-		return null;
-	},
-	/** @return -1 if the bone was not found. */
-	findBoneIndex: function (boneName) {
-		var bones = this.bones;
-		for (var i = 0, n = bones.length; i < n; i++)
-			if (bones[i].data.name == boneName) return i;
-		return -1;
-	},
-	/** @return May be null. */
-	findSlot: function (slotName) {
-		var slots = this.slots;
-		for (var i = 0, n = slots.length; i < n; i++)
-			if (slots[i].data.name == slotName) return slots[i];
-		return null;
-	},
-	/** @return -1 if the bone was not found. */
-	findSlotIndex: function (slotName) {
-		var slots = this.slots;
-		for (var i = 0, n = slots.length; i < n; i++)
-			if (slots[i].data.name == slotName) return i;
-		return -1;
-	},
-	setSkinByName: function (skinName) {
-		var skin = this.data.findSkin(skinName);
-		if (!skin) throw "Skin not found: " + skinName;
-		this.setSkin(skin);
-	},
-	/** 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. */
-	setSkin: function (newSkin) {
-		if (newSkin) {
-			if (this.skin)
-				newSkin._attachAll(this, this.skin);
-			else {
-				var slots = this.slots;
-				for (var i = 0, n = slots.length; i < n; i++) {
-					var slot = slots[i];
-					var name = slot.data.attachmentName;
-					if (name) {
-						var attachment = newSkin.getAttachment(i, name);
-						if (attachment) slot.setAttachment(attachment);
-					}
-				}
-			}
-		}
-		this.skin = newSkin;
-	},
-	/** @return May be null. */
-	getAttachmentBySlotName: function (slotName, attachmentName) {
-		return this.getAttachmentBySlotIndex(this.data.findSlotIndex(slotName), attachmentName);
-	},
-	/** @return May be null. */
-	getAttachmentBySlotIndex: function (slotIndex, attachmentName) {
-		if (this.skin) {
-			var attachment = this.skin.getAttachment(slotIndex, attachmentName);
-			if (attachment) return attachment;
-		}
-		if (this.data.defaultSkin) return this.data.defaultSkin.getAttachment(slotIndex, attachmentName);
-		return null;
-	},
-	/** @param attachmentName May be null. */
-	setAttachment: function (slotName, attachmentName) {
-		var slots = this.slots;
-		for (var i = 0, n = slots.length; i < n; i++) {
-			var slot = slots[i];
-			if (slot.data.name == slotName) {
-				var attachment = null;
-				if (attachmentName) {
-					attachment = this.getAttachmentBySlotIndex(i, attachmentName);
-					if (!attachment) throw "Attachment not found: " + attachmentName + ", for slot: " + slotName;
-				}
-				slot.setAttachment(attachment);
-				return;
-			}
-		}
-		throw "Slot not found: " + slotName;
-	},
-	/** @return May be null. */
-	findIkConstraint: function (constraintName) {
-		var ikConstraints = this.ikConstraints;
-		for (var i = 0, n = ikConstraints.length; i < n; i++)
-			if (ikConstraints[i].data.name == constraintName) return ikConstraints[i];
-		return null;
-	},
-	/** @return May be null. */
-	findTransformConstraint: function (constraintName) {
-		var transformConstraints = this.transformConstraints;
-		for (var i = 0, n = transformConstraints.length; i < n; i++)
-			if (transformConstraints[i].data.name == constraintName) return transformConstraints[i];
-		return null;
-	},
-	update: function (delta) {
-		this.time += delta;
-	}
-};
-
-spine.EventData = function (name) {
-	this.name = name;
-};
-spine.EventData.prototype = {
-	intValue: 0,
-	floatValue: 0,
-	stringValue: null
-};
-
-spine.Event = function (time, data) {
-	this.time = time;
-	this.data = data;
-};
-spine.Event.prototype = {
-	intValue: 0,
-	floatValue: 0,
-	stringValue: null
-};
-
-spine.AttachmentType = {
-	region: 0,
-	boundingbox: 1,
-	mesh: 2,
-	weightedmesh: 3,
-	linkedmesh: 4,
-	weightedlinkedmesh: 5
-};
-
-spine.RegionAttachment = function (name) {
-	this.name = name;
-	this.offset = new spine.Float32Array(8);
-	this.offset.length = 8;
-	this.uvs = new spine.Float32Array(8);
-	this.uvs.length = 8;
-};
-spine.RegionAttachment.prototype = {
-	type: spine.AttachmentType.region,
-	x: 0, y: 0,
-	rotation: 0,
-	scaleX: 1, scaleY: 1,
-	width: 0, height: 0,
-	r: 1, g: 1, b: 1, a: 1,
-	path: null,
-	rendererObject: null,
-	regionOffsetX: 0, regionOffsetY: 0,
-	regionWidth: 0, regionHeight: 0,
-	regionOriginalWidth: 0, regionOriginalHeight: 0,
-	setUVs: function (u, v, u2, v2, rotate) {
-		var uvs = this.uvs;
-		if (rotate) {
-			uvs[2/*X2*/] = u;
-			uvs[3/*Y2*/] = v2;
-			uvs[4/*X3*/] = u;
-			uvs[5/*Y3*/] = v;
-			uvs[6/*X4*/] = u2;
-			uvs[7/*Y4*/] = v;
-			uvs[0/*X1*/] = u2;
-			uvs[1/*Y1*/] = v2;
-		} else {
-			uvs[0/*X1*/] = u;
-			uvs[1/*Y1*/] = v2;
-			uvs[2/*X2*/] = u;
-			uvs[3/*Y2*/] = v;
-			uvs[4/*X3*/] = u2;
-			uvs[5/*Y3*/] = v;
-			uvs[6/*X4*/] = u2;
-			uvs[7/*Y4*/] = v2;
-		}
-	},
-	updateOffset: function () {
-		var regionScaleX = this.width / this.regionOriginalWidth * this.scaleX;
-		var regionScaleY = this.height / this.regionOriginalHeight * this.scaleY;
-		var localX = -this.width / 2 * this.scaleX + this.regionOffsetX * regionScaleX;
-		var localY = -this.height / 2 * this.scaleY + this.regionOffsetY * regionScaleY;
-		var localX2 = localX + this.regionWidth * regionScaleX;
-		var localY2 = localY + this.regionHeight * regionScaleY;
-		var radians = this.rotation * spine.degRad;
-		var cos = Math.cos(radians);
-		var sin = Math.sin(radians);
-		var localXCos = localX * cos + this.x;
-		var localXSin = localX * sin;
-		var localYCos = localY * cos + this.y;
-		var localYSin = localY * sin;
-		var localX2Cos = localX2 * cos + this.x;
-		var localX2Sin = localX2 * sin;
-		var localY2Cos = localY2 * cos + this.y;
-		var localY2Sin = localY2 * sin;
-		var offset = this.offset;
-		offset[0/*X1*/] = localXCos - localYSin;
-		offset[1/*Y1*/] = localYCos + localXSin;
-		offset[2/*X2*/] = localXCos - localY2Sin;
-		offset[3/*Y2*/] = localY2Cos + localXSin;
-		offset[4/*X3*/] = localX2Cos - localY2Sin;
-		offset[5/*Y3*/] = localY2Cos + localX2Sin;
-		offset[6/*X4*/] = localX2Cos - localYSin;
-		offset[7/*Y4*/] = localYCos + localX2Sin;
-	},
-	computeVertices: function (x, y, bone, vertices) {
-		x += bone.worldX;
-		y += bone.worldY;
-		var m00 = bone.a, m01 = bone.b, m10 = bone.c, m11 = bone.d;
-		var offset = this.offset;
-		vertices[0/*X1*/] = offset[0/*X1*/] * m00 + offset[1/*Y1*/] * m01 + x;
-		vertices[1/*Y1*/] = offset[0/*X1*/] * m10 + offset[1/*Y1*/] * m11 + y;
-		vertices[2/*X2*/] = offset[2/*X2*/] * m00 + offset[3/*Y2*/] * m01 + x;
-		vertices[3/*Y2*/] = offset[2/*X2*/] * m10 + offset[3/*Y2*/] * m11 + y;
-		vertices[4/*X3*/] = offset[4/*X3*/] * m00 + offset[5/*X3*/] * m01 + x;
-		vertices[5/*X3*/] = offset[4/*X3*/] * m10 + offset[5/*X3*/] * m11 + y;
-		vertices[6/*X4*/] = offset[6/*X4*/] * m00 + offset[7/*Y4*/] * m01 + x;
-		vertices[7/*Y4*/] = offset[6/*X4*/] * m10 + offset[7/*Y4*/] * m11 + y;
-	}
-};
-
-spine.MeshAttachment = function (name) {
-	this.name = name;
-};
-spine.MeshAttachment.prototype = {
-	type: spine.AttachmentType.mesh,
-	vertices: null,
-	uvs: null,
-	regionUVs: null,
-	triangles: null,
-	hullLength: 0,
-	r: 1, g: 1, b: 1, a: 1,
-	path: null,
-	inheritFFD: true,
-	parentMesh: null,
-	rendererObject: null,
-	regionU: 0, regionV: 0, regionU2: 0, regionV2: 0, regionRotate: false,
-	regionOffsetX: 0, regionOffsetY: 0,
-	regionWidth: 0, regionHeight: 0,
-	regionOriginalWidth: 0, regionOriginalHeight: 0,
-	edges: null,
-	width: 0, height: 0,
-	updateUVs: function () {
-		var width = this.regionU2 - this.regionU, height = this.regionV2 - this.regionV;
-		var n = this.regionUVs.length;
-		if (!this.uvs || this.uvs.length != n) this.uvs = new spine.Float32Array(n);
-		if (this.regionRotate) {
-			for (var i = 0; i < n; i += 2) {
-				this.uvs[i] = this.regionU + this.regionUVs[i + 1] * width;
-				this.uvs[i + 1] = this.regionV + height - this.regionUVs[i] * height;
-			}
-		} else {
-			for (var i = 0; i < n; i += 2) {
-				this.uvs[i] = this.regionU + this.regionUVs[i] * width;
-				this.uvs[i + 1] = this.regionV + this.regionUVs[i + 1] * height;
-			}
-		}
-	},
-	computeWorldVertices: function (x, y, slot, worldVertices) {
-		var bone = slot.bone;
-		x += bone.worldX;
-		y += bone.worldY;
-		var m00 = bone.a, m01 = bone.b, m10 = bone.c, m11 = bone.d;
-		var vertices = this.vertices;
-		var verticesCount = vertices.length;
-		if (slot.attachmentVertices.length == verticesCount) vertices = slot.attachmentVertices;
-		for (var i = 0; i < verticesCount; i += 2) {
-			var vx = vertices[i];
-			var vy = vertices[i + 1];
-			worldVertices[i] = vx * m00 + vy * m01 + x;
-			worldVertices[i + 1] = vx * m10 + vy * m11 + y;
-		}
-	},
-	setParentMesh: function (parentMesh) {
-		this.parentMesh = parentMesh;
-		if (parentMesh) {
-			this.vertices = parentMesh.vertices;
-			this.regionUVs = parentMesh.regionUVs;
-			this.triangles = parentMesh.triangles;
-			this.hullLength = parentMesh.hullLength;
-			this.edges = parentMesh.edges;
-			this.width = parentMesh.width;
-			this.height = parentMesh.height;
-		}
-	}
-};
-
-spine.WeightedMeshAttachment = function (name) {
-	this.name = name;
-};
-spine.WeightedMeshAttachment.prototype = {
-	type: spine.AttachmentType.weightedmesh,
-	bones: null,
-	weights: null,
-	uvs: null,
-	regionUVs: null,
-	triangles: null,
-	hullLength: 0,
-	r: 1, g: 1, b: 1, a: 1,
-	path: null,
-	inheritFFD: true,
-	parentMesh: null,
-	rendererObject: null,
-	regionU: 0, regionV: 0, regionU2: 0, regionV2: 0, regionRotate: false,
-	regionOffsetX: 0, regionOffsetY: 0,
-	regionWidth: 0, regionHeight: 0,
-	regionOriginalWidth: 0, regionOriginalHeight: 0,
-	edges: null,
-	width: 0, height: 0,
-	updateUVs: function (u, v, u2, v2, rotate) {
-		var width = this.regionU2 - this.regionU, height = this.regionV2 - this.regionV;
-		var n = this.regionUVs.length;
-		if (!this.uvs || this.uvs.length != n) this.uvs = new spine.Float32Array(n);
-		if (this.regionRotate) {
-			for (var i = 0; i < n; i += 2) {
-				this.uvs[i] = this.regionU + this.regionUVs[i + 1] * width;
-				this.uvs[i + 1] = this.regionV + height - this.regionUVs[i] * height;
-			}
-		} else {
-			for (var i = 0; i < n; i += 2) {
-				this.uvs[i] = this.regionU + this.regionUVs[i] * width;
-				this.uvs[i + 1] = this.regionV + this.regionUVs[i + 1] * height;
-			}
-		}
-	},
-	computeWorldVertices: function (x, y, slot, worldVertices) {
-		var skeletonBones = slot.bone.skeleton.bones;
-		var weights = this.weights;
-		var bones = this.bones;
-
-		var w = 0, v = 0, b = 0, f = 0, n = bones.length, nn;
-		var wx, wy, bone, vx, vy, weight;
-		if (!slot.attachmentVertices.length) {
-			for (; v < n; w += 2) {
-				wx = 0;
-				wy = 0;
-				nn = bones[v++] + v;
-				for (; v < nn; v++, b += 3) {
-					bone = skeletonBones[bones[v]];
-					vx = weights[b];
-					vy = weights[b + 1];
-					weight = weights[b + 2];
-					wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
-					wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
-				}
-				worldVertices[w] = wx + x;
-				worldVertices[w + 1] = wy + y;
-			}
-		} else {
-			var ffd = slot.attachmentVertices;
-			for (; v < n; w += 2) {
-				wx = 0;
-				wy = 0;
-				nn = bones[v++] + v;
-				for (; v < nn; v++, b += 3, f += 2) {
-					bone = skeletonBones[bones[v]];
-					vx = weights[b] + ffd[f];
-					vy = weights[b + 1] + ffd[f + 1];
-					weight = weights[b + 2];
-					wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
-					wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
-				}
-				worldVertices[w] = wx + x;
-				worldVertices[w + 1] = wy + y;
-			}
-		}
-	},
-	setParentMesh: function (parentMesh) {
-		this.parentMesh = parentMesh;
-		if (parentMesh) {
-			this.bones = parentMesh.bones;
-			this.weights = parentMesh.weights;
-			this.regionUVs = parentMesh.regionUVs;
-			this.triangles = parentMesh.triangles;
-			this.hullLength = parentMesh.hullLength;
-			this.edges = parentMesh.edges;
-			this.width = parentMesh.width;
-			this.height = parentMesh.height;
-		}
-	}
-};
-
-spine.BoundingBoxAttachment = function (name) {
-	this.name = name;
-};
-spine.BoundingBoxAttachment.prototype = {
-	type: spine.AttachmentType.boundingbox,
-	computeWorldVertices: function (x, y, bone, worldVertices) {
-		x += bone.worldX;
-		y += bone.worldY;
-		var m00 = bone.a, m01 = bone.b, m10 = bone.c, m11 = bone.d;
-		var vertices = this.vertices;
-		for (var i = 0, n = vertices.length; i < n; i += 2) {
-			var px = vertices[i];
-			var py = vertices[i + 1];
-			worldVertices[i] = px * m00 + py * m01 + x;
-			worldVertices[i + 1] = px * m10 + py * m11 + y;
-		}
-	}
-};
-
-spine.AnimationStateData = function (skeletonData) {
-	this.skeletonData = skeletonData;
-	this.animationToMixTime = {};
-};
-spine.AnimationStateData.prototype = {
-	defaultMix: 0,
-	setMixByName: function (fromName, toName, duration) {
-		var from = this.skeletonData.findAnimation(fromName);
-		if (!from) throw "Animation not found: " + fromName;
-		var to = this.skeletonData.findAnimation(toName);
-		if (!to) throw "Animation not found: " + toName;
-		this.setMix(from, to, duration);
-	},
-	setMix: function (from, to, duration) {
-		this.animationToMixTime[from.name + ":" + to.name] = duration;
-	},
-	getMix: function (from, to) {
-		var key = from.name + ":" + to.name;
-		return this.animationToMixTime.hasOwnProperty(key) ? this.animationToMixTime[key] : this.defaultMix;
-	}
-};
-
-spine.TrackEntry = function () {};
-spine.TrackEntry.prototype = {
-	next: null, previous: null,
-	animation: null,
-	loop: false,
-	delay: 0, time: 0, lastTime: -1, endTime: 0,
-	timeScale: 1,
-	mixTime: 0, mixDuration: 0, mix: 1,
-	onStart: null, onEnd: null, onComplete: null, onEvent: null
-};
-
-spine.AnimationState = function (stateData) {
-	this.data = stateData;
-	this.tracks = [];
-	this.events = [];
-};
-spine.AnimationState.prototype = {
-	onStart: null,
-	onEnd: null,
-	onComplete: null,
-	onEvent: null,
-	timeScale: 1,
-	update: function (delta) {
-		delta *= this.timeScale;
-		for (var i = 0; i < this.tracks.length; i++) {
-			var current = this.tracks[i];
-			if (!current) continue;
-
-			current.time += delta * current.timeScale;
-			if (current.previous) {
-				var previousDelta = delta * current.previous.timeScale;
-				current.previous.time += previousDelta;
-				current.mixTime += previousDelta;
-			}
-
-			var next = current.next;
-			if (next) {
-				next.time = current.lastTime - next.delay;
-				if (next.time >= 0) this.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) this.clearTrack(i);
-			}
-		}
-	},
-	apply: function (skeleton) {
-		for (var i = 0; i < this.tracks.length; i++) {
-			var current = this.tracks[i];
-			if (!current) continue;
-
-			this.events.length = 0;
-
-			var time = current.time;
-			var lastTime = current.lastTime;
-			var endTime = current.endTime;
-			var loop = current.loop;
-			if (!loop && time > endTime) time = endTime;
-
-			var previous = current.previous;
-			if (!previous) {
-				if (current.mix == 1)
-					current.animation.apply(skeleton, current.lastTime, time, loop, this.events);
-				else
-					current.animation.mix(skeleton, current.lastTime, time, loop, this.events, current.mix);
-			} else {
-				var previousTime = previous.time;
-				if (!previous.loop && previousTime > previous.endTime) previousTime = previous.endTime;
-				previous.animation.apply(skeleton, previousTime, previousTime, previous.loop, null);
-
-				var alpha = current.mixTime / current.mixDuration * current.mix;
-				if (alpha >= 1) {
-					alpha = 1;
-					current.previous = null;
-				}
-				current.animation.mix(skeleton, current.lastTime, time, loop, this.events, alpha);
-			}
-
-			for (var ii = 0, nn = this.events.length; ii < nn; ii++) {
-				var event = this.events[ii];
-				if (current.onEvent) current.onEvent(i, event);
-				if (this.onEvent) this.onEvent(i, event);
-			}
-
-			// Check if completed the animation or a loop iteration.
-			if (loop ? (lastTime % endTime > time % endTime) : (lastTime < endTime && time >= endTime)) {
-				var count = Math.floor(time / endTime);
-				if (current.onComplete) current.onComplete(i, count);
-				if (this.onComplete) this.onComplete(i, count);
-			}
-
-			current.lastTime = current.time;
-		}
-	},
-	clearTracks: function () {
-		for (var i = 0, n = this.tracks.length; i < n; i++)
-			this.clearTrack(i);
-		this.tracks.length = 0; 
-	},
-	clearTrack: function (trackIndex) {
-		if (trackIndex >= this.tracks.length) return;
-		var current = this.tracks[trackIndex];
-		if (!current) return;
-
-		if (current.onEnd) current.onEnd(trackIndex);
-		if (this.onEnd) this.onEnd(trackIndex);
-
-		this.tracks[trackIndex] = null;
-	},
-	_expandToIndex: function (index) {
-		if (index < this.tracks.length) return this.tracks[index];
-		while (index >= this.tracks.length)
-			this.tracks[this.tracks.length] = null;
-		return null;
-	},
-	setCurrent: function (index, entry) {
-		var current = this._expandToIndex(index);
-		if (current) {
-			var previous = current.previous;
-			current.previous = null;
-
-			if (current.onEnd) current.onEnd(index);
-			if (this.onEnd) this.onEnd(index);
-
-			entry.mixDuration = this.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 && current.mixTime / current.mixDuration < 0.5)
-					entry.previous = previous;
-				else
-					entry.previous = current;
-			}
-		}
-
-		this.tracks[index] = entry;
-
-		if (entry.onStart) entry.onStart(index);
-		if (this.onStart) this.onStart(index);
-	},
-	setAnimationByName: function (trackIndex, animationName, loop) {
-		var animation = this.data.skeletonData.findAnimation(animationName);
-		if (!animation) throw "Animation not found: " + animationName;
-		return this.setAnimation(trackIndex, animation, loop);
-	},
-	/** Set the current animation. Any queued animations are cleared. */
-	setAnimation: function (trackIndex, animation, loop) {
-		var entry = new spine.TrackEntry();
-		entry.animation = animation;
-		entry.loop = loop;
-		entry.endTime = animation.duration;
-		this.setCurrent(trackIndex, entry);
-		return entry;
-	},
-	addAnimationByName: function (trackIndex, animationName, loop, delay) {
-		var animation = this.data.skeletonData.findAnimation(animationName);
-		if (!animation) throw "Animation not found: " + animationName;
-		return this.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. */
-	addAnimation: function (trackIndex, animation, loop, delay) {
-		var entry = new spine.TrackEntry();
-		entry.animation = animation;
-		entry.loop = loop;
-		entry.endTime = animation.duration;
-
-		var last = this._expandToIndex(trackIndex);
-		if (last) {
-			while (last.next)
-				last = last.next;
-			last.next = entry;
-		} else
-			this.tracks[trackIndex] = entry;
-
-		if (delay <= 0) {
-			if (last)
-				delay += last.endTime - this.data.getMix(last.animation, animation);
-			else
-				delay = 0;
-		}
-		entry.delay = delay;
-
-		return entry;
-	},
-	/** May be null. */
-	getCurrent: function (trackIndex) {
-		if (trackIndex >= this.tracks.length) return null;
-		return this.tracks[trackIndex];
-	}
-};
-
-spine.SkeletonJson = function (attachmentLoader) {
-	this.attachmentLoader = attachmentLoader;
-	this.linkedMeshes = [];
-};
-spine.SkeletonJson.prototype = {
-	scale: 1,
-	readSkeletonData: function (root, name) {
-		var skeletonData = new spine.SkeletonData();
-		skeletonData.name = name;
-
-		// Skeleton.
-		var skeletonMap = root["skeleton"];
-		if (skeletonMap) {
-			skeletonData.hash = skeletonMap["hash"];
-			skeletonData.version = skeletonMap["spine"];
-			skeletonData.width = skeletonMap["width"] || 0;
-			skeletonData.height = skeletonMap["height"] || 0;
-		}
-
-		// Bones.
-		var bones = root["bones"];
-		for (var i = 0, n = bones.length; i < n; i++) {
-			var boneMap = bones[i];
-			var parent = null;
-			if (boneMap["parent"]) {
-				parent = skeletonData.findBone(boneMap["parent"]);
-				if (!parent) throw "Parent bone not found: " + boneMap["parent"];
-			}
-			var boneData = new spine.BoneData(boneMap["name"], parent);
-			boneData.length = (boneMap["length"] || 0) * this.scale;
-			boneData.x = (boneMap["x"] || 0) * this.scale;
-			boneData.y = (boneMap["y"] || 0) * this.scale;
-			boneData.rotation = (boneMap["rotation"] || 0);
-			boneData.scaleX = boneMap.hasOwnProperty("scaleX") ? boneMap["scaleX"] : 1;
-			boneData.scaleY = boneMap.hasOwnProperty("scaleY") ? boneMap["scaleY"] : 1;
-			boneData.inheritScale = boneMap.hasOwnProperty("inheritScale") ? boneMap["inheritScale"] : true;
-			boneData.inheritRotation = boneMap.hasOwnProperty("inheritRotation") ? boneMap["inheritRotation"] : true;
-			skeletonData.bones[i] = boneData;
-		}
-
-		// IK constraints.
-		var ik = root["ik"];
-		if (ik) {
-			for (var i = 0, n = ik.length; i < n; i++) {
-				var ikMap = ik[i];
-				var ikConstraintData = new spine.IkConstraintData(ikMap["name"]);
-
-				var bones = ikMap["bones"];
-				for (var ii = 0, nn = bones.length; ii < nn; ii++) {
-					var bone = skeletonData.findBone(bones[ii]);
-					if (!bone) throw "IK bone not found: " + bones[ii];
-					ikConstraintData.bones[ii] = bone;
-				}
-
-				ikConstraintData.target = skeletonData.findBone(ikMap["target"]);
-				if (!ikConstraintData.target) throw "Target bone not found: " + ikMap["target"];
-
-				ikConstraintData.bendDirection = (!ikMap.hasOwnProperty("bendPositive") || ikMap["bendPositive"]) ? 1 : -1;
-				ikConstraintData.mix = ikMap.hasOwnProperty("mix") ? ikMap["mix"] : 1;
-
-				skeletonData.ikConstraints[i] = ikConstraintData;
-			}
-		}
-
-		// Transform constraints.
-		var transform = root["transform"];
-		if (transform) {
-			for (var i = 0, n = transform.length; i < n; i++) {
-				var transformMap = transform[i];
-				var transformConstraintData = new spine.TransformConstraintData(transformMap["name"]);
-
-				transformConstraintData.bone = skeletonData.findBone(transformMap["bone"]);
-				if (!transformConstraintData.bone) throw "Bone not found: " + transformMap["bone"];
-
-				transformConstraintData.target = skeletonData.findBone(transformMap["target"]);
-				if (!transformConstraintData.target) throw "Target bone not found: " + transformMap["target"];
-
-				transformConstraintData.mix = transformMap.hasOwnProperty("translateMix") ? ikMap["translateMix"] : 1;
-				transformConstraintData.x = (transformMap["x"] || 0) * this.scale;
-				transformConstraintData.y = (transformMap["y"] || 0) * this.scale;
-
-				skeletonData.transformConstraints[i] = transformConstraintData;
-			}
-		}
-
-		// Slots.
-		var slots = root["slots"];
-		for (var i = 0, n = slots.length; i < n; i++) {
-			var slotMap = slots[i];
-			var boneData = skeletonData.findBone(slotMap["bone"]);
-			if (!boneData) throw "Slot bone not found: " + slotMap["bone"];
-			var slotData = new spine.SlotData(slotMap["name"], boneData);
-
-			var color = slotMap["color"];
-			if (color) {
-				slotData.r = this.toColor(color, 0);
-				slotData.g = this.toColor(color, 1);
-				slotData.b = this.toColor(color, 2);
-				slotData.a = this.toColor(color, 3);
-			}
-
-			slotData.attachmentName = slotMap["attachment"];
-			slotData.blendMode = spine.BlendMode[slotMap["blend"] || "normal"];
-
-			skeletonData.slots[i] = slotData;
-		}
-
-		// Skins.
-		var skins = root["skins"];
-		for (var skinName in skins) {
-			if (!skins.hasOwnProperty(skinName)) continue;
-			var skinMap = skins[skinName];
-			var skin = new spine.Skin(skinName);
-			for (var slotName in skinMap) {
-				if (!skinMap.hasOwnProperty(slotName)) continue;
-				var slotIndex = skeletonData.findSlotIndex(slotName);
-				var slotEntry = skinMap[slotName];
-				for (var attachmentName in slotEntry) {
-					if (!slotEntry.hasOwnProperty(attachmentName)) continue;
-					var attachment = this.readAttachment(skin, slotIndex, attachmentName, slotEntry[attachmentName]);
-					if (attachment) skin.addAttachment(slotIndex, attachmentName, attachment);
-				}
-			}
-			skeletonData.skins[skeletonData.skins.length] = skin;
-			if (skin.name == "default") skeletonData.defaultSkin = skin;
-		}
-
-		// Linked meshes.
-		for (var i = 0, n = this.linkedMeshes.length; i < n; i++) {
-			var linkedMesh = this.linkedMeshes[i];
-			var skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);
-			if (!skin) throw "Skin not found: " + linkedMesh.skin;
-			var parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
-			if (!parent) throw "Parent mesh not found: " + linkedMesh.parent;
-			linkedMesh.mesh.setParentMesh(parent);
-			linkedMesh.mesh.updateUVs();
-		}
-		this.linkedMeshes.length = 0;
-
-		// Events.
-		var events = root["events"];
-		for (var eventName in events) {
-			if (!events.hasOwnProperty(eventName)) continue;
-			var eventMap = events[eventName];
-			var eventData = new spine.EventData(eventName);
-			eventData.intValue = eventMap["int"] || 0;
-			eventData.floatValue = eventMap["float"] || 0;
-			eventData.stringValue = eventMap["string"] || null;
-			skeletonData.events[skeletonData.events.length] = eventData;
-		}
-
-		// Animations.
-		var animations = root["animations"];
-		for (var animationName in animations) {
-			if (!animations.hasOwnProperty(animationName)) continue;
-			this.readAnimation(animationName, animations[animationName], skeletonData);
-		}
-
-		return skeletonData;
-	},
-	readAttachment: function (skin, slotIndex, name, map) {
-		name = map["name"] || name;
-
-		var type = map["type"] || "region";
-		if (type == "skinnedmesh") type = "weightedmesh";
-		type = spine.AttachmentType[type];
-		var path = map["path"] || name;
-
-		var scale = this.scale;
-		switch (type) {
-		case spine.AttachmentType.region:
-			var region = this.attachmentLoader.newRegionAttachment(skin, name, path);
-			if (!region) return null;
-			region.path = path;
-			region.x = (map["x"] || 0) * scale;
-			region.y = (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 = (map["width"] || 0) * scale;
-			region.height = (map["height"] || 0) * scale;
-
-			var color = map["color"];
-			if (color) {
-				region.r = this.toColor(color, 0);
-				region.g = this.toColor(color, 1);
-				region.b = this.toColor(color, 2);
-				region.a = this.toColor(color, 3);
-			}
-
-			region.updateOffset();
-			return region;
-		case spine.AttachmentType.mesh:
-		case spine.AttachmentType.linkedmesh:
-			var mesh = this.attachmentLoader.newMeshAttachment(skin, name, path);
-			if (!mesh) return null;
-			mesh.path = path; 
-
-			color = map["color"];
-			if (color) {
-				mesh.r = this.toColor(color, 0);
-				mesh.g = this.toColor(color, 1);
-				mesh.b = this.toColor(color, 2);
-				mesh.a = this.toColor(color, 3);
-			}
-
-			mesh.width = (map["width"] || 0) * scale;
-			mesh.height = (map["height"] || 0) * scale;
-
-			if (!map["parent"]) {
-				mesh.vertices = this.getFloatArray(map, "vertices", scale);
-				mesh.triangles = this.getUint32Array(map, "triangles");
-				mesh.regionUVs = this.getFloatArray(map, "uvs", 1);
-				mesh.updateUVs();
-
-				mesh.hullLength = (map["hull"] || 0) * 2;
-				if (map["edges"]) mesh.edges = this.getUint16Array(map, "edges");
-			} else {
-				mesh.inheritFFD = map.hasOwnProperty("ffd") ? map["ffd"] : true;
-				this.linkedMeshes[this.linkedMeshes.length] = {mesh: mesh, skin: map["skin"], slotIndex: slotIndex, parent: map["parent"]};
-			}
-			return mesh;
-		case spine.AttachmentType.weightedmesh:
-		case spine.AttachmentType.weightedlinkedmesh:
-			var mesh = this.attachmentLoader.newWeightedMeshAttachment(skin, name, path);
-			if (!mesh) return null;
-			mesh.path = path;
-
-			color = map["color"];
-			if (color) {
-				mesh.r = this.toColor(color, 0);
-				mesh.g = this.toColor(color, 1);
-				mesh.b = this.toColor(color, 2);
-				mesh.a = this.toColor(color, 3);
-			}
-
-			mesh.width = (map["width"] || 0) * scale;
-			mesh.height = (map["height"] || 0) * scale;
-
-			if (!map["parent"]) {
-				var uvs = this.getFloatArray(map, "uvs", 1);
-				var vertices = this.getFloatArray(map, "vertices", 1);
-				var weights = new spine.Float32Array(uvs.length * 3 * 3);
-				var bones = new spine.Uint32Array(uvs.length * 3);
-				for (var i = 0, b = 0, w = 0, n = vertices.length; i < n; ) {
-					var boneCount = vertices[i++] | 0;
-					bones[b++] = boneCount;
-					for (var nn = i + boneCount * 4; i < nn; ) {
-						bones[b++] = vertices[i];
-						weights[w++] = vertices[i + 1] * scale;
-						weights[w++] = vertices[i + 2] * scale;
-						weights[w++] = vertices[i + 3];
-						i += 4;
-					}
-				}
-				mesh.bones = bones;
-				mesh.weights = weights;
-				mesh.triangles = this.getUint32Array(map, "triangles");
-				mesh.regionUVs = uvs;
-				mesh.updateUVs();
-
-				mesh.hullLength = (map["hull"] || 0) * 2;
-				if (map["edges"]) mesh.edges = this.getUint16Array(map, "edges");
-			} else {
-				mesh.inheritFFD = map.hasOwnProperty("ffd") ? map["ffd"] : true;
-				this.linkedMeshes[this.linkedMeshes.length] = {mesh: mesh, skin: map["skin"], slotIndex: slotIndex, parent: map["parent"]};
-			}
-			return mesh;
-		case spine.AttachmentType.boundingbox:
-			var attachment = this.attachmentLoader.newBoundingBoxAttachment(skin, name);
-			var vertices = map["vertices"];
-			attachment.vertices = new spine.Float32Array(vertices.length);
-			for (var i = 0, n = vertices.length; i < n; i++)
-				attachment.vertices[i] = vertices[i] * scale;
-			return attachment;
-		}
-		throw "Unknown attachment type: " + type;
-	},
-	readAnimation: function (name, map, skeletonData) {
-		var timelines = [];
-		var duration = 0;
-
-		var slots = map["slots"];
-		for (var slotName in slots) {
-			if (!slots.hasOwnProperty(slotName)) continue;
-			var slotMap = slots[slotName];
-			var slotIndex = skeletonData.findSlotIndex(slotName);
-
-			for (var timelineName in slotMap) {
-				if (!slotMap.hasOwnProperty(timelineName)) continue;
-				var values = slotMap[timelineName];
-				if (timelineName == "color") {
-					var timeline = new spine.ColorTimeline(values.length);
-					timeline.slotIndex = slotIndex;
-
-					var frameIndex = 0;
-					for (var i = 0, n = values.length; i < n; i++) {
-						var valueMap = values[i];
-						var color = valueMap["color"];
-						var r = this.toColor(color, 0);
-						var g = this.toColor(color, 1);
-						var b = this.toColor(color, 2);
-						var a = this.toColor(color, 3);
-						timeline.setFrame(frameIndex, valueMap["time"], r, g, b, a);
-						this.readCurve(timeline, frameIndex, valueMap);
-						frameIndex++;
-					}
-					timelines[timelines.length] = timeline;
-					duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 5 - 5]);
-
-				} else if (timelineName == "attachment") {
-					var timeline = new spine.AttachmentTimeline(values.length);
-					timeline.slotIndex = slotIndex;
-
-					var frameIndex = 0;
-					for (var i = 0, n = values.length; i < n; i++) {
-						var valueMap = values[i];
-						timeline.setFrame(frameIndex++, valueMap["time"], valueMap["name"]);
-					}
-					timelines[timelines.length] = timeline;
-					duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);
-
-				} else
-					throw "Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")";
-			}
-		}
-
-		var bones = map["bones"];
-		for (var boneName in bones) {
-			if (!bones.hasOwnProperty(boneName)) continue;
-			var boneIndex = skeletonData.findBoneIndex(boneName);
-			if (boneIndex == -1) throw "Bone not found: " + boneName;
-			var boneMap = bones[boneName];
-
-			for (var timelineName in boneMap) {
-				if (!boneMap.hasOwnProperty(timelineName)) continue;
-				var values = boneMap[timelineName];
-				if (timelineName == "rotate") {
-					var timeline = new spine.RotateTimeline(values.length);
-					timeline.boneIndex = boneIndex;
-
-					var frameIndex = 0;
-					for (var i = 0, n = values.length; i < n; i++) {
-						var valueMap = values[i];
-						timeline.setFrame(frameIndex, valueMap["time"], valueMap["angle"]);
-						this.readCurve(timeline, frameIndex, valueMap);
-						frameIndex++;
-					}
-					timelines[timelines.length] = timeline;
-					duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 2 - 2]);
-
-				} else if (timelineName == "translate" || timelineName == "scale") {
-					var timeline;
-					var timelineScale = 1;
-					if (timelineName == "scale")
-						timeline = new spine.ScaleTimeline(values.length);
-					else {
-						timeline = new spine.TranslateTimeline(values.length);
-						timelineScale = this.scale;
-					}
-					timeline.boneIndex = boneIndex;
-
-					var frameIndex = 0;
-					for (var i = 0, n = values.length; i < n; i++) {
-						var valueMap = values[i];
-						var x = (valueMap["x"] || 0) * timelineScale;
-						var y = (valueMap["y"] || 0) * timelineScale;
-						timeline.setFrame(frameIndex, valueMap["time"], x, y);
-						this.readCurve(timeline, frameIndex, valueMap);
-						frameIndex++;
-					}
-					timelines[timelines.length] = timeline;
-					duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]);
-
-				} else
-					throw "Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")";
-			}
-		}
-
-		var ikMap = map["ik"];
-		for (var ikConstraintName in ikMap) {
-			if (!ikMap.hasOwnProperty(ikConstraintName)) continue;
-			var ikConstraint = skeletonData.findIkConstraint(ikConstraintName);
-			var values = ikMap[ikConstraintName];
-			var timeline = new spine.IkConstraintTimeline(values.length);
-			timeline.ikConstraintIndex = skeletonData.ikConstraints.indexOf(ikConstraint);
-			var frameIndex = 0;
-			for (var i = 0, n = values.length; i < n; i++) {
-				var valueMap = values[i];
-				var mix = valueMap.hasOwnProperty("mix") ? valueMap["mix"] : 1;
-				var bendDirection = (!valueMap.hasOwnProperty("bendPositive") || valueMap["bendPositive"]) ? 1 : -1;
-				timeline.setFrame(frameIndex, valueMap["time"], mix, bendDirection);
-				this.readCurve(timeline, frameIndex, valueMap);
-				frameIndex++;
-			}
-			timelines[timelines.length] = timeline;
-			duration = Math.max(duration, timeline.frames[timeline.getFrameCount() * 3 - 3]);
-		}
-
-		var ffd = map["ffd"];
-		for (var skinName in ffd) {
-			var skin = skeletonData.findSkin(skinName);
-			var slotMap = ffd[skinName];
-			for (slotName in slotMap) {
-				var slotIndex = skeletonData.findSlotIndex(slotName);
-				var meshMap = slotMap[slotName];
-				for (var meshName in meshMap) {
-					var values = meshMap[meshName];
-					var timeline = new spine.FfdTimeline(values.length);
-					var attachment = skin.getAttachment(slotIndex, meshName);
-					if (!attachment) throw "FFD attachment not found: " + meshName;
-					timeline.slotIndex = slotIndex;
-					timeline.attachment = attachment;
-
-					var isMesh = attachment.type == spine.AttachmentType.mesh;
-					var vertexCount;
-					if (isMesh)
-						vertexCount = attachment.vertices.length;
-					else
-						vertexCount = attachment.weights.length / 3 * 2;
-
-					var frameIndex = 0;
-					for (var i = 0, n = values.length; i < n; i++) {
-						var valueMap = values[i];
-						var vertices;
-						if (!valueMap["vertices"]) {
-							if (isMesh)
-								vertices = attachment.vertices;
-							else {
-								vertices = new spine.Float32Array(vertexCount);
-								vertices.length = vertexCount;
-							}
-						} else {
-							var verticesValue = valueMap["vertices"];
-							var vertices = new spine.Float32Array(vertexCount);
-							vertices.length = vertexCount;
-							var start = valueMap["offset"] || 0;
-							var nn = verticesValue.length;
-							if (this.scale == 1) {
-								for (var ii = 0; ii < nn; ii++)
-									vertices[ii + start] = verticesValue[ii];
-							} else {
-								for (var ii = 0; ii < nn; ii++)
-									vertices[ii + start] = verticesValue[ii] * this.scale;
-							}
-							if (isMesh) {
-								var meshVertices = attachment.vertices;
-								for (var ii = 0, nn = vertices.length; ii < nn; ii++)
-									vertices[ii] += meshVertices[ii];
-							}
-						}
-
-						timeline.setFrame(frameIndex, valueMap["time"], vertices);
-						this.readCurve(timeline, frameIndex, valueMap);
-						frameIndex++;
-					}
-					timelines[timelines.length] = timeline;
-					duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);
-				}
-			}
-		}
-
-		var drawOrderValues = map["drawOrder"];
-		if (!drawOrderValues) drawOrderValues = map["draworder"];
-		if (drawOrderValues) {
-			var timeline = new spine.DrawOrderTimeline(drawOrderValues.length);
-			var slotCount = skeletonData.slots.length;
-			var frameIndex = 0;
-			for (var i = 0, n = drawOrderValues.length; i < n; i++) {
-				var drawOrderMap = drawOrderValues[i];
-				var drawOrder = null;
-				if (drawOrderMap["offsets"]) {
-					drawOrder = new spine.Uint32Array(slotCount);
-					drawOrder.length = slotCount;
-					for (var ii = slotCount - 1; ii >= 0; ii--)
-						drawOrder[ii] = 4294967295;
-					var offsets = drawOrderMap["offsets"];
-					var unchanged = new spine.Uint32Array(slotCount - offsets.length);
-					unchanged.length = slotCount - offsets.length;
-					var originalIndex = 0, unchangedIndex = 0;
-					for (var ii = 0, nn = offsets.length; ii < nn; ii++) {
-						var offsetMap = offsets[ii];
-						var slotIndex = skeletonData.findSlotIndex(offsetMap["slot"]);
-						if (slotIndex == -1) throw "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 (var ii = slotCount - 1; ii >= 0; ii--)
-						if (drawOrder[ii] == 4294967295) drawOrder[ii] = unchanged[--unchangedIndex];
-				}
-				timeline.setFrame(frameIndex++, drawOrderMap["time"], drawOrder);
-			}
-			timelines[timelines.length] = timeline;
-			duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);
-		}
-
-		var events = map["events"];
-		if (events) {
-			var timeline = new spine.EventTimeline(events.length);
-			var frameIndex = 0;
-			for (var i = 0, n = events.length; i < n; i++) {
-				var eventMap = events[i];
-				var eventData = skeletonData.findEvent(eventMap["name"]);
-				if (!eventData) throw "Event not found: " + eventMap["name"];
-				var event = new spine.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;
-				timeline.setFrame(frameIndex++, event);
-			}
-			timelines[timelines.length] = timeline;
-			duration = Math.max(duration, timeline.frames[timeline.getFrameCount() - 1]);
-		}
-
-		skeletonData.animations[skeletonData.animations.length] = new spine.Animation(name, timelines, duration);
-	},
-	readCurve: function (timeline, frameIndex, valueMap) {
-		var curve = valueMap["curve"];
-		if (!curve) 
-			timeline.curves.setLinear(frameIndex);
-		else if (curve == "stepped")
-			timeline.curves.setStepped(frameIndex);
-		else if (curve instanceof Array)
-			timeline.curves.setCurve(frameIndex, curve[0], curve[1], curve[2], curve[3]);
-	},
-	toColor: function (hexString, colorIndex) {
-		if (hexString.length != 8) throw "Color hexidecimal length must be 8, recieved: " + hexString;
-		return parseInt(hexString.substring(colorIndex * 2, (colorIndex * 2) + 2), 16) / 255;
-	},
-	getFloatArray: function (map, name, scale) {
-		var list = map[name];
-		var values = new spine.Float32Array(list.length);
-		var i = 0, n = 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;
-	},
-	getUint32Array: function (map, name) {
-		var list = map[name];
-		var values = new spine.Uint32Array(list.length);
-		for (var i = 0, n = list.length; i < n; i++)
-			values[i] = list[i] | 0;
-		return values;
-	},
-	getUint16Array: function (map, name) {
-		var list = map[name];
-		var values = new spine.Uint16Array(list.length);
-		for (var i = 0, n = list.length; i < n; i++)
-			values[i] = list[i] | 0;
-		return values;
-	}
-};
-
-spine.Atlas = function (atlasText, textureLoader) {
-	this.textureLoader = textureLoader;
-	this.pages = [];
-	this.regions = [];
-
-	var reader = new spine.AtlasReader(atlasText);
-	var tuple = [];
-	tuple.length = 4;
-	var page = null;
-	while (true) {
-		var line = reader.readLine();
-		if (line === null) break;
-		line = reader.trim(line);
-		if (!line.length)
-			page = null;
-		else if (!page) {
-			page = new spine.AtlasPage();
-			page.name = line;
-
-			if (reader.readTuple(tuple) == 2) { // size is only optional for an atlas packed with an old TexturePacker.
-				page.width = parseInt(tuple[0]);
-				page.height = parseInt(tuple[1]);
-				reader.readTuple(tuple);
-			}
-			page.format = spine.Atlas.Format[tuple[0]];
-
-			reader.readTuple(tuple);
-			page.minFilter = spine.Atlas.TextureFilter[tuple[0]];
-			page.magFilter = spine.Atlas.TextureFilter[tuple[1]];
-
-			var direction = reader.readValue();
-			page.uWrap = spine.Atlas.TextureWrap.clampToEdge;
-			page.vWrap = spine.Atlas.TextureWrap.clampToEdge;
-			if (direction == "x")
-				page.uWrap = spine.Atlas.TextureWrap.repeat;
-			else if (direction == "y")
-				page.vWrap = spine.Atlas.TextureWrap.repeat;
-			else if (direction == "xy")
-				page.uWrap = page.vWrap = spine.Atlas.TextureWrap.repeat;
-
-			textureLoader.load(page, line, this);
-
-			this.pages[this.pages.length] = page;
-
-		} else {
-			var region = new spine.AtlasRegion();
-			region.name = line;
-			region.page = page;
-
-			region.rotate = reader.readValue() == "true";
-
-			reader.readTuple(tuple);
-			var x = parseInt(tuple[0]);
-			var y = parseInt(tuple[1]);
-
-			reader.readTuple(tuple);
-			var width = parseInt(tuple[0]);
-			var height = parseInt(tuple[1]);
-
-			region.u = x / page.width;
-			region.v = y / page.height;
-			if (region.rotate) {
-				region.u2 = (x + height) / page.width;
-				region.v2 = (y + width) / page.height;
-			} else {
-				region.u2 = (x + width) / page.width;
-				region.v2 = (y + height) / page.height;
-			}
-			region.x = x;
-			region.y = y;
-			region.width = Math.abs(width);
-			region.height = Math.abs(height);
-
-			if (reader.readTuple(tuple) == 4) { // split is optional
-				region.splits = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])];
-
-				if (reader.readTuple(tuple) == 4) { // pad is optional, but only present with splits
-					region.pads = [parseInt(tuple[0]), parseInt(tuple[1]), parseInt(tuple[2]), parseInt(tuple[3])];
-
-					reader.readTuple(tuple);
-				}
-			}
-
-			region.originalWidth = parseInt(tuple[0]);
-			region.originalHeight = parseInt(tuple[1]);
-
-			reader.readTuple(tuple);
-			region.offsetX = parseInt(tuple[0]);
-			region.offsetY = parseInt(tuple[1]);
-
-			region.index = parseInt(reader.readValue());
-
-			this.regions[this.regions.length] = region;
-		}
-	}
-};
-spine.Atlas.prototype = {
-	findRegion: function (name) {
-		var regions = this.regions;
-		for (var i = 0, n = regions.length; i < n; i++)
-			if (regions[i].name == name) return regions[i];
-		return null;
-	},
-	dispose: function () {
-		var pages = this.pages;
-		for (var i = 0, n = pages.length; i < n; i++)
-			this.textureLoader.unload(pages[i].rendererObject);
-	},
-	updateUVs: function (page) {
-		var regions = this.regions;
-		for (var i = 0, n = regions.length; i < n; i++) {
-			var region = regions[i];
-			if (region.page != page) continue;
-			region.u = region.x / page.width;
-			region.v = region.y / page.height;
-			if (region.rotate) {
-				region.u2 = (region.x + region.height) / page.width;
-				region.v2 = (region.y + region.width) / page.height;
-			} else {
-				region.u2 = (region.x + region.width) / page.width;
-				region.v2 = (region.y + region.height) / page.height;
-			}
-		}
-	}
-};
-
-spine.Atlas.Format = {
-	alpha: 0,
-	intensity: 1,
-	luminanceAlpha: 2,
-	rgb565: 3,
-	rgba4444: 4,
-	rgb888: 5,
-	rgba8888: 6
-};
-
-spine.Atlas.TextureFilter = {
-	nearest: 0,
-	linear: 1,
-	mipMap: 2,
-	mipMapNearestNearest: 3,
-	mipMapLinearNearest: 4,
-	mipMapNearestLinear: 5,
-	mipMapLinearLinear: 6
-};
-
-spine.Atlas.TextureWrap = {
-	mirroredRepeat: 0,
-	clampToEdge: 1,
-	repeat: 2
-};
-
-spine.AtlasPage = function () {};
-spine.AtlasPage.prototype = {
-	name: null,
-	format: null,
-	minFilter: null,
-	magFilter: null,
-	uWrap: null,
-	vWrap: null,
-	rendererObject: null,
-	width: 0,
-	height: 0
-};
-
-spine.AtlasRegion = function () {};
-spine.AtlasRegion.prototype = {
-	page: null,
-	name: null,
-	x: 0, y: 0,
-	width: 0, height: 0,
-	u: 0, v: 0, u2: 0, v2: 0,
-	offsetX: 0, offsetY: 0,
-	originalWidth: 0, originalHeight: 0,
-	index: 0,
-	rotate: false,
-	splits: null,
-	pads: null
-};
-
-spine.AtlasReader = function (text) {
-	this.lines = text.split(/\r\n|\r|\n/);
-};
-spine.AtlasReader.prototype = {
-	index: 0,
-	trim: function (value) {
-		return value.replace(/^\s+|\s+$/g, "");
-	},
-	readLine: function () {
-		if (this.index >= this.lines.length) return null;
-		return this.lines[this.index++];
-	},
-	readValue: function () {
-		var line = this.readLine();
-		var colon = line.indexOf(":");
-		if (colon == -1) throw "Invalid line: " + line;
-		return this.trim(line.substring(colon + 1));
-	},
-	/** Returns the number of tuple values read (1, 2 or 4). */
-	readTuple: function (tuple) {
-		var line = this.readLine();
-		var colon = line.indexOf(":");
-		if (colon == -1) throw "Invalid line: " + line;
-		var i = 0, lastMatch = colon + 1;
-		for (; i < 3; i++) {
-			var comma = line.indexOf(",", lastMatch);
-			if (comma == -1) break;
-			tuple[i] = this.trim(line.substr(lastMatch, comma - lastMatch));
-			lastMatch = comma + 1;
-		}
-		tuple[i] = this.trim(line.substring(lastMatch));
-		return i + 1;
-	}
-};
-
-spine.AtlasAttachmentLoader = function (atlas) {
-	this.atlas = atlas;
-};
-spine.AtlasAttachmentLoader.prototype = {
-	newRegionAttachment: function (skin, name, path) {
-		var region = this.atlas.findRegion(path);
-		if (!region) throw "Region not found in atlas: " + path + " (region attachment: " + name + ")";
-		var attachment = new spine.RegionAttachment(name);
-		attachment.rendererObject = region;
-		attachment.setUVs(region.u, region.v, region.u2, region.v2, region.rotate);
-		attachment.regionOffsetX = region.offsetX;
-		attachment.regionOffsetY = region.offsetY;
-		attachment.regionWidth = region.width;
-		attachment.regionHeight = region.height;
-		attachment.regionOriginalWidth = region.originalWidth;
-		attachment.regionOriginalHeight = region.originalHeight;
-		return attachment;
-	},
-	newMeshAttachment: function (skin, name, path) {
-		var region = this.atlas.findRegion(path);
-		if (!region) throw "Region not found in atlas: " + path + " (mesh attachment: " + name + ")";
-		var attachment = new spine.MeshAttachment(name);
-		attachment.rendererObject = region;
-		attachment.regionU = region.u;
-		attachment.regionV = region.v;
-		attachment.regionU2 = region.u2;
-		attachment.regionV2 = region.v2;
-		attachment.regionRotate = region.rotate;
-		attachment.regionOffsetX = region.offsetX;
-		attachment.regionOffsetY = region.offsetY;
-		attachment.regionWidth = region.width;
-		attachment.regionHeight = region.height;
-		attachment.regionOriginalWidth = region.originalWidth;
-		attachment.regionOriginalHeight = region.originalHeight;
-		return attachment;
-	},
-	newWeightedMeshAttachment: function (skin, name, path) {
-		var region = this.atlas.findRegion(path);
-		if (!region) throw "Region not found in atlas: " + path + " (weighted mesh attachment: " + name + ")";
-		var attachment = new spine.WeightedMeshAttachment(name);
-		attachment.rendererObject = region;
-		attachment.regionU = region.u;
-		attachment.regionV = region.v;
-		attachment.regionU2 = region.u2;
-		attachment.regionV2 = region.v2;
-		attachment.regionRotate = region.rotate;
-		attachment.regionOffsetX = region.offsetX;
-		attachment.regionOffsetY = region.offsetY;
-		attachment.regionWidth = region.width;
-		attachment.regionHeight = region.height;
-		attachment.regionOriginalWidth = region.originalWidth;
-		attachment.regionOriginalHeight = region.originalHeight;
-		return attachment;
-	},
-	newBoundingBoxAttachment: function (skin, name) {
-		return new spine.BoundingBoxAttachment(name);
-	}
-};
-
-spine.SkeletonBounds = function () {
-	this.polygonPool = [];
-	this.polygons = [];
-	this.boundingBoxes = [];
-};
-spine.SkeletonBounds.prototype = {
-	minX: 0, minY: 0, maxX: 0, maxY: 0,
-	update: function (skeleton, updateAabb) {
-		var slots = skeleton.slots;
-		var slotCount = slots.length;
-		var x = skeleton.x, y = skeleton.y;
-		var boundingBoxes = this.boundingBoxes;
-		var polygonPool = this.polygonPool;
-		var polygons = this.polygons;
-
-		boundingBoxes.length = 0;
-		for (var i = 0, n = polygons.length; i < n; i++)
-			polygonPool[polygonPool.length] = polygons[i];
-		polygons.length = 0;
-
-		for (var i = 0; i < slotCount; i++) {
-			var slot = slots[i];
-			var boundingBox = slot.attachment;
-			if (boundingBox.type != spine.AttachmentType.boundingbox) continue;
-			boundingBoxes[boundingBoxes.length] = boundingBox;
-
-			var poolCount = polygonPool.length, polygon;
-			if (poolCount > 0) {
-				polygon = polygonPool[poolCount - 1];
-				polygonPool.splice(poolCount - 1, 1);
-				polygon.length = boundingBox.vertices.length;
-			} else
-				polygon = new Array(boundingBox.vertices.length);
-			polygons[polygons.length] = polygon;
-
-			boundingBox.computeWorldVertices(x, y, slot.bone, polygon);
-		}
-
-		if (updateAabb) this.aabbCompute();
-	},
-	aabbCompute: function () {
-		var polygons = this.polygons;
-		var minX = Number.MAX_VALUE, minY = Number.MAX_VALUE, maxX = -Number.MAX_VALUE, maxY = -Number.MAX_VALUE;
-		for (var i = 0, n = polygons.length; i < n; i++) {
-			var vertices = polygons[i];
-			for (var ii = 0, nn = vertices.length; ii < nn; ii += 2) {
-				var x = vertices[ii];
-				var y = 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. */
-	aabbContainsPoint: function (x, y) {
-		return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY;
-	},
-	/** Returns true if the axis aligned bounding box intersects the line segment. */
-	aabbIntersectsSegment: function (x1, y1, x2, y2) {
-		var minX = this.minX, minY = this.minY, maxX = this.maxX, maxY = this.maxY;
-		if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY))
-			return false;
-		var m = (y2 - y1) / (x2 - x1);
-		var y = 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 = (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. */
-	aabbIntersectsSkeleton: function (bounds) {
-		return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.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. */
-	containsPoint: function (x, y) {
-		var polygons = this.polygons;
-		for (var i = 0, n = polygons.length; i < n; i++)
-			if (this.polygonContainsPoint(polygons[i], x, y)) return this.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. */
-	intersectsSegment: function (x1, y1, x2, y2) {
-		var polygons = this.polygons;
-		for (var i = 0, n = polygons.length; i < n; i++)
-			if (polygons[i].intersectsSegment(x1, y1, x2, y2)) return this.boundingBoxes[i];
-		return null;
-	},
-	/** Returns true if the polygon contains the point. */
-	polygonContainsPoint: function (polygon, x, y) {
-		var nn = polygon.length;
-		var prevIndex = nn - 2;
-		var inside = false;
-		for (var ii = 0; ii < nn; ii += 2) {
-			var vertexY = polygon[ii + 1];
-			var prevY = polygon[prevIndex + 1];
-			if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) {
-				var vertexX = polygon[ii];
-				if (vertexX + (y - vertexY) / (prevY - vertexY) * (polygon[prevIndex] - vertexX) < x) inside = !inside;
-			}
-			prevIndex = ii;
-		}
-		return inside;
-	},
-	/** Returns true if the polygon contains the line segment. */
-	polygonIntersectsSegment: function (polygon, x1, y1, x2, y2) {
-		var nn = polygon.length;
-		var width12 = x1 - x2, height12 = y1 - y2;
-		var det1 = x1 * y2 - y1 * x2;
-		var x3 = polygon[nn - 2], y3 = polygon[nn - 1];
-		for (var ii = 0; ii < nn; ii += 2) {
-			var x4 = polygon[ii], y4 = polygon[ii + 1];
-			var det2 = x3 * y4 - y3 * x4;
-			var width34 = x3 - x4, height34 = y3 - y4;
-			var det3 = width12 * height34 - height12 * width34;
-			var x = (det1 * width34 - width12 * det2) / det3;
-			if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) {
-				var y = (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;
-	},
-	getPolygon: function (attachment) {
-		var index = this.boundingBoxes.indexOf(attachment);
-		return index == -1 ? null : this.polygons[index];
-	},
-	getWidth: function () {
-		return this.maxX - this.minX;
-	},
-	getHeight: function () {
-		return this.maxY - this.minY;
-	}
-};

Some files were not shown because too many files changed in this diff