function SpineAnimation(json, atlas, path, textures)
{
	if (textures === undefined)
	{
		textures = [];
	}

	var textureAtlas = new TextureAtlas(atlas, function(file)
	{
		for (var i = 0; i < textures.length; i++)
		{
			if (textures[i].name === file)
			{
				var texture = new SpineTexture(textures[i].texture);
				break;
			}
		}

		if (i === textures.length)
		{
			var texture = new SpineTexture(new Texture(new Image(path + "/" + file)));
			textures.push({name: file, texture: texture.texture});
		}

		var element = texture.texture.image;
		var image = texture.texture.source;

		if (image.width > 0 && image.height > 0)
		{
			element.width = image.width;
			element.height = image.height;
		}
		else if (element.naturalWidth !== 0 && element.naturalHeight !== 0)
		{
			element.width = element.naturalWidth;
			element.height = element.naturalHeight;
			image.width = element.width;
			image.height = element.height;
		}
		else
		{
			var beginning = atlas.search("size: ");
			var end = atlas.search("\nformat");
			var size = atlas.substring(beginning + 6, end);
			size = size.split(",");
			element.width = parseInt(size[0]);
			element.height = parseInt(size[1]);
		}

		return texture;
	});

	var loader = new AtlasAttachmentLoader(textureAtlas);
	var skeleton = new SkeletonJson(loader).readSkeletonData(json);

	SkeletonMesh.call(this, skeleton);

	this.name = "spine";
	this.type = "SpineAnimation";

	this.scale.set(0.01, 0.01, 0.01);

	/**
	 * Spine animation data.
	 *
	 * @property json
	 * @type {Object}
	 */
	this.json = json;

	/**
	 * Texture atlas information.
	 *
	 * @property atlas
	 * @type {Object}
	 */
	this.atlas = atlas;

	/**
	 * Array of SpineTextures used by the animation.
	 *
	 * @property textures
	 * @type {Array}
	 */
	this.textures = textures;

	/**
	 * The animation can have multiple skins that define diferent sets of textures for the same animation.
	 *
	 * @attribute skin
	 * @type {Object}
	 */
	this.skin = this.getSkins().length > 0 ? this.getSkins()[0].name : null;

	/**
	 * Animation currently playing, animations are split into tracks.
	 *
	 * An animation (e.g. walk) can be composed of multiple tracks.
	 *
	 * @attribute animation
	 * @type {Object}
	 */
	this.animation = this.getAnimations().length > 0 ? this.getAnimations()[0].name : null;

	/**
	 * Index of the animation track playing.
	 *
	 * @attribute track
	 * @type {number}
	 */
	this.track = 0;

	/**
	 * Indicates the loop mode of the animation if set true the animation starts again after it ends.
	 *
	 * @attribute loop
	 * @type {boolean}
	 */
	this.loop = true;

	this.clock = new Clock();

	this.play();
}
Spine animation object, to used with animation produced inside Esoteric spine. These animations are created using the Spine animation studio software.

Based on the official three.js runtime code available at https:// github.com/EsotericSoftware/spine-runtimes.

More information about spine available at www.esotericsoftware.com.

@class SpineAnimation
@extends {SkeletonMesh}
@param {Object} json Object containing the spine JSON encoded data for this animation.
@param {string} atlas Atlas file path.
@param {string} path Path to retrieve images from.
@param {Texture[]} textures List of textures provided for this animation.
@module Animations