Newer
Older
pixi.js / src / loaders / spritesheetParser.js
@Mat Groves Mat Groves on 31 Mar 2016 4 KB Merge branch 'dev'
var Resource = require('resource-loader').Resource,
    path = require('path'),
    core = require('../core'),
    async = require('async');

var BATCH_SIZE = 1000;

module.exports = function ()
{
    return function (resource, next)
    {
        var imageResourceName = resource.name + '_image';

        // skip if no data, its not json, it isn't spritesheet data, or the image resource already exists
        if (!resource.data || !resource.isJson || !resource.data.frames || this.resources[imageResourceName])
        {
            return next();
        }

        var loadOptions = {
            crossOrigin: resource.crossOrigin,
            loadType: Resource.LOAD_TYPE.IMAGE,
            metadata: resource.metadata.imageMetadata
        };

        var route = path.dirname(resource.url.replace(this.baseUrl, ''));

        // load the image for this sheet
        this.add(imageResourceName, route + '/' + resource.data.meta.image, loadOptions, function (res)
        {
            resource.textures = {};

            var frames = resource.data.frames;
            var frameKeys = Object.keys(frames);
            var resolution = core.utils.getResolutionOfUrl(resource.url);
            var batchIndex = 0;

            function processFrames(initialFrameIndex, maxFrames)
            {
                var frameIndex = initialFrameIndex;

                while (frameIndex - initialFrameIndex < maxFrames && frameIndex < frameKeys.length)
                {
                    var frame = frames[frameKeys[frameIndex]];
                    var rect = frame.frame;

                    if (rect)
                    {
                        var size = null;
                        var trim = null;

                        if (frame.rotated)
                        {
                            size = new core.Rectangle(rect.x, rect.y, rect.h, rect.w);
                        }
                        else
                        {
                            size = new core.Rectangle(rect.x, rect.y, rect.w, rect.h);
                        }

                        //  Check to see if the sprite is trimmed
                        if (frame.trimmed)
                        {
                            trim = new core.Rectangle(
                                frame.spriteSourceSize.x / resolution,
                                frame.spriteSourceSize.y / resolution,
                                frame.sourceSize.w / resolution,
                                frame.sourceSize.h / resolution
                            );
                        }

                        // flip the width and height!
                        if (frame.rotated)
                        {
                            var temp = size.width;
                            size.width = size.height;
                            size.height = temp;
                        }

                        size.x /= resolution;
                        size.y /= resolution;
                        size.width /= resolution;
                        size.height /= resolution;

                        resource.textures[frameKeys[frameIndex]] = new core.Texture(res.texture.baseTexture, size, size.clone(), trim, frame.rotated);

                        // lets also add the frame to pixi's global cache for fromFrame and fromImage functions
                        core.utils.TextureCache[frameKeys[frameIndex]] = resource.textures[frameKeys[frameIndex]];
                    }
                    frameIndex++;
                }
            }

            function shouldProcessNextBatch()
            {
                return batchIndex * BATCH_SIZE < frameKeys.length;
            }

            function processNextBatch(done)
            {
                processFrames(batchIndex * BATCH_SIZE, BATCH_SIZE);
                batchIndex++;
                setTimeout(done, 0);
            }

            if (frameKeys.length <= BATCH_SIZE)
            {
                processFrames(0, BATCH_SIZE);
                next();
            }
            else
            {
                async.whilst(shouldProcessNextBatch, processNextBatch, next);
            }
        });
    };
};