Source: d:/wamp/www/phaser/src/pixi/extras/PIXISpine.js

/* Esoteric Software SPINE wrapper for pixi.js */

spine.Bone.yDown = true;
PIXI.AnimCache = {};

/**
 * Supporting class to load images from spine atlases as per spine spec.
 *
 * @class SpineTextureLoader
 * @uses EventTarget
 * @constructor
 * @param basePath {String} Tha base path where to look for the images to be loaded
 * @param crossorigin {Boolean} Whether requests should be treated as crossorigin
 */
PIXI.SpineTextureLoader = function(basePath, crossorigin)
{
    PIXI.EventTarget.call(this);

    this.basePath = basePath;
    this.crossorigin = crossorigin;
    this.loadingCount = 0;
};

/* constructor */
PIXI.SpineTextureLoader.prototype = PIXI.SpineTextureLoader;

/**
 * Starts loading a base texture as per spine specification
 *
 * @method load
 * @param page {spine.AtlasPage} Atlas page to which texture belongs
 * @param file {String} The file to load, this is just the file path relative to the base path configured in the constructor
 */
PIXI.SpineTextureLoader.prototype.load = function(page, file)
{
    page.rendererObject = PIXI.BaseTexture.fromImage(this.basePath + '/' + file, this.crossorigin);
    if (!page.rendererObject.hasLoaded)
    {
        var scope = this;
        ++scope.loadingCount;
        page.rendererObject.addEventListener('loaded', function(){
            --scope.loadingCount;
            scope.dispatchEvent({
                type: 'loadedBaseTexture',
                content: scope
            });
        });
    }
};

/**
 * Unloads a previously loaded texture as per spine specification
 *
 * @method unload
 * @param texture {BaseTexture} Texture object to destroy
 */
PIXI.SpineTextureLoader.prototype.unload = function(texture)
{
    texture.destroy(true);
};

/**
 * A class that enables the you to import and run your spine animations in pixi.
 * Spine animation data needs to be loaded using the PIXI.AssetLoader or PIXI.SpineLoader before it can be used by this class
 * See example 12 (http://www.goodboydigital.com/pixijs/examples/12/) to see a working example and check out the source
 *
 * @class Spine
 * @extends DisplayObjectContainer
 * @constructor
 * @param url {String} The url of the spine anim file to be used
 */
PIXI.Spine = function (url) {
    PIXI.DisplayObjectContainer.call(this);

    this.spineData = PIXI.AnimCache[url];

    if (!this.spineData) {
        throw new Error('Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: ' + url);
    }

    this.skeleton = new spine.Skeleton(this.spineData);
    this.skeleton.updateWorldTransform();

    this.stateData = new spine.AnimationStateData(this.spineData);
    this.state = new spine.AnimationState(this.stateData);

    this.slotContainers = [];

    for (var i = 0, n = this.skeleton.drawOrder.length; i < n; i++) {
        var slot = this.skeleton.drawOrder[i];
        var attachment = slot.attachment;
        var slotContainer = new PIXI.DisplayObjectContainer();
        this.slotContainers.push(slotContainer);
        this.addChild(slotContainer);

        if (attachment instanceof spine.RegionAttachment)
        {
            var spriteName = attachment.rendererObject.name;
            var sprite = this.createSprite(slot, attachment);
            slot.currentSprite = sprite;
            slot.currentSpriteName = spriteName;
            slotContainer.addChild(sprite);
        }
        else if (attachment instanceof spine.MeshAttachment)
        {
            var mesh = this.createMesh(slot, attachment);
            slot.currentMesh = mesh;
            slot.currentMeshName = attachment.name;
            slotContainer.addChild(mesh);
        }
        else
        {
            continue;
        }

    }

    this.autoUpdate = true;
};

PIXI.Spine.prototype = Object.create(PIXI.DisplayObjectContainer.prototype);
PIXI.Spine.prototype.constructor = PIXI.Spine;

/**
 * If this flag is set to true, the spine animation will be autoupdated every time
 * the object id drawn. The down side of this approach is that the delta time is
 * automatically calculated and you could miss out on cool effects like slow motion,
 * pause, skip ahead and the sorts. Most of these effects can be achieved even with
 * autoupdate enabled but are harder to achieve.
 *
 * @property autoUpdate
 * @type { Boolean }
 * @default true
 */
Object.defineProperty(PIXI.Spine.prototype, 'autoUpdate', {
    get: function()
    {
        return (this.updateTransform === PIXI.Spine.prototype.autoUpdateTransform);
    },

    set: function(value)
    {
        this.updateTransform = value ? PIXI.Spine.prototype.autoUpdateTransform : PIXI.DisplayObjectContainer.prototype.updateTransform;
    }
});

/**
 * Update the spine skeleton and its animations by delta time (dt)
 *
 * @method update
 * @param dt {Number} Delta time. Time by which the animation should be updated
 */
PIXI.Spine.prototype.update = function(dt)
{
    this.state.update(dt);
    this.state.apply(this.skeleton);
    this.skeleton.updateWorldTransform();

    var drawOrder = this.skeleton.drawOrder;
    for (var i = 0, n = drawOrder.length; i < n; i++) {
        var slot = drawOrder[i];
        var attachment = slot.attachment;
        var slotContainer = this.slotContainers[i];
        var type = attachment.type;
        if (type === spine.AttachmentType.region)
        {
            if (attachment.rendererObject)
            {
                if (!slot.currentSpriteName || slot.currentSpriteName !== attachment.name)
                {
                    var spriteName = attachment.rendererObject.name;
                    if (slot.currentSprite !== undefined)
                    {
                        slot.currentSprite.visible = false;
                    }
                    slot.sprites = slot.sprites || {};
                    if (slot.sprites[spriteName] !== undefined)
                    {
                        slot.sprites[spriteName].visible = true;
                    }
                    else
                    {
                        var sprite = this.createSprite(slot, attachment);
                        slotContainer.addChild(sprite);
                    }
                    slot.currentSprite = slot.sprites[spriteName];
                    slot.currentSpriteName = spriteName;
                }
            }

            var bone = slot.bone;

            slotContainer.position.x = bone.worldX + attachment.x * bone.m00 + attachment.y * bone.m01;
            slotContainer.position.y = bone.worldY + attachment.x * bone.m10 + attachment.y * bone.m11;
            slotContainer.scale.x = bone.worldScaleX;
            slotContainer.scale.y = bone.worldScaleY;

            slotContainer.rotation = -(slot.bone.worldRotation * spine.degRad);

            slot.currentSprite.tint = PIXI.rgb2hex([slot.r,slot.g,slot.b]);
        }
        else if (type === spine.AttachmentType.skinnedmesh)
        {
            if (!slot.currentMeshName || slot.currentMeshName !== attachment.name)
            {
                var meshName = attachment.name;
                if (slot.currentMesh !== undefined)
                {
                    slot.currentMesh.visible = false;
                }

                slot.meshes = slot.meshes || {};

                if (slot.meshes[meshName] !== undefined)
                {
                    slot.meshes[meshName].visible = true;
                }
                else
                {
                    var mesh = this.createMesh(slot, attachment);
                    slotContainer.addChild(mesh);
                }

                slot.currentMesh = slot.meshes[meshName];
                slot.currentMeshName = meshName;
            }

            attachment.computeWorldVertices(slot.bone.skeleton.x, slot.bone.skeleton.y, slot, slot.currentMesh.vertices);

        }
        else
        {
            slotContainer.visible = false;
            continue;
        }
        slotContainer.visible = true;

        slotContainer.alpha = slot.a;
    }
};

/**
 * When autoupdate is set to yes this function is used as pixi's updateTransform function
 *
 * @method autoUpdateTransform
 * @private
 */
PIXI.Spine.prototype.autoUpdateTransform = function () {
    this.lastTime = this.lastTime || Date.now();
    var timeDelta = (Date.now() - this.lastTime) * 0.001;
    this.lastTime = Date.now();

    this.update(timeDelta);

    PIXI.DisplayObjectContainer.prototype.updateTransform.call(this);
};

/**
 * Create a new sprite to be used with spine.RegionAttachment
 *
 * @method createSprite
 * @param slot {spine.Slot} The slot to which the attachment is parented
 * @param attachment {spine.RegionAttachment} The attachment that the sprite will represent
 * @private
 */
PIXI.Spine.prototype.createSprite = function (slot, attachment) {
    var descriptor = attachment.rendererObject;
    var baseTexture = descriptor.page.rendererObject;
    var spriteRect = new PIXI.Rectangle(descriptor.x,
                                        descriptor.y,
                                        descriptor.rotate ? descriptor.height : descriptor.width,
                                        descriptor.rotate ? descriptor.width : descriptor.height);
    var spriteTexture = new PIXI.Texture(baseTexture, spriteRect);
    var sprite = new PIXI.Sprite(spriteTexture);

    var baseRotation = descriptor.rotate ? Math.PI * 0.5 : 0.0;
    sprite.scale.set(descriptor.width / descriptor.originalWidth, descriptor.height / descriptor.originalHeight);
    sprite.rotation = baseRotation - (attachment.rotation * spine.degRad);
    sprite.anchor.x = sprite.anchor.y = 0.5;

    slot.sprites = slot.sprites || {};
    slot.sprites[descriptor.name] = sprite;
    return sprite;
};

PIXI.Spine.prototype.createMesh = function (slot, attachment) {
    var descriptor = attachment.rendererObject;
    var baseTexture = descriptor.page.rendererObject;
    var texture = new PIXI.Texture(baseTexture);

    var strip = new PIXI.Strip(texture);
    strip.drawMode = PIXI.Strip.DrawModes.TRIANGLES;
    strip.padding = 5;

    strip.vertices = new PIXI.Float32Array(attachment.uvs.length);
    strip.uvs = attachment.uvs;
    strip.indices = attachment.triangles;

    slot.meshes[attachment.name] = strip;

    return strip;
};
Phaser Copyright © 2012-2014 Photon Storm Ltd.
Documentation generated by JSDoc 3.3.0-dev on Tue Nov 25 2014 00:17:19 GMT-0000 (GMT) using the DocStrap template.